Node.jsにネイティブビルド環境をインストールする

Windows上のNode.jsプログラム間でnamed-pipesモジュールを使用してプロセス間通信を行い、サーバー側プログラムが終了するときに、クライアントに送信したメッセージが届く前にパイプを閉じないように時間待ちをしたいと考えた。
しかし、以下を読んで、その時間待ち処理を行うには、徹底的なイベント駆動型を踏襲しなければならないことに辟易した。

qiita.com

言語仕様(と言うより、言語思想)に泣かされたことはscalaでもあったが、世の中には同じ思いの人が必ずいるものだ。
ちゃんとsleepを行うためのsleepモジュールが以下に存在した。

github.com

しかし、このsleepモジュールにはネイティブコードが含まれているため、それをビルドするための環境が必要だった。

そこで先ずは以下のWindows用のビルドツールをNode.jsにインストールした。

github.com

以下はnpmでwindows-build-toolsをインストールしたときの画面出力である。

>npm install --global windows-build-tools

> windows-build-tools@1.0.0 postinstall C:\Users\pochi\AppData\Roaming\npm\node_modules\windows-build-tools
> node ./lib/index.js

Downloading BuildTools_Full.exe
[============================================>] 100.0% of 3.29 MB (208.76 kB/s)
Downloading python-2.7.11.msi
[============================================>] 100.0% of 18.64 MB (124.66 kB/s)
Downloaded python-2.7.11.msi. Saved to C:\Users\pochi\.windows-build-tools\python-2.7.11.msi.
Starting installation...
Launched installers, now waiting for them to finish.
This will likely take some time - please be patient!
Waiting for installers... |Successfully installed Python 2.7
Waiting for installers... -Successfully installed Visual Studio Build Tools.
C:\Users\pochi\AppData\Roaming\npm
`-- windows-build-tools@1.0.0
  +-- chalk@1.1.3
  | +-- ansi-styles@2.2.1
  | +-- escape-string-regexp@1.0.5
  | +-- has-ansi@2.0.0
  | | `-- ansi-regex@2.0.0
  | +-- strip-ansi@3.0.1
  | `-- supports-color@2.0.0
  +-- cli-spinner@0.2.5
  +-- debug@2.6.0
  | `-- ms@0.7.2
  +-- fs-extra@1.0.0
  | +-- graceful-fs@4.1.11
  | +-- jsonfile@2.4.0
  | `-- klaw@1.3.1
  `-- nugget@2.0.1
    +-- minimist@1.2.0
    +-- pretty-bytes@1.0.4
    | +-- get-stdin@4.0.1
    | `-- meow@3.7.0
    |   +-- camelcase-keys@2.1.0
    |   | `-- camelcase@2.1.1
    |   +-- decamelize@1.2.0
    |   +-- loud-rejection@1.6.0
    |   | +-- currently-unhandled@0.4.1
    |   | | `-- array-find-index@1.0.2
    |   | `-- signal-exit@3.0.2
    |   +-- map-obj@1.0.1
    |   +-- normalize-package-data@2.3.5
    |   | +-- hosted-git-info@2.1.5
    |   | +-- is-builtin-module@1.0.0
    |   | | `-- builtin-modules@1.1.1
    |   | +-- semver@5.3.0
    |   | `-- validate-npm-package-license@3.0.1
    |   |   +-- spdx-correct@1.0.2
    |   |   | `-- spdx-license-ids@1.2.2
    |   |   `-- spdx-expression-parse@1.0.4
    |   +-- object-assign@4.1.0
    |   +-- read-pkg-up@1.0.1
    |   | +-- find-up@1.1.2
    |   | | `-- path-exists@2.1.0
    |   | `-- read-pkg@1.1.0
    |   |   +-- load-json-file@1.1.0
    |   |   | +-- parse-json@2.2.0
    |   |   | | `-- error-ex@1.3.0
    |   |   | |   `-- is-arrayish@0.2.1
    |   |   | +-- pify@2.3.0
    |   |   | `-- strip-bom@2.0.0
    |   |   |   `-- is-utf8@0.2.1
    |   |   `-- path-type@1.1.0
    |   +-- redent@1.0.0
    |   | +-- indent-string@2.1.0
    |   | | `-- repeating@2.0.1
    |   | |   `-- is-finite@1.0.2
    |   | `-- strip-indent@1.0.1
    |   `-- trim-newlines@1.0.0
    +-- progress-stream@1.2.0
    | +-- speedometer@0.1.4
    | `-- through2@0.2.3
    |   +-- readable-stream@1.1.14
    |   | +-- core-util-is@1.0.2
    |   | +-- inherits@2.0.3
    |   | +-- isarray@0.0.1
    |   | `-- string_decoder@0.10.31
    |   `-- xtend@2.1.2
    |     `-- object-keys@0.4.0
    +-- request@2.79.0
    | +-- aws-sign2@0.6.0
    | +-- aws4@1.5.0
    | +-- caseless@0.11.0
    | +-- combined-stream@1.0.5
    | | `-- delayed-stream@1.0.0
    | +-- extend@3.0.0
    | +-- forever-agent@0.6.1
    | +-- form-data@2.1.2
    | | `-- asynckit@0.4.0
    | +-- har-validator@2.0.6
    | | +-- commander@2.9.0
    | | | `-- graceful-readlink@1.0.1
    | | +-- is-my-json-valid@2.15.0
    | | | +-- generate-function@2.0.0
    | | | +-- generate-object-property@1.2.0
    | | | | `-- is-property@1.0.2
    | | | +-- jsonpointer@4.0.1
    | | | `-- xtend@4.0.1
    | | `-- pinkie-promise@2.0.1
    | |   `-- pinkie@2.0.4
    | +-- hawk@3.1.3
    | | +-- boom@2.10.1
    | | +-- cryptiles@2.0.5
    | | +-- hoek@2.16.3
    | | `-- sntp@1.0.9
    | +-- http-signature@1.1.1
    | | +-- assert-plus@0.2.0
    | | +-- jsprim@1.3.1
    | | | +-- extsprintf@1.0.2
    | | | +-- json-schema@0.2.3
    | | | `-- verror@1.3.6
    | | `-- sshpk@1.10.1
    | |   +-- asn1@0.2.3
    | |   +-- assert-plus@1.0.0
    | |   +-- bcrypt-pbkdf@1.0.0
    | |   +-- dashdash@1.14.1
    | |   | `-- assert-plus@1.0.0
    | |   +-- ecc-jsbn@0.1.1
    | |   +-- getpass@0.1.6
    | |   | `-- assert-plus@1.0.0
    | |   +-- jodid25519@1.0.2
    | |   +-- jsbn@0.1.0
    | |   `-- tweetnacl@0.14.5
    | +-- is-typedarray@1.0.0
    | +-- isstream@0.1.2
    | +-- json-stringify-safe@5.0.1
    | +-- mime-types@2.1.13
    | | `-- mime-db@1.25.0
    | +-- oauth-sign@0.8.2
    | +-- qs@6.3.0
    | +-- stringstream@0.0.5
    | +-- tough-cookie@2.3.2
    | | `-- punycode@1.4.1
    | +-- tunnel-agent@0.4.3
    | `-- uuid@3.0.1
    +-- single-line-log@1.1.2
    | `-- string-width@1.0.2
    |   +-- code-point-at@1.1.0
    |   `-- is-fullwidth-code-point@1.0.0
    |     `-- number-is-nan@1.0.1
    `-- throttleit@0.0.2

ご覧の通り、Visual C++ Build ToolsPythonを自動でインストールすると言うすぐれものだった。
なお、windows-build-toolsをインストールするためにはNode.jsのバージョンが4以上でなければならないので注意して欲しい。

これでsleepをインストールすることができるようになった。
(※以下の「npm install」の前に「npm init」を忘れずに。)

C:\Users\pochi\nodejs\sleep_test>npm install sleep --save

> sleep@5.0.0 install C:\Users\pochi\nodejs\sleep_test\node_modules\sleep
> node-gyp rebuild


C:\Users\pochi\nodejs\sleep_test\node_modules\sleep>if not defined npm_config_node_gyp (node "C:\Program Files\nodejs\node_modules\npm\bin\node-gyp-bin\\..\..\node_modules\node-gyp\bin\node-gyp.js" rebuild )  else (node "" rebuild )
このソリューション内のプロジェクトを 1 度に 1 つずつビルドします。並行ビルドを有効にするには、"/m" スイッチを追加してください。
  sleep.cc
  win_delay_load_hook.cc
     Creating library C:\Users\pochi\nodejs\sleep_test\node_modules\sl
  eep\build\Release\node_sleep.lib and object C:\Users\pochi\github\study-nodej
  s\calljs\node_modules\sleep\build\Release\node_sleep.exp
  Generating code
  Finished generating code
  node_sleep.vcxproj -> C:\Users\pochi\nodejs\sleep_test\node_modules\
  sleep\build\Release\\node_sleep.node
  node_sleep.vcxproj -> C:\Users\pochi\nodejs\sleep_test\node_modules\
  sleep\build\Release\node_sleep.pdb (Full PDB)
calljs@0.0.0 C:\Users\pochi\nodejs\sleep_test
`-- sleep@5.0.0
  `-- nan@2.5.0

npm WARN calljs@0.0.0 No description
npm WARN calljs@0.0.0 No repository field.

試しにインタラクティブモードでsleepを呼んでみた。

C:\Users\pochi\nodejs\sleep_test>node
> var sleep = require('sleep');
undefined
> sleep.sleep(3);
undefined
>
(To exit, press ^C again or type .exit)
>

「sleep.sleep(3)」で3秒待ってくれた、素晴らしい!

【動作環境】

【参考資料】