gyp でネイティブコードプロジェクトのビルドを多環境に対応させる
今回は「gyp でネイティブコードプロジェクトのビルドを多環境に対応させる」です。私がやっていることをメモしておきます。
背景
私は Windows のコードをよく書いていました。ある時から Android、Windows Mobile、Linux、Mac OS X、iOS でも動くように意識して書くようになりました。すぐに、コードをビルドするための各種設定ファイルを用意するのが面倒になりました。Visual Studio、Xcode、Makefile、Android NDK 用 Makefile・・・やっていられませんね。
ビルドツール巡り・・・cmake、scons、waf、そして gyp へ
ビルド設定ファイルを自動生成するためのビルドツールを探してみるとすぐにいくつか出てきました。半年ほど cmake と scons を並行運用していましたが、その中で気に入らない点が出てきました。
- ビルドはできるが Visual Studio、Xcode などのプロジェクトファイルが生成できない
- scons、waf などはこれ
- Visual Studio、Xcode のプロジェクトファイルが生成できるが中身がイマイチ
- プロジェクト間の設定の共有がイマイチ
- Android NDK の export の概念に相当するものがあったりなかったり
- Android NDK に対応していない
- 当時は cmake、scons、waf どれも対応してませんでした
この辺をすべてうまく対応してくれたのが、gyp*1 です。gyp は Google Chrome をはじめとした Google 製クライアントプログラムを中心に利用実績があります*2。Google 日本語入力のベースである mozc なんかもそうですね。node.js*3、その中で動いている v8*4、libuv なんかも gyp でビルドされるようになっています。ただし、gyp のスクリプトはPython 2.4 だと動かない*5ので、Cent OS など Python 2.4 が既定の環境では地味に辛いのですが、手でビルド設定ファイルを書くことに比べればささいな問題です。
gyp をプロジェクトに配置する
gyp はただの Python スクリプト群です。New BSD ライセンスなので、自分のプロジェクトに組み込んでしまうのが楽かもしれません。私の場合は、node.js を参考に以下のようにして運用しています。
- $PROJECT_ROOT/tools/gyp
- gyp 一式を配置する
- $PROJECT_ROOT/build/common.gypi
- 各プロジェクトの共通設定を書く
- Visual Studio のプロジェクト設定、Xcode のプロジェクト設定など
- 各プロジェクトの共通設定を書く
- $PROJECT_ROOT/configure.py
- gyp を呼び出してプロジェクトファイルを生成するスクリプトを書く
- $PROJECT_ROOT/README.md
- ビルド手順を書く
Android NDK 向けのテコ入れ
gyp が生成した Android NDK 用の Makefile でビルドすると、やたらと長いファイル名になってしまうので、私は以下のファイルを一部修正してファイル名が短くなるようにしています。
- $PROJECT_ROOT/tools/gyp/pylib/gyp/generator/android.py
- ComputeAndroidModule で return self.target するようにしている
まとめ
この記事には具体例がありませんが、Github の node.js のコードが何よりも雄弁です。
*1:https://code.google.com/p/gyp/
*2:gyp は Google Chrome などを他環境でビルドするための作られたもので、以前は scons でビルドされていました
*3:以前は waf でビルドされていました
*4:以前は scons でビルドされていました
*5:with など新しい構文を使っているため
Tools to build Google Chrome, gyp and Ninja
先日から yamake というオレオレメイクツールを作っている*1のですが、その直後のとあるツイートで gyp、Ninja というビルドシステムがあるということを知りました。どちらも、Chromium のビルドをより良くするために生まれたようです。知らなかったので、少し調べてみました。
Google がこういったビルドツールの開発に積極的な理由
Google Chrome というブラウザがクロスプラットフォームなブラウザだからだと思います。詳細は、gyp のドキュメントに書かれています。
特に厄介なのが Mac OS X での開発だそうで、Xcode を必ず通さないといけないようです。なので、まずはそれにパスすることを目標とし、それに併せて他を揃えていったらしいです。
gyp
以下の動画が分かりやすいと思います。
gyp 自体はビルドツールではなく、ビルドするための何らかのファイルを生成するビルド補助ツールです。*2ドキュメントとソースコードをチラ見した限りでは、以下のような特徴があるように思えました。
- 記法は JSON 形式っぽいもの
- Visual Studio、Xcode、SCons、Autotools に対応している
- Python で実装されている
依存性解決などはそれぞれの環境でそれなりのものがあるので、中継部分だけを作るという考え方には非常に共感できますが、記法が少しまどろっこしい気がします。ドキュメントにあったサンプル*3を抜粋します。
{ 'target_defaults': { 'defines': [ 'U_STATIC_IMPLEMENTATION', ['LOGFILE', 'foo.log',], ], 'include_dirs': [ '..', ], }, 'targets': [ { 'target_name': 'foo', 'type': 'static_library', 'sources': [ 'foo/src/foo.cc', 'foo/src/foo_main.cc', ], 'include_dirs': [ 'foo', 'foo/include', ], 'conditions': [ [ 'OS==mac', { 'sources': [ 'platform_test_mac.mm' ] } ] ], 'direct_dependent_settings': { 'defines': [ 'UNIT_TEST', ], 'include_dirs': [ 'foo', 'foo/include', ], }, }, ], }
Makefile に比べると、記述すべきことがかなり絞られていることがよく分かります。SCons を使っていたときに思ったのですが、私は文字列を引用符で括ったり、何か記号が多いのは嫌いです。*4
Ninja
少し前に SourceForge.JP からニュースが出ています。
こっちの記事が元ネタですかね。
ドキュメントとソースコードをチラ見した限りでは、以下のような特徴があるように思えました。
- 「とにかく速く」という哲学を持っている
- 記法は make と似ている
- C++ で実装されている
- 並列ビルドに対応しているっぽい
- Visual Studio などを使ったビルドをするには一手間必要になりそう
ドキュメントにあったサンプルを抜粋します。ノリは make に近いと思います。
cflags = -Wall rule cc command = gcc $cflags -c $in -o $out build foo.o: cc foo.c
もう少し調べておきたいこと
自分で書いたコードのビルドはどうにでもできるのですが、何らかのライブラリを利用している場合、そのビルドを取り込む必要があります。大抵のオープンソースプロジェクトでは基本的に Autotools で configure、make するためのファイルが提供されています。しかし、Windows や Mac OS X などに向けたものはなかったり、あったとしても用意されているものの形式はばらつきがあります。Google Chrome ではこれらをどうやって統合しているのでしょうか。というあたりを次回あたりで書いてみようと思います。
*1:yamake is makefile generator from YAML
*2:yamake は Ninja よりも gyp に近いです
*3:GypUserDocumentation - gyp - Project Hosting on Google Code
*4:日本語キーボードでは記号を打つのは面倒ですよね