Search code examples
c++node.jsnode-gypnode.js-addon

Fail to build node c++ addon


I am working on a project that uses stereolab's depth camera ZED to retrieve distance of obstacles. Its SDK is written in C++ and it requires CUDA 6.5. However, I have to integrate this program with another part of project, which is written in nodejs. So I decided to compile ZED code as a node module. I've gone through node addon tutorial. Now I've written the interface, but I got following error after trying to build the project using command "node-gyp configure build". It seems the 'zed' module wasn't built. I have no idea what this error is and I've searched nothing so far. Can someone please give me some directions? Thank you.

gyp info it worked if it ends with ok
gyp info using node-gyp@2.0.2
gyp info using node@0.12.7 | linux | x64
gyp info spawn python2
gyp info spawn args [ '/usr/lib/node_modules/node-gyp/gyp/gyp_main.py',
gyp info spawn args   'binding.gyp',
gyp info spawn args   '-f',
gyp info spawn args   'make',
gyp info spawn args   '-I',
gyp info spawn args   '/Path/to/My/Project/DepthViewer/node_zed_module/build/config.gypi',
gyp info spawn args   '-I',
gyp info spawn args   '/usr/lib/node_modules/node-gyp/addon.gypi',
gyp info spawn args   '-I',
gyp info spawn args   '/home/joe/.node-gyp/0.12.7/common.gypi',
gyp info spawn args   '-Dlibrary=shared_library',
gyp info spawn args   '-Dvisibility=default',
gyp info spawn args   '-Dnode_root_dir=/home/joe/.node-gyp/0.12.7',
gyp info spawn args   '-Dnode_gyp_dir=/usr/lib/node_modules/node-gyp',
gyp info spawn args   '-Dmodule_root_dir=/Path/to/My/Project/DepthViewer/node_zed_module',
gyp info spawn args   '--depth=.',
gyp info spawn args   '--no-parallel',
gyp info spawn args   '--generator-output',
gyp info spawn args   'build',
gyp info spawn args   '-Goutput_dir=.' ]
gyp info spawn make
gyp info spawn args [ 'BUILDTYPE=Release', '-C', 'build' ]
make: Entering directory `/Path/to/My/Project/DepthViewer/node_zed_module/build'
  CXX(target) Release/obj.target/zed/../src/main.o
/bin/sh: 1: -DNODE_GYP_MODULE_NAME=zed: not found
make: [Release/obj.target/zed/../src/main.o] Error 127 (ignored)
  SOLINK_MODULE(target) Release/obj.target/zed.node
/bin/sh: 1: -shared: not found
make: [Release/obj.target/zed.node] Error 127 (ignored)
  COPY Release/zed.node
cp: cannot stat ‘Release/obj.target/zed.node’: No such file or directory
make: *** [Release/zed.node] Error 1
make: Leaving directory `/Path/to/My/Project/DepthViewer/node_zed_module/build'
gyp ERR! build error 
gyp ERR! stack Error: `make` failed with exit code: 2
gyp ERR! stack     at ChildProcess.onExit (/usr/lib/node_modules/node-gyp/lib/build.js:269:23)
gyp ERR! stack     at ChildProcess.emit (events.js:110:17)
gyp ERR! stack     at Process.ChildProcess._handle.onexit (child_process.js:1074:12)
gyp ERR! System Linux 3.13.0-58-generic
gyp ERR! command "node" "/usr/bin/node-gyp" "configure" "build"
gyp ERR! cwd /Path/to/My/Project/DepthViewer/node_zed_module
gyp ERR! node -v v0.12.7
gyp ERR! node-gyp -v v2.0.2
gyp ERR! not ok 

This is my binding.gyp:

{
  "targets": [
    {
      "target_name": "zed",
      "sources": [
        "../src/main.cpp",
      ],
      "include_dirs": [
        "/usr/local/zed/include/",
        "/usr/local/cuda-6.5/include/",
        "../include/"
      ],
    }
  ]
}

This is my package.json:

{
  "name": "zed_depth_viewer",
  "version": "0.0.0",
  "description": "Measure depth with zed sdk",
  "main": "zed_depth.js",
  "private": true,
  "gypfile": true,
  "dependencies": {
    "bindings": "~1.2.1"
  }
}

And following is basically my interface with node: (just started for testing, 'initProgram' is working as 'main' for the project)

void node_main_handle(const FunctionCallbackInfo<Value>& args) {
  Isolate* isolate = Isolate::GetCurrent();
  HandleScope scope(isolate);

  Local<FunctionTemplate> tpl = FunctionTemplate::New(isolate, initProgram);
  Local<Function> fn = tpl->GetFunction();

  // omit this to make it anonymous
  fn->SetName(String::NewFromUtf8(isolate, "initProgram"));

  args.GetReturnValue().Set(fn);
}

void Init(Handle<Object> exports, Handle<Object> module)
{
    NODE_SET_METHOD(module, "exports", node_main_handle);
}

NODE_MODULE(zed, Init) 

An example using this module should be:

var zed = require('bindings')('zed'); //zed.node will be in './build/Release/'
var func = zed();
func();

Not sure if this works, haven't tested it yet. I'm new to nodejs.


Solution

  • It seems from the line /bin/sh: 1: -DNODE_GYP_MODULE_NAME=zed: not found that the compiler cannot be found (it should be something like /usr/bin/g++ instead of /bin/sh). If you want to have custom flags passed to gyp or if you want a specific compiler, your gyp file should like something like this:

    {
      'make_global_settings': [
         ['CXX','/usr/bin/clang++-3.5'],
         ['LINK','/usr/bin/clang++-3.5'],
      ],
      "targets": [
        {
          "target_name": "zed",
          "sources": [
            "../src/main.cpp",
          ],
          "include_dirs": [
            "/usr/local/zed/include/",
            "/usr/local/cuda-6.5/include/",
            "../include/"
          ],
          "link_settings": {
            "libraries": [ // For compiler
              "-requiredlibs",
            ],
            "ldflags": [  // For linker
                "-L</path/to/libs",
                "-Wl,-rpath,path/to/libs",
            ]
          },
          "cflags": [
            "-std=c++11"
          ],
        }
      ]
    }
    

    The above gyp file uses clang (instead of g++) for compilation and linking and sets the correct rpath for the created shared library so you won't need to export the library path every time you want to use your binding!

    For more information this article might be useful!