4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

node-gyp rebuildのerrorを解決する

Last updated at Posted at 2020-03-21

Node.jsの開発スピードが速すぎて、公開しているNode-REDのライブラリがいつの間にかnpm installできなくなっていました。このライブラリはC++のドライバにアクセスするためNode.jsのC++ Addonを利用していますが、npm install時のnode-gypで失敗しているようでした。V8 API1のトラブルシューティングに関しては、検索してもなかなか情報が見つからず、参考になれば幸いです。

ちなみに、本家のサイト2によるとライブラリの開発には

  • N-API
  • nan
  • direct use of internal V8, libuv and Node.js libraries

の3つがあると書かれていますが、ここで扱うのは3つ目のタイプです。

Node.jsのversion

10.xまでは問題なかったのですが、11.xからエラーが出るようになりました。現在最新の13.11を対象としています(※2020/05/15追記:もう最新ではなくなりました)。ちなみに、11.xからV8のMajor versionが6から7に上がっています。3

#Object->Set()でエラー

Maybe versionになったため、引数にcontextを追加で渡せとのエラーです。Maybe versionの場合は.ToChecked()で返します。4

###ログ

../nodes/***/***_wrap.cc:286:46: error: no matching function for call to v8::Array::Set(int&, v8::Local<v8::Integer>)
     dst_addr->Set(i,Integer::New(isolate,tmp));
                                              ^
In file included from /home/***/.cache/node-gyp/13.11.0/include/node/node.h:67:0,
                 from ../nodes/***/***_wrap.cc:29:
/home/***/.cache/node-gyp/13.11.0/include/node/v8.h:3547:37: note: candidate: v8::Maybe<bool> v8::Object::Set(v8::Local<v8::Context>, v8::Local<v8::Value>, v8::Local<v8::Value>)
   V8_WARN_UNUSED_RESULT Maybe<bool> Set(Local<Context> context,
                                     ^~~
/home/***/.cache/node-gyp/13.11.0/include/node/v8.h:3547:37: note:   candidate expects 3 arguments, 2 provided
/home/***/.cache/node-gyp/13.11.0/include/node/v8.h:3550:37: note: candidate: v8::Maybe<bool> v8::Object::Set(v8::Local<v8::Context>, uint32_t, v8::Local<v8::Value>)
   V8_WARN_UNUSED_RESULT Maybe<bool> Set(Local<Context> context, uint32_t index,
                                     ^~~
/home/***/.cache/node-gyp/13.11.0/include/node/v8.h:3550:37: note:   candidate expects 3 arguments, 2 provided

コード


// 修正前
Local<Array> dst_addr = Array::New(isolate,4);
...
dst_addr->Set(i,Integer::New(isolate,tmp));

// 修正後
Local<Context> context = isolate->GetCurrentContext();
Local<Array> dst_addr = Array::New(isolate,4);
...
dst_addr->Set(context,i,Integer::New(isolate,tmp)).ToChecked();

Object->Set()でエラー その2

別パターンですが、Maybe versionに関するエラーです。同様にcontextを渡して、.ToChecked()で返します。String::NewFromUtf8()の引数、戻り値の型もMaybeLocalに変わったので、引数にNewStringType::kNormalを追加し、.ToLocalChecked()で返します。

ログ

../nodes/***/***_wrap.cc:292:83: error: no matching function for call to v8::Object::Set(v8::MaybeLocal<v8::String>, v8::Local<v8::Integer>)
    obj->Set(String::NewFromUtf8(isolate,"header"),Integer::New(isolate,mac.header));
                                                                                   ^
In file included from /home/***/.cache/node-gyp/13.11.0/include/node/node.h:67:0,
                 from ../nodes/***/***_wrap.cc:29:
/home/***/.cache/node-gyp/13.11.0/include/node/v8.h:3547:37: note: candidate: v8::Maybe<bool> v8::Object::Set(v8::Local<v8::Context>, v8::Local<v8::Value>, v8::Local<v8::Value>)
   V8_WARN_UNUSED_RESULT Maybe<bool> Set(Local<Context> context,
                                     ^~~
/home/***/.cache/node-gyp/13.11.0/include/node/v8.h:3547:37: note:   candidate expects 3 arguments, 2 provided
/home/***/.cache/node-gyp/13.11.0/include/node/v8.h:3550:37: note: candidate: v8::Maybe<bool> v8::Object::Set(v8::Local<v8::Context>, uint32_t, v8::Local<v8::Value>)
   V8_WARN_UNUSED_RESULT Maybe<bool> Set(Local<Context> context, uint32_t index,
                                     ^~~
/home/***/.cache/node-gyp/13.11.0/include/node/v8.h:3550:37: note:   candidate expects 3 arguments, 2 provided

コード

// 修正前
obj->Set(String::NewFromUtf8(isolate,"header"),Integer::New(isolate,mac.header));

// 修正後
obj->Set(context,(String::NewFromUtf8(isolate,"header",NewStringType::kNormal)).ToLocalChecked(),Integer::New(isolate,mac.header)).ToChecked();

BooleanValue()でエラー

BooleanValueの引数が空なので、Isolate* isolateを引数で渡せとのエラーです。

※V8 7.4の前後でエラーの内容が変わるので両対応しています。

ログ

../nodes/***/***_wrap.cc:196:33: error: no matching function for call to v8::Value::BooleanValue()
  latest = args[0]->BooleanValue();
                                 ^
In file included from /home/***/.cache/node-gyp/13.11.0/include/node/node.h:67:0,
                 from ../nodes/***/***_wrap.cc:29:
/home/***/.cache/node-gyp/13.11.0/include/node/v8.h:2771:8: note: candidate: bool v8::Value::BooleanValue(v8::Isolate*) const
   bool BooleanValue(Isolate* isolate) const;
        ^~~~~~~~~~~~
/home/***/.cache/node-gyp/13.11.0/include/node/v8.h:2771:8: note:   candidate expects 1 argument, 0 provided

コード

// 修正前
static void foo(const FunctionCallbackInfo<Value>& args) {
	Isolate* isolate = args.GetIsolate();
	latest = args[0]->BooleanValue();
	args.GetReturnValue().Set(Boolean::New(isolate,true));
	return;
}

// 修正後
static void foo(const FunctionCallbackInfo<Value>& args) {
	Isolate* isolate = args.GetIsolate();
#if (V8_MAJOR_VERSION > 7) || ((V8_MAJOR_VERSION == 7) && (V8_MINOR_VERSION >= 4))
	latest = args[0]->BooleanValue(isolate);
#elif (V8_MAJOR_VERSION >= 7)
	Local<Context> context = isolate->GetCurrentContext();
	latest = args[0]->BooleanValue(context).ToChecked();
#else
	latest = args[0]->BooleanValue();
#endif
	args.GetReturnValue().Set(Boolean::New(isolate,true));
	return;
}

Object->Get()でエラー

Object->Set()と同様。Maybe versionに関するエラー。

###ログ

../nodes/***/***_wrap.cc:449:26: error: no matching function for call to v8::Array::Get(int)
  dst_addr[0] = arr->Get(0)->NumberValue(context).FromMaybe(0);
                          ^
In file included from /home/***/.cache/node-gyp/13.11.0/include/node/node.h:67:0,
                 from ../nodes/***/***_wrap.cc:29:
/home/***/.cache/node-gyp/13.11.0/include/node/v8.h:3594:43: note: candidate: v8::MaybeLocal<v8::Value> v8::Object::Get(v8::Local<v8::Context>, v8::Local<v8::Value>)
   V8_WARN_UNUSED_RESULT MaybeLocal<Value> Get(Local<Context> context,
                                           ^~~
/home/***/.cache/node-gyp/13.11.0/include/node/v8.h:3594:43: note:   candidate expects 2 arguments, 1 provided
/home/***/.cache/node-gyp/13.11.0/include/node/v8.h:3597:43: note: candidate: v8::MaybeLocal<v8::Value> v8::Object::Get(v8::Local<v8::Context>, uint32_t)
   V8_WARN_UNUSED_RESULT MaybeLocal<Value> Get(Local<Context> context,
                                           ^~~
/home/***/.cache/node-gyp/13.11.0/include/node/v8.h:3597:43: note:   candidate expects 2 arguments, 1 provided

###コード

// 修正前
dst_addr[0] = arr->Get(0)->NumberValue(context).FromMaybe(0);

// 修正後
Local<Context> context = isolate->GetCurrentContext();

dst_addr[0] = arr->Get(context,0).ToLocalChecked()->NumberValue(context).FromMaybe(0);

まとめ

Node.jsの10.x(V8 6.8)から11.x(V8 7.0)でV8 APIに大きな変更が入り5 (※2020/05/15追記:予告されていたDeprecatedなAPIを削除した、が正解でした)、全体的にMaybe versionが適用されているAPIでnode-gypエラーが出ていました。V8の文法に慣れず読み解くのに苦労しました。

  1. v8.dev (https://v8.dev)

  2. C++ Addons (https://nodejs.org/api/addons.html#addons_c_addons)

  3. Previous Releases (https://nodejs.org/en/download/releases/)

  4. Use Maybe version of V8 APIs (https://github.com/joyeecheung/node/blob/v8-maybe-doc/CPP_STYLE_GUIDE.md#use-maybe-version-of-v8-apis)
    v8/node deprecated APIs and how to handle them #7 (https://github.com/bcoin-org/bcrypto/issues/7)

  5. V8 API changes (https://docs.google.com/document/d/1g8JFi8T_oAE_7uAri7Njtig7fKaPDfotU6huOa1alds/edit)

4
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?