Homebrewでnode.jsを使うときはXcodeをインストールしないと大変なことになる件

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

はじめに

Homebrewは非常に便利なツールです。Macで開発をする際には、ほぼ必須と行っても過言ではありません。

ただ、そんなHomebrewとうまくつきあっていかないとひどい目に遭うよと言った話になります。

結論

Homebrew経由でnode.jsを入れるときはXcodeを入れる必要があります。

JavaScriptなのに、Xcodeのインストール?と思われるかもしれませんが、
痛い目を見たくないならばXcodeの導入がおすすめです。

もし、HDDの容量を節約したいといった願いがあるならば、nodebrew経由で入れる必要があります。

以下はnodebrew経由で入れずに痛い目を見たといった話と、nodebrew経由で入れる方法になります。
Xcodeを入れる予定があるならば、先にXcodeを導入することで以下の内容は不要になります。

痛い目を見てみる

Homebrew + Command Line Toolsのみが入っている環境で、node.jsを入れて、その後痛い目を見てみます。

なお、Homebrew + Command Line Toolsの導入に関しては省略します。

Homebrew経由でnode.jsをインストール

$ brew install node
==> Downloading https://downloads.sf.net/project/machomebrew/Bottles/node-0.10.31.mavericks.bottle.3.tar.gz
Already downloaded: /Library/Caches/Homebrew/node-0.10.31.mavericks.bottle.3.tar.gz
==> Pouring node-0.10.31.mavericks.bottle.3.tar.gz
==> Caveats
Bash completion has been installed to:
  /usr/local/etc/bash_completion.d
==> make install
==> /usr/local/bin/npm install --global npm@latest --prefix /usr/local
==> Summary
  /usr/local/Cellar/node/0.10.31: 1678 files, 19M
$ node -v
v0.10.31

ここまでは、問題なくnodeがインストールできました。

最近流行のgulpを動かして見たいと思い、gulpのインストールを実施します。

$ sudo npm install -g gulp
(中略)
gulp@3.8.7 /usr/local/lib/node_modules/gulp
├── tildify@0.2.0
├── interpret@0.3.2
├── pretty-hrtime@0.2.0
├── deprecated@0.0.1
├── archy@0.0.2
├── minimist@0.2.0
├── chalk@0.5.0 (escape-string-regexp@1.0.1, ansi-styles@1.1.0, supports-color@0.2.0, has-ansi@0.1.0, strip-ansi@0.3.0)
├── semver@3.0.1
├── orchestrator@0.3.0 (sequencify@0.0.7, events@1.0.2, execify@0.0.3)
├── vinyl-fs@0.3.0 (map-stream@0.1.0, graceful-fs@3.0.2, lodash.defaults@2.4.1, mkdirp@0.5.0, through2@0.5.1, strip-bom@0.3.0, through2-map@1.4.0, glob-watcher@0.0.6, vinyl@0.2.0, glob-stream@3.1.15)
├── liftoff@0.12.0 (extend@1.2.1, minimist@0.1.0, resolve@0.7.4, findup-sync@0.1.3)
└── gulp-util@3.0.1 (lodash._reinterpolate@2.4.1, dateformat@1.0.8-1.2.3, minimist@1.1.0, multipipe@0.1.0, through2@0.6.1, lodash.template@2.4.1, lodash@2.4.1, vinyl@0.4.0)

少し、時間がかかりそうだったのでgulpのインストールはコマンドを実行後、
結果を見た感じインストールができたように見えます。

その後、弊社たいがの記事を参考にしながらgulpのタスクを分割し、
分割したタスクを実行するといったことを実行したいと思います。

[Gulp.js] タスク単位のファイル分割 | Developers.IO

プロジェクト作成

mkdir gulpSample
cd gulpSample
mkdir gulp-task
npm install --save-dev recursive-readdir
npm install --save-dev gulp

gulp-task/task1.js

module.exports = function(gulp) {
    var taskName       = 'task1';
    gulp.task(taskName, function () {
        console.log(taskName + 'run');
    });
};

gulp-task/task2.js

module.exports = function(gulp) {
    var taskName       = 'task2';
    gulp.task(taskName, function () {
        console.log(taskName + 'run');
    });
};

gulpfile.js

ar gulp      = require('gulp');
var recursive = require('recursive-readdir');

gulp.task('recursiveTask', function(callback) {
    recursive('./gulp-task', function (err, files) {
        files.forEach(function(path, index, arry) {
            path = './' + path.replace('\\', '/' );
            console.log(path);
            require(path)(gulp);
        });
        callback();
    });
});

gulp.task('default', ['recursiveTask'], function() {
    gulp.start(['task1', 'task2']);
});

作成したgulpを実行してみます。

$ gulp
[00:54:04] Using gulpfile ~/Project/gulpSample/gulpfile.js
[00:54:04] Starting 'recursiveTask'...
./gulp-task/task1.js
./gulp-task/task2.js
[00:54:04] Finished 'recursiveTask' after 3.34 ms
[00:54:04] Starting 'default'...
[00:54:04] Finished 'default' after 289 μs

きちんとgulpが動いているように見えますが、task1.js task2.jsに記載した内容がまったく動いておりません。

こうなったら大変。タスクが悪いのか、nodeが悪いのか、環境が悪いのか。
タスクは以前別の環境では動いていたのだからとなるものだから、何を疑っていいのやら。
途方に暮れることになることは容易に想像できます。

いったい何が起こっていたのか?

さて、ここでネタばらし gulpをインストールしていたときに実はエラーが出ていました。

$ sudo npm install -g gulp
> node-v8-clone@0.6.2 install /usr/local/lib/node_modules/gulp/node_modules/gulp-util/node_modules/vinyl/node_modules/node-v8-clone
> node-gyp rebuild

xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance

xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance

  CXX(target) Release/obj.target/clone/src/clone.o
  SOLINK_MODULE(target) Release/clone.node
  SOLINK_MODULE(target) Release/clone.node: Finished
/usr/local/bin/gulp -> /usr/local/lib/node_modules/gulp/bin/gulp.js
gulp@3.8.7 /usr/local/lib/node_modules/gulp
├── tildify@0.2.0
├── interpret@0.3.2
├── pretty-hrtime@0.2.0
├── deprecated@0.0.1
├── archy@0.0.2
├── minimist@0.2.0
├── chalk@0.5.0 (escape-string-regexp@1.0.1, ansi-styles@1.1.0, supports-color@0.2.0, strip-ansi@0.3.0, has-ansi@0.1.0)
├── semver@3.0.1
├── orchestrator@0.3.0 (sequencify@0.0.7, events@1.0.2, execify@0.0.3)
├── vinyl-fs@0.3.0 (map-stream@0.1.0, graceful-fs@3.0.2, lodash.defaults@2.4.1, mkdirp@0.5.0, through2-map@1.4.0, through2@0.5.1, vinyl@0.2.0, strip-bom@0.3.0, glob-watcher@0.0.6, glob-stream@3.1.15)
├── liftoff@0.12.0 (extend@1.2.1, minimist@0.1.0, resolve@0.7.4, findup-sync@0.1.3)
└── gulp-util@3.0.1 (lodash._reinterpolate@2.4.1, dateformat@1.0.8-1.2.3, minimist@1.1.0, multipipe@0.1.0, through2@0.6.1, lodash.template@2.4.1, lodash@2.4.1, vinyl@0.4.0)

エラーメッセージを読めばわかるのですが、xcodebuildというツールがXcodeを求めており、
正しくビルドができていないことがわかります。

ただ、npm installとしてはエラーとならないため、
gulpはインストールできたものと勘違いしてしまいやすい状態になっていることもわかります。

Xcodeを入れずに、正しくgulpが動く環境を構築する。

最初に書きましたが、Xcodeを入れずにgulpが動く環境を構築するには、
nodebrewを用いることで構築することができます。

(brew 経由で入れたnodeをアンインストール)
$ brew uninstall node
Uninstalling /usr/local/Cellar/node/0.10.31...
(アンインストールされたことを確認)
$ node -v
zsh: command not found: node
$ brew install nodebrew
(パスに追記するよう言ってくるので対応を実施 以下はbashの場合)
$ echo 'export PATH="$HOME/.rbenv/bin:/usr/local/bin:$PATH"' >> ~/.bash_profile
$ exec -l $SHELL
$ nodebrew install v0.10.31
$ nodebrew use v0.10.31
$ sudo npm install -g gulp
gulp@3.8.7 /Users/KAJIWARAYutaka/.nodebrew/node/v0.10.31/lib/node_modules/gulp
├── tildify@0.2.0
├── interpret@0.3.6
├── pretty-hrtime@0.2.1
├── deprecated@0.0.1
├── archy@0.0.2
├── minimist@0.2.0
├── semver@3.0.1
├── chalk@0.5.1 (escape-string-regexp@1.0.1, ansi-styles@1.1.0, supports-color@0.2.0, has-ansi@0.1.0, strip-ansi@0.3.0)
├── orchestrator@0.3.7 (sequencify@0.0.7, stream-consume@0.1.0, end-of-stream@0.1.5)
├── gulp-util@3.0.1 (lodash._reinterpolate@2.4.1, dateformat@1.0.8-1.2.3, minimist@1.1.0, through2@0.6.1, vinyl@0.4.2, multipipe@0.1.1, lodash@2.4.1, lodash.template@2.4.1)
├── vinyl-fs@0.3.7 (graceful-fs@3.0.2, mkdirp@0.5.0, strip-bom@1.0.0, through2@0.6.1, vinyl@0.4.2, glob-stream@3.1.15, glob-watcher@0.0.6, lodash@2.4.1)
└── liftoff@0.12.1 (extend@1.3.0, resolve@0.7.4, findup-sync@0.1.3)
$ gulp
[01:34:00] Using gulpfile ~/Project/gulpSample/gulpfile.js
[01:34:00] Starting 'recursiveTask'...
./gulp-task/task2.js
./gulp-task/task1.js
[01:34:00] Finished 'recursiveTask' after 3.75 ms
[01:34:00] Starting 'default'...
[01:34:00] Finished 'default' after 258 μs

まとめ

環境を新しく構築した際に、Xcodeのインストールを渋ったたため、このような大捜索になってしまいました。

HDDの容量との相談にはなるとは思いますが、
Xcodeを入れておいた方が開発環境構築時のハマりポイントを減らすことができるのかもしれません。

同様の事例にハマった方がこのブログを見て、解消することができたのならば幸いです。

  • Hiroki Kondo

    nodebrewも入れてみたのですが、結局XCodeをインストールしないといけないエラーは解決できませんでした。
    nodebrewでインストールしたnodeはv4.2.1です。