Node.jsをBuildする

[公式](https://github.com/nodejs/node/blob/master/BUILDING.md)のドキュメントを読めば環境ごとに必要なtoolとそのversionがわかる。
ここではOSXでの具体的な環境構築手順を、自分がハマった点をメインに補完する。

# Note

初回のビルドには30分〜１時間かかるので、fgで実行する場合は注意

また再ビルドする場合、基本的に`./configure`は実行不要である
これは次のmakeコマンドのためのビルドで（v8のビルドとか走る）

- moduleが追加された
- 環境が変わった

などでなければ時間をかけて再実行する必要はない

また紹介する環境構築をなぞる場合、途中のSoftware UpdateやXcode installで数時間かかり、数GBのディスク容量も必要

# Get Source[^1]

```bash
$git clone git@github.com:nodejs/node.git
# debug目的で特定versionをいじってビルドしたい場合はtagsを利用
$git checkout -b v8.9.4 refs/tags/v8.9.4
```

# Goal

既に自分の環境がビルド条件をクリアしているかもしれないので、時間に余裕があるならいきなりビルドしてみても良さそう

```bash
$./configure > /dev/null
$make -j8 > /dev/null
```

公式では`make -j4`と記載されているが、ここでは8並列で実行（コア数が少なければ同じだが）

上記で標準エラー出力が出れば、いくつかのtoolのversionが足りてない。
自分の場合は下記がでた。

```bash
$./configure > /dev/null
xcode-select: error: tool 'xcodebuild' requires Xcode, but active developer directory '/Library/Developer/CommandLineTools' is a command line tools instance

xcrun: error: unable to lookup item 'PlatformPath' from command line tools installation
xcrun: error: unable to lookup item 'PlatformPath' in SDK '/'
```

結論から言うと、この時点でいくつかのtoolのversionが古かったのだが、それがエラー原因ではなくXcodeをinstallしていないことが原因だった。

> On macOS, you will need to install the Xcode Command Line Tools by running xcode-select --install. Alternatively, if you already have the full Xcode installed, you can find them under the menu Xcode -> Open Developer Tool -> More Developer Tools.... This step will install clang, clang++, and make.

と公式にあり、XcodeがなくてもCLIで代用できそうな雰囲気だが、
以下ではXcodeをinstallして解決するまでの流れを紹介する

# Prepare

[Building Node.js on supported platforms](https://github.com/nodejs/node/blob/master/BUILDING.md#building-nodejs-on-supported-platforms)の「Unix/macOS」を参考にしつつ

## Check
### gcc/g++/clang/clang++/make

```bash
$gcc -dumpversion
4.2.1

$g++ --version
Configured with: --prefix=/Library/Developer/CommandLineTools/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 9.0.0 (clang-900.0.37)
Target: x86_64-apple-darwin16.7.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin

$make --version
GNU Make 3.81
Copyright (C) 2006  Free Software Foundation, Inc.
This is free software; see the source for copying conditions.
There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE.

This program built for i386-apple-darwin11.3.0
```

gccとg++とで確認の仕方を変えているが深い意味はない
`--version`だとclang/clang++のバージョンもわかる

ビルドには`gcc/g++`は4.9.4以上が必要だが、MBP 2016モデルのデフォは`4.2.1`と足りてない
`clang/clang++`は3.4.2以上、`make`は3.81以上が必要だが、これらはクリアしている

### Python

2系が必要
OSがデフォで持ってるpythonは大体２系だが、pythonで開発しているなら3系を使っていると思う
`pyenv`を使うと楽だが、`.python-version`はnodeリポジトリの`.gitignore`に含まれていないので、globalな`.gitignore`を用意

```bash
$cat ~/.gitignore_global
.python-version
$cat ~/.gitconfig
[user]
  name = Daiki Arai
  email = darai0512@yahoo.co.jp
[core]
  excludesfile = ~/.gitignore_global
```
※ PRするなら`.gitconfig`に`user.name`と`user.email`を入れた方が良い


あるいはビルド時のみOSがデフォで持ってるpythonのPATHの優先度をあげるとか

```bash
$/usr/bin/python -V
Python 2.7.10
# PATHの優先度の上げ方は下記でうまくいくとは限らないので注意
$PATH=${PATH}:${PYENV_ROOT}/bin ./configure
```

## Upgrade gcc/g++

実は`4.2.1`でもビルドできるのでこのstepは不要
※ただしいくらかwarningsがでる（openssl/icu-small/v8など）。core moduleの一部が使えないなど何かしら不備がわかったらすぐ更新します

むしろ下記手順で5系を入れて`make`すると失敗する

```bash
$brew install gcc5
# or
$brew upgrade gcc@5

$/usr/local/Cellar/gcc\@5/5.5.0_2/bin/gcc-5 --version
gcc-5 (Homebrew GCC 5.5.0_2) 5.5.0
Copyright (C) 2015 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
$/usr/local/Cellar/gcc\@5/5.5.0_2/bin/g++-5 -dumpversion
5.5.0

$which gcc
/usr/bin/gcc
$which g++
/usr/bin/g++
$ln -s /usr/local/Cellar/gcc\@5/5.5.0_2/bin/gcc-5 /usr/local/bin/gcc
$ln -s /usr/local/Cellar/gcc\@5/5.5.0_2/bin/g++-5 /usr/local/bin/g++

# 必要ならPATHを再読込
$source ~/.bashrc
$gcc -dumpversion
5.5.0

# build
$./configure
$make -j4 > /dev/null
g++: error: unrecognized command line option '-stdlib=libc++'
make[1]: *** [/Users/daiki/workspace/node/out/Release/obj.host/icutools/deps/icu-small/source/tools/toolutil/collationinfo.o] Error 1
make[1]: *** Waiting for unfinished jobs....
unrefdHandle
this._handle.unref
make: *** [node] Error 2
# errorに従って再build
$make -j4 -stdlib=libc++  > /dev/null
make[1]: touch: open: /Users/daiki/workspace/node/out/Release/obj.host/icutools/deps/icu-small/source/common/appendable.o: No such file or directory
make: *** [node] Error 1
```

## Complete?

toolのversionは条件を満たしたはずだが、これでもまだ`./configure`実行時に冒頭のエラーがでる

エラーの`active developer directory '/Library/Developer/CommandLineTools'`は、上述の`g++ --version`などの結果の`InstalledDir: /Library/Developer/CommandLineTools/usr/bin`である。

[xcode-selectのエラー(iOS)](https://qiita.com/teradonburi/items/5b214c74cddd776cb67f#xcode-select%E3%81%AE%E3%82%A8%E3%83%A9%E3%83%BCios)を試すと、

```bash
$xcode-select --install
xcode-select: error: command line tools are already installed, use "Software Update" to install updates
$xcode-select --switch /Applications/Xcode.app
xcode-select: error: invalid developer directory '/Applications/Xcode.app'
```

1つ目よりCLIは入っているが、２つ目よりXcodeはinstallされていないことがわかる

できればCLIだけで解決したかったが、いくらSoftware Updateしても解決しないので、Xcodeをinstall

```bash
$xcode-select --switch /Applications/Xcode.app
xcode-select: error: --switch must be run as root (e.g. `sudo xcode-select --switch <xcode_folder_path>`).
# 上記エラーが出たらsudoで実行
$sudo xcode-select --switch /Applications/Xcode.app
# clang/clang++のInstalledDirを確認
$clang --version
Apple LLVM version 9.0.0 (clang-900.0.39.2)
Target: x86_64-apple-darwin16.7.0
Thread model: posix
InstalledDir: /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin
```

これで`./configure`を実行、成功！

## Complete!!

リポジトリルートにビルド結果のシンボリックリンクが貼られてれば完成！

```bash
$make -j8
$ls -l ./node
lrwxr-xr-x  1 darai  staff  16  3 26 13:25 node -> out/Release/node
```

# Optional
## Openssl

MBP 2016モデルのOSXのデフォルトは0.9.8と古め
[OpenSSL asm support](https://github.com/nodejs/node/blob/master/BUILDING.md#openssl-asm-support)が必要ならupdateする: [opensslのversion]( https://qiita.com/darai0512/items/928cfa52668fb39d3106#openssl%E3%81%AEversion-up)

# ToDo

もうありそうだけど、時間がある時にDocker image作りたい（linuxベースだけど）


[^1]: PR目的ならForkすること: [Pull Requests->Setting up your local environment](https://github.com/nodejs/node/blob/master/doc/guides/contributing/pull-requests.md#setting-up-your-local-environment)