🔨

ビルドシステム GN のコマンドラインツールで構造を把握する

2024/11/05に公開

はじめに

gn コマンドを利用して、GN で構築されたビルドシステムの依存関係や設定などの情報を取得する方法について記述します。あるファイルがどのような手順でビルドされているか、あるいはそのファイルがビルドに使用されているかどうかを知る手がかりになります。

説明は最小限です。逆引きのような記事構成にしているので、詳細は gn help してください。

前提

GN とは

Makefile 、Ninja と比較してより高レベルなビルドシステムで、役割は CMake とだいたい同じ。強い抽象化構文を持ち、V8, Skia, Chromium など C++ をベースとした Google の大規模な repository で使われている。

環境について

サンプルは Chromium 上の実行結果を記載しています。gn, ninja のバージョンは以下。

$ gn --version
2124 (e4702d740906)
$ ninja --version
1.11.1

GN

(gn path) ターゲット間の依存関係を調べる

ファイルを書き換えたが反映されている気がしない…ときに本当にビルド対象かどうかチェックするために使うことが多い。

gn path . //xxx/yyy:zzz //aaa/bbb:ccc

引数に指定する2つの順序は問わない。常にビルドされる順番で表示される。

$ gn path out/and-release/ //components/embedder_support/android:view_java //content/shell/android:content_shell_apk
//content/shell/android:content_shell_apk --[public]-->
//content/shell/android:content_shell_apk__java --[private]-->
//content/shell/android:content_shell_apk_java --[private]-->
//components/embedder_support/android:view_java

Showing one of 3 "interesting" non-data paths. 0 of them are public.
Use --all to print all paths.

依存関係にない場合は何も表示されない。exitcode は 0 を返し失敗しない。

$ gn path out/and-release/ //components/crash/android:java //components/embedder_support/android:view_java
No non-data paths found between these two targets.
$ echo $?
0

パスが複数存在する場合、最短経路が出力される。

(gn refs) ソースファイルがどのターゲットから依存されているか列挙する

gn refs . //aaa/bbb.cc

$ gn refs out/and-release/ //components/embedder_support/android/java/src/org/chromium/components/embedder_support/view/ContentViewRenderView.java
//components/embedder_support/android:view_java__compile_java
//components/embedder_support/android:view_java__errorprone
//components/embedder_support/android:view_java__header
//components/embedder_support/android:view_jni_headers

gn 引数の設定によりそのファイルがビルドされないなど、依存がない場合は失敗する。

# gn refs out/and-release/ //chromeos/startup/startup.cc
The input matches no targets, configs, or files.
# echo $?
1

(gn refs --all) そのファイルまたはターゲットがどのターゲットから依存されているかすべて列挙する

間接的に依存されているターゲットも列挙する。
依存されているかどうか調べたいターゲットが既に分かっているときは、gn analyze を使う。gn refs --all を使うときはターゲット名が知らない時なので、 grep と併せて使いがち。

gn refs . --all --type=action //aaa/bbb.cc
gn refs . --all --type=action //xxx/yyy:zzz

$ gn refs out/and-release/  --all --type=action //ui/android:ui_full_java \
  | grep -v test | grep _apk__create
//chrome/android:chrome_public_apk__create
//chrome/android:monochrome_public_apk__create
//content/shell/android:content_shell_apk__create

(gn analyze) ファイルがどのターゲットに影響を与えるかを調べる

あるファイルを書き換えたときに、どのユニットテストが影響を受けるのか調べるために使う。

変更のあったファイルとチェックしたいターゲットを json に記述してコマンドから与えると、指定されたファイルに依存されているターゲットの一覧を取得できる。

gn analyze . /path/to/input.json /path/to/output.json

$ cat /mnt/work/gn_analyze_input_path.json 
{
  "files": [
    "//components/translate/content/browser/partial_translate_manager.cc"
  ],
  "test_targets": [
    "//chrome/android:chrome_public_apk",
    "//content/shell/android:content_shell_apk"
  ]
}
$ gn analyze out/and-release/ /mnt/work/gn_analyze_input_path.json -
{"compile_targets":[],"status":"Found dependency","test_targets":["//chrome/android:chrome_public_apk"]}

(gn desc deps) ターゲットのビルドに必要な前提となるターゲットをすべて列挙する

gn desc は、指定されたターゲットの詳細を表示するツール。さらに <what to show> を記述すると、それに関する情報のみを表示する。

deps はどのターゲットでも利用可能。--allを付けると、依存するターゲットをすべて列挙する。

gn desc . //xxx/yyy:app deps --all --type=action

$ gn desc out/and-release/ //components/embedder_support/android:view_java deps --all -type=action | grep __host
//base:base_java__host
//base:process_launcher_java__host
//build/android:build_java__host
//cc/mojom:mojom_java__host
//components/attribution_reporting:mojom_java__host
...

(gn desc) コンパイル時に渡されるマクロ定義などの引数を調べる

include_dirs libs outputs などは、static_library 等の C/C++ 用ターゲットにしか使えない。

gn desc . //xxx/yyy:zzz defines

$ gn desc out/and-release/ //components/translate/content/browser defines
DCHECK_ALWAYS_ON=1
__STDC_CONSTANT_MACROS
__STDC_FORMAT_MACROS
_FORTIFY_SOURCE=2
_GNU_SOURCE
_LIBCPP_ENABLE_SAFE_MODE=1
...

一部の <what to show>--blame が使える。--blame を付けると、どの gn ファイルによってマクロが定義されたのか判定できる。

gn desc out/and-release/ //components/translate/content/browser defines --blame | head -n5
From //build/config:feature_flags
     (Added by //build/config/BUILDCONFIG.gn:332)
  DCHECK_ALWAYS_ON=1
From //build/config/compiler:chromium_code
     (Added by //build/config/BUILDCONFIG.gn:336)

Discussion