better gyp

仕事でごりごり gyp を使って早くも3年になる。いくつか個人的に痒いところを修正して公開してみた。


修正は以下のとおり。

  1. Android: 非 cygwin でもビルドできるようにした
    1. android: Fix path separator for non-cygwin Windows ndk-build. · 22e62bd · okumura/gyp
  2. Android: *.so をビルドするときの name mangling 規則を緩められるようにした
    1. android: Allow targets to have not strict unmangled names by android_unm... · 0a70b36 · okumura/gyp
  3. Windows: MIDL オプションの ValidateParameters、GenerateTypeLibrary をサポートした
    1. win: Allow support MIDL ValidateParameters and GenerateTypeLibrary. · 879936b · okumura/gyp


ここを見てちゃんとやれば本流に取り込んでもらえるかな?

gyp でネイティブコードプロジェクトのビルドを多環境に対応させる

今回は「gyp でネイティブコードプロジェクトのビルドを多環境に対応させる」です。私がやっていることをメモしておきます。

背景

私は Windows のコードをよく書いていました。ある時から AndroidWindows MobileLinuxMac OS XiOS でも動くように意識して書くようになりました。すぐに、コードをビルドするための各種設定ファイルを用意するのが面倒になりました。Visual StudioXcodeMakefileAndroid NDK 用 Makefile・・・やっていられませんね。

ビルドツール巡り・・・cmake、scons、waf、そして gyp へ

ビルド設定ファイルを自動生成するためのビルドツールを探してみるとすぐにいくつか出てきました。半年ほど cmake と scons を並行運用していましたが、その中で気に入らない点が出てきました。

  1. ビルドはできるが Visual StudioXcode などのプロジェクトファイルが生成できない
    1. scons、waf などはこれ
  2. Visual StudioXcode のプロジェクトファイルが生成できるが中身がイマイチ
    1. cmake では、include ディレクトリがなぜか絶対パスだったりした
  3. プロジェクト間の設定の共有がイマイチ
    1. Android NDK の export の概念に相当するものがあったりなかったり
  4. Android NDK に対応していない
    1. 当時は cmake、scons、waf どれも対応してませんでした

この辺をすべてうまく対応してくれたのが、gyp*1 です。gyp は Google Chrome をはじめとした Google 製クライアントプログラムを中心に利用実績があります*2Google 日本語入力のベースである 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 を参考に以下のようにして運用しています。

  1. $PROJECT_ROOT/tools/gyp
    1. gyp 一式を配置する
  2. $PROJECT_ROOT/build/common.gypi
    1. 各プロジェクトの共通設定を書く
      1. Visual Studio のプロジェクト設定、Xcode のプロジェクト設定など
  3. $PROJECT_ROOT/configure.py
    1. gyp を呼び出してプロジェクトファイルを生成するスクリプトを書く
  4. $PROJECT_ROOT/README.md
    1. ビルド手順を書く

Android NDK 向けのテコ入れ

gyp が生成した Android NDK 用の Makefile でビルドすると、やたらと長いファイル名になってしまうので、私は以下のファイルを一部修正してファイル名が短くなるようにしています。

  1. $PROJECT_ROOT/tools/gyp/pylib/gyp/generator/android.py
    1. 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ドキュメントとソースコードをチラ見した限りでは、以下のような特徴があるように思えました。


依存性解決などはそれぞれの環境でそれなりのものがあるので、中継部分だけを作るという考え方には非常に共感できますが、記法が少しまどろっこしい気がします。ドキュメントにあったサンプル*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 するためのファイルが提供されています。しかし、WindowsMac OS X などに向けたものはなかったり、あったとしても用意されているものの形式はばらつきがあります。Google Chrome ではこれらをどうやって統合しているのでしょうか。というあたりを次回あたりで書いてみようと思います。

*1:yamake is makefile generator from YAML

*2:yamake は Ninja よりも gyp に近いです

*3:GypUserDocumentation - gyp - Project Hosting on Google Code

*4:日本語キーボードでは記号を打つのは面倒ですよね