GN Quick Start guide 運行 GN
你可以在命令列裡直接輸入gn運行。因為在depot_tools(路徑應該在你的環境變數PATH中已經設定過)工具目錄中有一個相同名字的指令碼。這個指令碼會找到目前的目錄中的二進位檔案並運行它。 構建一個build
使用GYP時,系統會根據相應的配置參數分別產生Debug和Release編譯目錄。但GN不一樣,你可以任意配置你的編譯參數和組建目錄。編譯時間如果檢測到Ninja檔案需要更新時,也會自動重建。
新產生一個編譯目錄:
gn gen out/my_build
傳入編譯參數
設定編譯目錄的編譯參數:
gn args out/my_build
然後,會彈出一個文字編輯器,像下面這樣輸入編譯參數:
is_component_build = trueis_debug = false
查看所有的參數變數以及他們的預設值:
gn args --list out/my_build
這個命令必須指定編譯目錄,因為不同的目錄有不同的參數值。
Chrome 開發人員還可以參考Chrome-specific build configuration的指示擷取更多資訊。 交叉編譯配置(Cross-compiling to a target OS or architecture)
運行gn args out/Default(用你需要的目錄替換),添加下面的常用的交叉編譯選項中的一個或多個:
target_os = "chromeos"target_os = "android"target_cpu = "arm"target_cpu = "x86"target_cpu = "x64"
更多資訊請參考GNCrossCompiles。 goma 配置
運行gn args out/Default(用你需要的目錄替換)。並添加:
use_goma = truegoma_dir = "~/foo/bar/goma"
如果你的 goma 安裝在預設路徑(~/goma),可以忽略goma_dir參數。 配置 component 模式
運行gn args out/Default並添加:
is_component_build = true
分步詳解
增加一個編譯檔案(BUILD.gn)
建立檔案tools/gn/tutorial/BUILD.gn並輸入:
executable("hello_world") { sources = [ "hello_world.cc", ]}
在目標目錄中應該存在一個hello_world.cc的檔案,包含你期望的內容。現在我們僅僅需要告訴編譯器需要處理這個編譯檔案就行了。開啟根目錄(src)下的BUILD.gn檔案,將新建立的編譯檔案添加到其中一個根group的依賴項中(這裡的每個group是其它目標的一個集合):
group("root") { deps = [ ... "//url", "//tools/gn/tutorial:hello_world", ]}
你可以看到你的目標檔案標籤的前面有一個”//”符號(表示源碼的根目錄,也就是src目錄),後面緊跟具體路徑,再接一個冒號,最後就是你的項目的目標名稱。 測試你新增的工程
在源碼根目錄中,使用命令列操作:
gn gen out/Defaultninja -C out/Default hello_worldout/Default/hello_world
GN 鼓勵對靜態庫使用相同的名字。編譯其中的某個時,你可以將不帶首碼”//”的標籤文本傳給 ninja:
ninja -C out/Default tools/gn/tutorial:hello_world
聲明依賴
現在來構建一個靜態庫,它有一個函數,功能是對任何人說hello。這些都包含在一個hello.cc的檔案中。開啟tools/gn/tutorial/BUILD.gn,將下面的配置靜態庫的文本添加到檔案的最下面:
static_library("hello") { sources = [ "hello.cc", ]}
我再添加一個可執行檔的工程,依賴上面的靜態庫:
executable("say_hello") { sources = [ "say_hello.cc", ] deps = [ ":hello", ]}
這個exe的工程包含一個源檔案並且依賴上面的lib工程。lib是通過exe中的deps依賴項來引入的。你也可以使用全路徑文本//tools/gn/tutorial:hello,但是如果你引入的工程是在同一個build檔案中,你可以使用縮寫:hello。 測試靜態庫
在源碼根目錄中輸入:
ninja -C out/Default say_helloout/Default/say_hello
你不需要再次運行 GN 命令了。當BUILD.gn檔案改變的時候 GN會自動重建 ninja 檔案。你知道的,這通常發生在 ninja 剛運行時,它會列印出[1/1] Regenerating ninja files。 先行編譯設定(Compiler settings)
我們的 hello lib工程有一個新功能,就是可以同時對兩個人說 hello。這個功能是通過宏定義TWO_PEOPLE來控制的。我們可以在工程中這樣添加:
static_library("hello") { sources = [ "hello.cc", ] defines = [ "TWO_PEOPLE", ]}
將一些設定放到config中(Putting settings in a config)
然而,使用lib的工程也需要知道這個預定義,將定義放到lib工程中,僅僅對這個工程中的檔案生效。如果別的工程包含了hello.h,他們是看不到這個定義的。如果要看到這個定義,每個引入這個lib的工程都必須定義TWO_PEOPLE。
GN 有一個”config”的概念,可以將一些設定放在裡面。現在我們來建立一個”config”並將我們需要的預定義宏放到裡面:
config("hello_config") { defines = [ "TWO_PEOPLE", ]}
如何在目標工程中引入這些設定,你只需要在目標的configs選項中將需要的配置羅列出來即可:
static_library("hello") { ... configs += [ ":hello_config", ]}
這個地方你需要使用+=,而不是=,因為每個目標工程構建編譯的都有一系列的預設配置。你要做是將新的配置添加到預設的配置中,而不是全部重寫它。如果需要查看預設的配置,你可以在編譯檔案(BUILD.gn)中使用print函數或者desc命令列子命令(下面的例子都會介紹)。 依賴配置項(Dependent configs)
上面介紹的方法可以很好的封裝我們的配置,但是它仍然需要每個使用lib的工程在他們自己的配置裡去設定。如果每個使用lib的工程可以自動擷取這些配置,那該有多好。現在來改變以下lib的配置:
static_library("hello") { sources = [ "hello.cc", ] all_dependent_configs = [ ":hello_config" ]}
這會將hello_config的配置應用到hello工程本身,以及所有依賴(所有繼承,包含間接依賴)hello的工程。現在每個依賴我們的lib的工程都會擷取這些配置。你也可以設定public_configs來設定只應用到直接依賴的目標項目中(不傳遞)。
現在,如果你編譯並啟動並執行話,你將會看到兩個人的新版本:
> ninja -C out/Default say_helloninja: Entering directory 'out/Default'[1/1] Regenerating ninja files[4/4] LINK say_hello> out/Default/say_helloHello, Bill and Joy.
添加一個新的編譯參數
你可以通過declare_args直接聲明你接受的參數並指定它們的預設值。
declare_args() { enable_teleporter = true enable_doom_melon = false}
使用gn help buildargs來擷取它們工作原理的概述。使用gn help declare_args擷取聲明參數的細節。
It is an error to declare a given argument more than once in a given scope, so care should be used in scoping and naming arguments. 不知道發生了什麼。(Don‘t know what’s going on?)
你可以運行 GN 的 verbose 模式,會看到很多關於當前發生的資訊。使用-v啟用。 列印調試資訊
有一個print的命令,可以輸出到 stdout:
static_library("hello") { ... print(configs)}
這會列印出應用到目標項目的所有配置資訊(包括預設的)。 “desc”命令
你可以運行gn desc <build_dir> <targetname>擷取指定目標的資訊。
gn desc out/Default //tools/gn/tutorial:say_hello
這會列印出很多我們想要的資訊。你也可以只列印一項。現在來告訴你,如何知道目標工程say_hello中的TWO_PEOPLE宏定義在什麼地方:
> gn desc out/Default //tools/gn/tutorial:say_hello defines --blame...lots of other stuff omitted... From //tools/gn/tutorial:hello_config (Added by //tools/gn/tutorial/BUILD.gn:12) TWO_PEOPLE
你可以看見TWO_PEOPLE是通過一個 config 來定義的,你也可以知道是哪行將config應用到目標工程的(在這裡,是all_dependent_configs那行)。
兩外一個特別有趣的命令:
gn desc out/Default //base:base_i18n deps --tree
參考gn help desc擷取詳情。 效能(Performance)
You can see what took a long time by running it with the –time command line flag. This will output a summary of timings for various things.
You can also make a trace of how the build files were executed:
gn --tracelog=mylog.trace
and you can load the resulting file in Chrome’s about:tracing page to look at everything.