Search code examples
c++node.jsv8node-gyp

Make failed while trying to build a nodejs native addon


I am trying to create a native nodejs addon (node v16.19) using node-gyp. The C++ code looks fine, and gives no warnings in my IDE. 'node-gyp configure' runs ok, but when I run 'node-gyp build' I get the stack below. It seems it has something to do with the NODE_SET_METHOD or NODE_MODULE calls I took from this page: https://nodejs.org/docs/latest-v16.x/api/addons.html#factory-of-wrapped-objects

  CXX(target) Release/obj.target/addon/source/index.o
In file included from ../source/index.cc:1:
/home/matthias/.cache/node-gyp/16.19.0/include/node/node.h:887:7: warning: cast between incompatible function types from ‘void (*)(v8::Local<v8::Object>)’ to ‘node::addon_register_func’ {aka ‘void (*)(v8::Local<v8::Object>, v8::Local<v8::Value>, void*)’} [-Wcast-function-type]
  887 |       (node::addon_register_func) (regfunc),                          \
      |       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
/home/matthias/.cache/node-gyp/16.19.0/include/node/node.h:921:3: note: in expansion of macro ‘NODE_MODULE_X’
  921 |   NODE_MODULE_X(modname, regfunc, NULL, 0)  // NOLINT (readability/null_usage)
      |   ^~~~~~~~~~~~~
../source/index.cc:60:3: note: in expansion of macro ‘NODE_MODULE’
   60 |   NODE_MODULE(NODE_GYP_MODULE_NAME, Init)
      |   ^~~~~~~~~~~
In file included from /home/matthias/.cache/node-gyp/16.19.0/include/node/node.h:73:
/home/matthias/.cache/node-gyp/16.19.0/include/node/v8.h: In instantiation of ‘v8::Local<T>::Local(v8::Local<S>) [with S = v8::Value; T = v8::String]’:
../source/index.cc:48:53:   required from here
/home/matthias/.cache/node-gyp/16.19.0/include/node/v8.h:211:42: error: static assertion failed: type check
  211 |     static_assert(std::is_base_of<T, S>::value, "type check");
      |                                          ^~~~~
/home/matthias/.cache/node-gyp/16.19.0/include/node/v8.h:211:42: note: ‘std::integral_constant<bool, false>::value’ evaluates to false
make: *** [addon.target.mk:111: Release/obj.target/addon/source/index.o] Error 1
make: Leaving directory '/home/matthias/projects/client/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:203:23)
gyp ERR! stack     at ChildProcess.emit (node:events:513:28)
gyp ERR! stack     at Process.ChildProcess._handle.onexit (node:internal/child_process:293:12)
gyp ERR! System Linux 5.15.88-2-lts
gyp ERR! command "/home/matthias/.volta/tools/image/node/16.19.0/bin/node" "/usr/bin/node-gyp" "build"
gyp ERR! cwd /home/matthias/projects/client
gyp ERR! node -v v16.19.0
gyp ERR! node-gyp -v v9.3.1
gyp ERR! not ok 

The addon file:

#include <node.h>

namespace main
{
  using v8::Array;
  using v8::Context;
  using v8::Exception;
  using v8::FunctionCallbackInfo;
  using v8::Isolate;
  using v8::Local;
  using v8::Number;
  using v8::Object;
  using v8::String;
  using v8::Value;

  const char *ToCString(Isolate *isolate, Local<String> str)
  {
    String::Utf8Value cvalue(isolate, str);
    return *cvalue ? *cvalue : "<string conversion failed>";
  }

  void Method(const FunctionCallbackInfo<Value> &args)
  {
    Isolate *isolate = args.GetIsolate();
    char *fingerprint = const_cast<char *>(ToCString(isolate, args[0]));
    char *server = const_cast<char *>(ToCString(isolate, args[2]));
    char *remotes = const_cast<char *>(ToCString(isolate, args[3]));
  }

  void Init(Local<Object> exports)
  {
    NODE_SET_METHOD(exports, "myFunction", Method);
  }

  NODE_MODULE(NODE_GYP_MODULE_NAME, Init)
} // namespace main

I had to leave out some parts because of confidentiality.


Solution

  • The macro NODE_SET_METHOD is expanded to the inline function

    inline void NODE_SET_METHOD(v8::Local<v8::Template> recv, const char *name,
                                v8::FunctionCallback callback)
    

    It's first parameter type is v8::Local<v8::Template>. You attempt to pass export of the type v8::Local<v8::Object>. This is a reason of the assertion "type check" failure.

    It's not enough context to make a fix.

    You pass wrong Init to NODE_MODULE. The first one should be

    void Init(v8::Local<v8::Object> exports, v8::Local<v8::Value> module, void* priv);