GYP?と同水準にあるメタビルドツール、GYPよりもシンプル。今ではGYPに代わりGNを使いつつあるようだ。
BUILD.gnを読み込んでビルドする。
なんでGNを使うか
- GYPよりも読みやすい
- 早い
- GYPより20倍速い。
- Ninjaからの要求により起動できる。GNを起動しなければなならない状態であったことを覚えておく必要がない。
- 依存性の強制ができる。
- ビルドグラフ(依存関係の図)を検索できる。
現状は?
2015/8現在 (途中)
ビルドの実行
GYPではDebugとReleaseの両方がつくられるが、GNはしない。自分で設定する、ビルドディレクトリも設定する。
ビルドのセットアップ
ビルドディレクトリの設定
gn gen out/my_build
ビルド引数の設定
gn args out/by_build
これはエディタを起動する。以下のように記述する
is_component_build = true is_debug = false
利用可能な引数と、デフォルト値を見るには以下
gn args --list out/my_build
クロスコンパイルの引数は例は以下
target_os = "chromeos" target_os = "android" target_cpu = "arm" target_cpu = "x86" target_cpu = "x64"
(途中)
descコマンド
状態の表示
gn desc out/my_build
パフォーマンス
以下のコマンドでトレースログを作成。これはChromiumのabout:tracingで読み込める。
gn --tracelog=mylog.trace
練習
実際にターゲットを追加して、Chromiumのソースに変更を加えてみる。 tools/gn/tutorial/BUILD.gnを作成して以下を入力。
executable("hello_world") { sources = [ "hello_world.cc", ] }
hello_world.ccも作成しなきゃならないが、すでにあるはずなので省略。このBUILD.gnは実行ファイルのターゲットhello_worldを定義している。これをchromiumのプロジェクトに含めるためにルート(toolsの一つ上のsrcディレクトリ)のBUILD.gnに以下を追加。
group("root") { deps = [ "//url", "//tools/gn/tutorial:hello_world", ] }
rootグループに属しているターゲットは//urlプロジェクトとhello_worldターゲットに依存する。//はソースのルートを表す。これでビルドしてみる。
gn gen out\hello ninja -C out\hello hello_world
src\out\hello\obj\tools\gn\tutorialに.ninjaファイルが作成され、src\out\hello\hello_world.exeも作成された。
依存性を宣言する
練習の続き。静的ライブラリhelloを作成する。tools/gn/tutorial/BUILD.gnに以下を追加。
static_library("hello") { sources = [ "hello.cc", ] }
executableの方を以下のように修正。
executable("hello_world") { sources = [ "hello_world.cc", ] deps = [ ":hello", ] }
hello_worldはhelloに依存するようになった。ここでは実際には依存していないがスルー。 ビルド
ninja -C out\hello hello_world
必要ならninjaは自動でgnを実行してくれる。
helloライブラリに機能を追加
同時に二人に挨拶できる機能を追加する。TWO_PEOPLEフラグでこの機能をコントロールする。BUILD.gnのhelloを以下のように修正。
static_library("hello") { sources = [ "hello.cc", ] defines = [ "TWO_PEOPLE", ] }
これでgnしてみると、hello.ninjaにdefines = -DTWO_PEOPLEが追加される。しかしhello.hをインクルードしてる他のユーザはこのことを知らないので教える必要がある。その仕組みがconfigと呼ばれる。configはconfigとして独立していて、どこかに依存しているわけではない。hello_configという名前のconfigを作成するには以下のように記述する。
config("hello_config") { defines = [ "TWO_PEOPLE", ] }
これをターゲットに含めるには以下のように記述する。
static_library("hello") { ... configs += [ ":hello_config", ] }
これをやるとdefinesの時と同様に-DTWO_PEOPLEが追加される。
Dependant configs
これで設定をカプセル化したが、使う側はこのコンフィグを設定しないとならない。自動でこのコンフィグを使うには以下のように記述する。
static_library("hello") { sources = [ "hello.cc", ] all_dependent_configs = [ ":hello_config" ] }
これでninjaすると、hello_world.ninjaにも-DTWO_PEOPLEが追加される。
print()とdesc
print()をBUILD.gnに書ける。
static_library("hello") { ... print(configs) }
gn descで出力できる。
gn desc out\debug //tools/gn/tutorial:hello_world gn desc out\debug //tools/gn/tutorial:hello
面白いこともできる。誰がTWO_HELLOを設定したのかを知りたければ以下のようにする。
gn desc out\hello //tools/gn/tutorial:hello_world defines --blame
これはターゲットのフルパスを指定する必要があるようだ。hello_worldのdefineが誰によって指定されたのかを見ることができる。
以下も面白い。
gn desc out\hello //tools/gn/tutorial:hello_world deps
hello_worldが依存しているターゲットを表示。
ターゲットの一覧
gn ls out\hello
Hack
GN自体をビルド
gn自体がchromiumツリーの一部。ビルドできる。
ninja -C out\hello gn
GNのユニットテストを実行
ninja -C out\hello gn_unittests out\hello\gn_unittests.exe
実用コマンド
あるソースファイルがどのターゲットに含まれているかを探す
gn refs out\Default //base/task_scheduler/scheduler_worker_pool_impl.cc //base:base
実行ファイルを生成するターゲットを探す
gn ls out\Default --type=executable //base:base_i18n_perftests //base:base_perftests //base:base_unittests //base:build_utf8_validator_tables //base:check_example //breakpad:dump_syms //cc:cc_perftests //cc:cc_unittests //cc/blink:cc_blink_unittests //chrome:chrome_initial //chrome/chrome_watcher:system_load_estimator_unittests //chrome/install_static:install_static_unittests //chrome/installer/gcapi:gcapi_test //chrome/installer/mini_installer:mini_installer ...
小さそうな実行形式ターゲットをVisual Studio 2015で開く
ターゲット//mash/example/views_examples:views_examples
で実験。
ソリューションファイルを作成。
gn gen --ide=vs --sln=mashviewsexample --filters=//mash/example/* out\Default Generating Visual Studio projects took 17298ms Done. Made 6202 targets from 1344 files in 26003ms
ビルド
ninja -C out\Default mash/example/views_examples:views_examples
作成されたソリューションをVisual Studio 2015で開く。
devenv out\Default\mashviewsexample.sln
devenvプロセスはdepot_toolsにパスが通っていないとならない。これでも500近いプロジェクトを含んでいるので、VSの拡張機能filterを使って読み込むプロジェクトを絞れば速くなる。
GNのビルドフラグを理解する
https://www.chromium.org/developers/gn-build-configuration
ビルドフラグを編集する
gn args out\Default
エディタが起動し現在の設定を確認できる。エディタを閉じると.ninjaを作成しなおす。
設定可能なビルドフラグの一覧
gn args out\Default --list
現在のビルドフラグの設定値(デフォルト含め)の確認
gn args out\Default --list=is_component_build is_component_build Current value (from the default) = true From //build/config/BUILDCONFIG.gn:169
共通のビルドフラグ
is_debug = false
デフォルトはデバッグビルド、falseだとリリース。
is_component_build
コンポーネントビルド? sharedライブラリかどうかtrueならsharedライブラリ
symbol_level
デバッグ時のシンボル作成の深さ。
remove_webcore_debug_symbols
WebCoreは多くのテンプレートを使っており、デバッグシンボルが多くなる。WebCoreのデバッグを考えてないならスキップすべき。 警告:Windowsでは、pdbが見つからないため他のリビルドが動いて逆に遅くなる。
target_cpu
ターゲットCPU