GN
使用gn編譯項目的過程:
-
編寫.gn文件
模塊化各個模塊藻雪,分別寫一個build.gn,添加進主目錄的build.gn的依賴中狸吞。
gn gen out/Default
ninja -C out/Default base
1. Ninja
ninja一個構(gòu)建系統(tǒng)勉耀,它以文件(通常是源代碼和輸出可執(zhí)行文件)的相互依賴性為輸入指煎,并快速地構(gòu)建它們。Ninja通過將編譯任務并行組織瑰排,大大提高了構(gòu)建速度贯要。
源于在Chromium瀏覽器項目中的工作暖侨,該項目具有30,000多個源文件椭住,并且其其他構(gòu)建系統(tǒng)(包括從自定義非遞歸Makefile構(gòu)建的一個)在更改一個文件后將需要十秒鐘才能開始構(gòu)建。 而用ninja構(gòu)建不到一秒鐘字逗。
1.1 設計目標
- 即使是非常大的項目京郑,也可以非常快速(即即時)的增量構(gòu)建葫掉。
- 關于如何構(gòu)建代碼的選擇很少些举。對于不同項目,可能有不同的構(gòu)建策略俭厚,ninja簡化了這些選擇户魏。
- 讓依賴正確,在一些特殊情況下Makefiles很難解決的挪挤。
- 速度和簡單之間叼丑,選擇速度。
1.2 示例
cflags = -Wall
rule cc
command = gcc $cflags -c $in -o $out
build foo.o: cc foo.c
為字符串生成一個更可讀的名字
cflags = -g
使用$符號取值
rule cc
command = gcc $cflags -c $in -o $out
? 定義一個叫cc的rule扛门,然后這條rule的內(nèi)容是一個可執(zhí)行的命令鸠信,$in
展開為輸入文件(foo.c
),$out
展開為輸出文件(foo.o
) for the command.
? Build語句聲明輸入文件和輸出文件之間的關系论寨,以build關鍵詞開始星立,格式是build outputs: rulename inputs
這個規(guī)則說明所有的輸出文件都是從輸入文件產(chǎn)生的。當output不存在或者input改變時葬凳,都會重新創(chuàng)建output绰垂。上面的例子里面out代表輸出列表。
2. GN
GN是一個用來生成ninja構(gòu)建文件的工具火焰。
2.1 運行參數(shù)
生成構(gòu)建目錄
gn gen out/my_build
設置構(gòu)建參數(shù)
gn gen out/my_build --args="..."
可以設置多個target os以及target cpugn args out/Default
(或者使用--args方式)
target_os = "chromeos"
target_os = "android"
target_cpu = "arm"
target_cpu = "x86"
target_cpu = "x64"
查看所有的參數(shù)
gn args --list out/Default
2.1 Build文件
示例
static_library(“base”) {
sources = [
“a.cc”,
“b.cc”,
]
}
加上依賴
static_library(“base”) {
sources = [
“a.cc”,
“b.cc”,
]
deps = [
“//fancypants”,
“//foo/bar:baz”,
]
}
設計原則
- 模塊化
創(chuàng)建一個反映代碼組件和子組件的目錄結(jié)構(gòu)劲装,把BUILD文件放在每個目錄中。
- 明確模塊之間的關系
內(nèi)置的target類型
-
executable
定義一個可執(zhí)行target
-
shared_library
在鏈接器行上為目標指定共享庫荐健,該目標在“ deps”中列出了共享庫酱畅。
-
static_library
創(chuàng)建.a以及.lib文件
-
loadable_module
創(chuàng)建一個目標文件,只能(并且只能)在運行時加載和卸載江场。
-
source_set:
編譯沒有中間庫的源文件纺酸,將其視為靜態(tài)庫,但沒有靜態(tài)庫鏈接規(guī)則址否。是經(jīng)過編譯但未鏈接的一組源餐蔬,相反碎紊,生成的目標文件是隱式添加到依賴源的所有目標的鏈接器中。
-
group
把一些依賴合并起來并命名
copy
action, action_foreach
bundle_data, create_bundle: Mac & iOS
另外樊诺,我們也可以創(chuàng)建自定義類型仗考。
標簽說明
- 完整標簽
//chrome/browser:version
- 隱式標簽
//base, //base::base的縮寫
- 當前目錄
:bar词爬,表示當前目錄下的bar文件
依賴放到一個group中
gorup是沒有被編譯或者依賴的集合秃嗜。
group("tools") {
deps = [
# This will expand to the name "http://tutorial:tutorial" which is the full name
# of our new target. Run "gn help labels" for more.
"http://tutorial",
]
}
條件語句
component(“base”) {
sources = [
“a.cc”,
“b.cc”,
]
if (is_win || is_linux) {
sources += [ “win_helper.cc” ]
} else {
sources -= [ “a.cc” ]
}
}
Config
Config持有flag, defines, include directories這樣一些東西,但不包含源文件和依賴顿膨。
添加移除配置
executable(“doom_melon”) {
configs -= [
"http://build/config/compiler:chromium_code",
]
configs += [
"http://build/config/compiler:no_chromium_code",
]
}
把配置放到一個group中
config(“myconfig”) {
defines = [ “EVIL_BIT=1” ]
}
executable(“doom_melon”) {
...
configs += [ “:myconfig” ]
}
test(“doom_melon_tests”) {
...
configs += [ “:myconfig” ]
}
動態(tài)加載一些外部的數(shù)據(jù)文件
shared_library(“icu”) {
# This target is loaded @ runtime.
data_deps = [
“:icu_data_tables”,
]
}
權(quán)限控制
- deps vs public_deps
控制依賴的可見性
- visibility
設置當前文件可以被其他文件依賴
- assert_no_deps
依賴項都不應該鏈接
- testonly
不鏈接到production代碼中