node-gyp と grpc のインストールは正直やっかい

かなり広範囲のライブラリで採用されていながら環境依存が激しいこのnode-gypgrpc。macOSでは最新版node.jsでは動かないのがやっかいなところ。つまり、昔は最新版で問題なかったのです。(私がタイトルに〇〇年×月とつけているのはそのためです。)

node-gypgrpcは数多くのライブラリ、フレームワークで採用されているため、前提としてnpm install -gされているよね?という暗黙の前提があったりします。
おかげでとあるフレームワークのインストールで手順通りに

$ npm i s xxxxxx

とやると、node-gyp rebuildでエラーやTried to download(403): https://storage.googleapis.com/grpc-precompiled-binaries/node/grpc/v1.10.1/node-v64-darwin-x64-unknown.tar.gzからの長大なエラーメッセージに高確率で遭遇してしまいます。

対象環境

OS: macOS High Sierra 10.13.6

インストールが成功した動作確認環境は上記です。もしかしたら、macのバージョンが違えば成功するnodeのバージョンも違うかもしれません。
またUbuntuなどのlinuxでも問題解決のヒントになるかもです。

保険のためには nvm 必須

OSのバージョンとnodeのバージョンの組み合わせに激しく依存するため自分の環境でうまくいくようにアレコレするためにはnvmが必須です。
まず、トライ&エラーをする保険として nvm のインストールをしておきましょう。
その前に、brew installしてあるnodeは全て削除、です。

$ brew uninstall --force node

以下のコマンドでnvmの最新版をインストールします。

$ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.34.0/install.sh | bash

インストールが終わったら、ターミナルを再起動するか、~/.bashrcsourceします。

$ . ~/.bashrc

node-gyp の解決

まず、brew install nodeで入ってくるnode11系です。
brew install nodenodeを入れた後、node-gyp をインストールする
もしくは、node-gyp を依存性に含むライブラリをインストールするとrebuildに失敗したという長大なエラーメッセージが吐き出されるかもしれません。

そんな時は、以下のissueをご覧ください。ちょっと古いissueですがここでの議論は今でも現役です。

上記のissueで成功している方のポイントは、
1. グローバルに入れておいた方がいい。
2. 単独でインストールした方がいい。
3. 管理権限でインストールした方がいいかも。
4. node 8 系ならバッチリ?
です。
要点を念頭に入れつつ、8系はさすがに古いので一旦、nodeのLTSバージョンをインストールしてみます。

$ nvm install --lts

上記コマンドでnodeのLTS版(今は10.15.3)をインストール&使用します。
そして以下のコマンドで node-gypをインストールします。

$ npm i g node-gyp
+ node-gyp@3.8.0
+ g@2.0.1
added 1 package from 1 contributor, removed 3 packages, updated 1 package and audited 874057 packages in 32.282s
found 1 high severity vulnerability
run `npm audit fix` to fix them, or `npm audit` for details

あら!?自分の環境ではLTS版ですんなりインストールできました。
(UbuntuではPython2.7入れておかないと必ず失敗します。node-gypはPython3系は未サポートのはずなので。自分のmac環境ではPython3なのでダメかと思っていたんですけど・・・? ま、まぁ、よしとします。)

node-grpcの解決

毎度の事ですが、brew install nodeで入ってくるnode11系です。その状態で、grpcのインストールをすると・・・

$ npm i s grpc
> grpc@1.19.0 install /opt/xxxxx/node_modules/grpc
> node-pre-gyp install --fallback-to-build --library=static_library

node-pre-gyp WARN Using request for node-pre-gyp https download 
[grpc] Success: "/opt/xxxxx/node_modules/grpc/src/node/extension_binary/node-v67-darwin-x64-unknown/grpc_node.node" is installed via remote

はい、すんなり入りました。ここで指定しているのは最新版grpc@1.19.0です。
つまりnode@11grpc@1.19.0はOKです。
もし、grpc@1.19.0より下のバージョンに依存したライブラリがあった場合・・・?

$ npm i s xxxxx
> grpc@1.10.1 install /opt/xxxxx/node_modules/grpc
> node-pre-gyp install --fallback-to-build --library=static_library

node-pre-gyp ERR! Tried to download(403): https://storage.googleapis.com/grpc-precompiled-binaries/node/grpc/v1.10.1/node-v67-darwin-x64-unknown.tar.gz node-pre-gyp ERR! Pre-built binaries not found for grpc@1.10.1 and node@11.10.1 (node-v67 ABI, unknown) (falling back to source compile with node-gyp) node-pre-gyp ERR! Pre-built binaries not installable for grpc@1.10.1 and node@11.10.1 (node-v67 ABI, unknown) (falling back to source compile with node-gyp) node-pre-gyp ERR! Hit error Connection closed while downloading tarball file CXX(target) Release/obj.target/grpc/deps/grpc/src/core/lib/surface/init.o
CXX(target) Release/obj.target/grpc/deps/grpc/src/core/lib/surface/init.o
rm: ./Release/.deps/Release/obj.target/grpc/deps/grpc/src/core/lib/surface/init.o.d.raw: No such file or directory
make: *** [Release/obj.target/grpc/deps/grpc/src/core/lib/surface/init.o] Error 1
gyp ERR! build error 

はい、node@11grpc@1.10.1NGなんです!!

そこでこちらの issue が役に立ちます。

上記のissueで成功している方のポイントは、
1. unsafe-permでインストールした方がいいかも?!
2. node 8 系ならバッチリ?
という点です。node-gypと同様、8系は古いのでLTS版から行ってみます。

node LTS バージョン

nvmからLTSバージョンを有効にします。

$ nvm use --lts

続いて、grpcをインストールしてみます。

$ sudo npm install -g --unsafe-perm=true grpc@1.10.1
> grpc@1.10.1 install /Users/yoshinori/.nvm/versions/node/v10.15.3/lib/node_modules/grpc
> node-pre-gyp install --fallback-to-build --library=static_library

node-pre-gyp ERR! Tried to download(403): https://storage.googleapis.com/grpc-precompiled-binaries/node/grpc/v1.10.1/node-v64-darwin-x64-unknown.tar.gz node-pre-gyp ERR! Pre-built binaries not found for grpc@1.10.1 and node@10.15.3 (node-v64 ABI, unknown) (falling back to source compile with node-gyp) node-pre-gyp ERR! Pre-built binaries not installable for grpc@1.10.1 and node@10.15.3 (node-v64 ABI, unknown) (falling back to source compile with node-gyp) node-pre-gyp ERR! Hit error Connection closed while downloading tarball file CXX(target) Release/obj.target/grpc/deps/grpc/src/core/lib/surface/init.o
CXX(target) Release/obj.target/grpc/deps/grpc/src/core/lib/surface/init.o
...

やっぱりダメみたいです。。。

node 8版で再チャレンジ

不本意ながら8系で行ってみます。nvmから8をインストール、そしてgrpcをインストールしてみましょう。

$ nvm install 8
Downloading and installing node v8.15.1...
Downloading https://nodejs.org/dist/v8.15.1/node-v8.15.1-darwin-x64.tar.xz...
######################################################################### 100.0%
Computing checksum with shasum -a 256
Checksums matched!
Now using node v8.15.1 (npm v6.4.1)
$ sudo npm install -g --unsafe-perm=true grpc@1.10.1
> grpc@1.10.1 install /Users/xxxx/.nvm/versions/node/v8.15.1/lib/node_modules/grpc
> node-pre-gyp install --fallback-to-build --library=static_library

[grpc] Success: "/Users/xxxx/.nvm/versions/node/v8.15.1/lib/node_modules/grpc/src/node/extension_binary/node-v57-darwin-x64-unknown/grpc_node.node" is installed via remote
+ grpc@1.10.1
added 129 packages from 97 contributors in 20.682s

よっしー!いけました。

そんなわけで node-gypgrpcがどちらも動く環境は・・・node 8じゃないとダメなん?

まとめ

node-gypgrpcなどのようにビルドがうまくいかないライブラリは割と多いです。
バージョンのホンのちょっとした違いでうまくいく/いかないがあるので、諦めずに要点を踏まえた上でトライ&エラーしてみましょう! (闇雲にトライ&エラーはダメです!)