Android中的Kati
kati是Google專門為了Android而開發(fā)的一個小項目幔嫂,基于Golang和C++辆它。 目的是為了把Android中的Makefile,轉(zhuǎn)換成Ninja文件履恩。
代碼位置
在Android 7.0以上的平臺項目中锰茉,kati的位置是build/kati/
。 另外切心,平臺代碼也自帶編譯好的ckati
飒筑。
$ find prebuilts/ -name ckati
prebuilts/build-tools/linux-x86/asan/bin/ckati
prebuilts/build-tools/linux-x86/bin/ckati
prebuilts/build-tools/darwin-x86/bin/ckati
它也是一個獨立發(fā)布的項目,在GitHub上的位置是google/kati绽昏。
git clone https://github.com/google/kati.git
編譯
在Git庫中协屡,可以用make
來直接編譯。 編譯完成后全谤,目錄下會出現(xiàn)ckati
這個可執(zhí)行文件肤晓。 產(chǎn)生ckati
后,通過執(zhí)行./m2n
认然,可以把Makefile轉(zhuǎn)換成build.ninja文件补憾。 接下來,可以通過執(zhí)行ninja
來再次編譯卷员。
在Android項目中余蟹,這個Git庫自帶Android.bp文件,可以作為一個模塊自動跟隨項目一起編譯子刮。 也可以在項目路徑中威酒,執(zhí)行mm
單獨編譯窑睁。 編譯產(chǎn)物主要是ckati
,會被安裝到項目的out/host/linux-x86/bin/ckati
葵孤,作為編譯過程中主機環(huán)境的一部分担钮。 (這里是使用Linux來編譯。如果是Windows或Darwin尤仍,產(chǎn)物位置會略有不同箫津。)
使用
在Android項目中,ckati
會在編譯過程中宰啦,自動被使用苏遥,無需操心。
單獨使用時赡模,在包含Makefile的目錄下田炭,執(zhí)行ckati
,效果與make
基本相同漓柑。 執(zhí)行ckati --ninja
教硫,可以根據(jù)Makefile生成build.ninja文件,并且附帶env.sh和ninja.sh辆布。 通過env.sh來配置環(huán)境瞬矩,通過執(zhí)行./ninja.sh
來啟動Ninja、使用build.ninja編譯锋玲。 生成的ninja.sh文件景用,主要內(nèi)容如下。
. ./env.sh
exec ninja -f ./build.ninja "$@"
除了--ninja
以外惭蹂,ckati
支持很多其它參數(shù)伞插。 比如,和make
一樣剿干,可以通過-f
指定Makefile位置,通過-j
指定線程數(shù)穆刻。 另外置尔,在kati項目的m2n
腳本中,就可以看到以下的復(fù)雜用法氢伟。
ckati --ninja --ignore_optional_include=out/%.P --ignore_dirty=out/% --use_find_emulator --detect_android_echo --detect_depfiles --gen_all_targets
然而榜轿,這些參數(shù)的具體含義,只能望文生義朵锣。 ckati
的文檔十分匱乏谬盐,不僅沒有像樣的網(wǎng)站,連幫助命令都沒有诚些。 不過飞傀,從其源文件find.cc
中皇型,還是可以看出一些端倪。
for (int i = 1; i < argc; i++) {
const char* arg = argv[i];
bool should_propagate = true;
int pi = i;
if (!strcmp(arg, "-f")) {
makefile = argv[++i];
should_propagate = false;
} else if (!strcmp(arg, "-c")) {
is_syntax_check_only = true;
} else if (!strcmp(arg, "-i")) {
is_dry_run = true;
} else if (!strcmp(arg, "-s")) {
is_silent_mode = true;
} else if (!strcmp(arg, "-d")) {
enable_debug = true;
} else if (!strcmp(arg, "--kati_stats")) {
enable_stat_logs = true;
} else if (!strcmp(arg, "--warn")) {
enable_kati_warnings = true;
} else if (!strcmp(arg, "--ninja")) {
generate_ninja = true;
} else if (!strcmp(arg, "--gen_all_targets")) {
gen_all_targets = true;
} else if (!strcmp(arg, "--regen")) {
// TODO: Make this default.
regen = true;
} else if (!strcmp(arg, "--regen_debug")) {
regen_debug = true;
} else if (!strcmp(arg, "--regen_ignoring_kati_binary")) {
regen_ignoring_kati_binary = true;
} else if (!strcmp(arg, "--dump_kati_stamp")) {
dump_kati_stamp = true;
regen_debug = true;
} else if (!strcmp(arg, "--detect_android_echo")) {
detect_android_echo = true;
} else if (!strcmp(arg, "--detect_depfiles")) {
detect_depfiles = true;
} else if (!strcmp(arg, "--color_warnings")) {
color_warnings = true;
} else if (!strcmp(arg, "--werror_find_emulator")) {
werror_find_emulator = true;
} else if (!strcmp(arg, "--werror_overriding_commands")) {
werror_overriding_commands = true;
} else if (ParseCommandLineOptionWithArg(
"-j", argv, &i, &num_jobs_str)) {
num_jobs = strtol(num_jobs_str, NULL, 10);
if (num_jobs <= 0) {
ERROR("Invalid -j flag: %s", num_jobs_str);
}
} else if (ParseCommandLineOptionWithArg(
"--remote_num_jobs", argv, &i, &num_jobs_str)) {
remote_num_jobs = strtol(num_jobs_str, NULL, 10);
if (remote_num_jobs <= 0) {
ERROR("Invalid -j flag: %s", num_jobs_str);
}
} else if (ParseCommandLineOptionWithArg(
"--ninja_suffix", argv, &i, &ninja_suffix)) {
} else if (ParseCommandLineOptionWithArg(
"--ninja_dir", argv, &i, &ninja_dir)) {
} else if (!strcmp(arg, "--use_find_emulator")) {
use_find_emulator = true;
} else if (ParseCommandLineOptionWithArg(
"--goma_dir", argv, &i, &goma_dir)) {
} else if (ParseCommandLineOptionWithArg(
"--ignore_optional_include",
argv, &i, &ignore_optional_include_pattern)) {
} else if (ParseCommandLineOptionWithArg(
"--ignore_dirty",
argv, &i, &ignore_dirty_pattern)) {
} else if (ParseCommandLineOptionWithArg(
"--no_ignore_dirty",
argv, &i, &no_ignore_dirty_pattern)) {
} else if (arg[0] == '-') {
ERROR("Unknown flag: %s", arg);
} else {
if (strchr(arg, '=')) {
cl_vars.push_back(arg);
} else {
should_propagate = false;
targets.push_back(Intern(arg));
}
}
總結(jié)
kati是一個基于Makefile來生成ninja.build的小項目砸烦。 它是Google專為Android而開發(fā)弃鸦,用來修正Android項目創(chuàng)建之初的錯誤——使用Makefile來做一個超復(fù)雜的編譯構(gòu)建系統(tǒng)。
在編譯過程中幢痘,kati負(fù)責(zé)把既有的Makefile唬格、Android.mk,轉(zhuǎn)換成Ninja文件颜说。 在Android 7.0中购岗,它獨挑大梁。 在Android 8.0以后门粪,它與Soong一起喊积,成為Ninja文件的兩大來源。 也許庄拇,在幾個大版本后注服,它會與原先的Makefile、Android.mk一起措近,退出Android平臺編譯系統(tǒng)的大舞臺溶弟。
在單獨使用時,它對普通的小項目還能勉強生效瞭郑。 面對復(fù)雜的辜御、多嵌套的Makefile時,它往往無法支持屈张,會出現(xiàn)各種各樣的問題擒权。 當(dāng)然,也可以理解為阁谆,它只為Android而設(shè)計碳抄。
總之,不推薦在Android以外的任何項目中使用kati场绿。
Android中的Ninja簡介
如果說Makefile是一個DSL剖效,那么Ninja就是一種配置文件逼蒙。 本文簡單介紹Android中的Ninja畴博。
Makefile與Ninja的對比
二者最核心的區(qū)別蝎毡,在于設(shè)計哲學(xué)喘鸟。 Makefile是設(shè)計來給人手寫的驻债,而Ninja設(shè)計出來是給其它程序生成的矗愧。 如果說Makefile是C語言柱徙,那么Ninja就是匯編語言席怪。 如果說Makefile是一個DSL澎粟,那么Ninja就是一種配置文件蛀序。 Makefile支持分支欢瞪、循環(huán)等流程控制,而Ninja只支持一些固定形式的配置哼拔。
二者的相同點是引有,都是為了控制編譯流程而設(shè)計。 所以倦逐,他們的核心功能譬正,都是指定目標(biāo),以及目標(biāo)之間的依賴關(guān)系檬姥,自動計算執(zhí)行順序曾我。
與Makefile相比,由于Ninja僅僅專注于核心的功能健民,所以有輕巧抒巢、速度快的優(yōu)點。
Makefile默認(rèn)文件名為Makefile
或makefile
秉犹,也常用.make
或.mk
作為文件后綴蛉谜。 Ninja的默認(rèn)文件名是build.ninja
,其它文件也以.ninja
為后綴崇堵。 執(zhí)行Makefile的程序型诚,默認(rèn)是GNU make,也有一些其它的實現(xiàn)鸳劳。 Ninja的執(zhí)行程序狰贯,就是ninja
命令。
在Android項目中赏廓,make
需要編譯主機上安裝涵紊,作為環(huán)境的一部分。 而ninja
命令則是Android平臺代碼自帶幔摸。
$ find prebuilts/ -name ninja
prebuilts/build-tools/linux-x86/asan/bin/ninja
prebuilts/build-tools/linux-x86/bin/ninja
prebuilts/build-tools/darwin-x86/bin/ninja
ninja命令的用法
通過ninja -h
摸柄,可以看到該命令的幫助文檔。
$ ninja -h
usage: ninja [options] [targets...]
if targets are unspecified, builds the 'default' target (see manual).
options:
--version print ninja version ("1.7.2")
-C DIR change to DIR before doing anything else
-f FILE specify input build file [default=build.ninja]
-j N run N jobs in parallel [default=6, derived from CPUs available]
-k N keep going until N jobs fail [default=1]
-l N do not start new jobs if the load average is greater than N
-n dry run (don't run commands but act like they succeeded)
-v show all command lines while building
-d MODE enable debugging (use -d list to list modes)
-t TOOL run a subtool (use -t list to list subtools)
terminates toplevel options; further flags are passed to the tool
-w FLAG adjust warnings (use -w list to list warnings)
很多參數(shù)既忆,和make
是比較類似的驱负,比如-f
、-j
等尿贫,不再贅述电媳。 有趣的是-t
踏揣、-d
庆亡、-w
這三個參數(shù),最有用的是-t
捞稿。
$ ninja -t list
ninja subtools:
browse browse dependency graph in a web browser
clean clean built files
commands list all commands required to rebuild given targets
deps show dependencies stored in the deps log
graph output graphviz dot file for targets
query show inputs/outputs for a path
targets list targets by their rule or depth in the DAG
compdb dump JSON compilation database to stdout
recompact recompacts ninja-internal data structures
ninja -t clean
是清理產(chǎn)物又谋,是自帶的拼缝,而make clean
往往需要自己實現(xiàn)。 其它都是查看編譯過程信息的工具彰亥,各有作用咧七,可以進(jìn)行復(fù)雜的編譯依賴分析。
Ninja的專注任斋,在這里完全超越了Makefile继阻。
Android中的Ninja文件
從Android 7開始,編譯時默認(rèn)使用Ninja废酷。 但是瘟檩,Android項目里是沒有.ninja
文件的。 遵循Ninja的設(shè)計哲學(xué)澈蟆,編譯時墨辛,會先把Makefile通過kati轉(zhuǎn)換成.ninja
文件,然后使用ninja
命令進(jìn)行編譯趴俘。 這些.ninja
文件睹簇,都產(chǎn)生在out/
目錄下,共有三類寥闪。
一類是build-*.ninja
文件太惠,通常非常大,幾十到幾百MB橙垢。 對make
全編譯垛叨,命名是build-<product_name>.ninja
。 如果Makefile發(fā)生修改柜某,需要重新產(chǎn)生Ninja文件嗽元。
這里Android有一個bug,或者說設(shè)計失誤喂击。 mm
剂癌、mma
的Ninja文件,命名是build-<product_name>-<path_to_Android.mk>.ninja
翰绊。 而mmm
佩谷、mmma
的Ninja文件,命名是build-<product_name>-_<path_to_Android.mk>.ninja
监嗜。 顯然谐檀,不同的單模塊編譯,產(chǎn)生的也是不同的Ninja文件裁奇。
這個設(shè)計本身就有一些問題了桐猬,為什么不同模塊不能共用一個總的Ninja文件? 這大概還是為了兼容舊的Makefile設(shè)計刽肠。 在某些Android.mk中溃肪,單模塊編譯與全編譯時免胃,編譯內(nèi)容截然不同。 如果說這還只能算是設(shè)計失誤的話惫撰,那么mm
與mmm
使用不同的編譯文件羔沙,就是顯然的bug了。 二者相差一個下劃線_
厨钻,通過mv
或cp
扼雏,可以通用。
第二類是combined-*.ninja
文件夯膀。 在使用了Soong后呢蛤,除了build-*.ninja
之外,還會產(chǎn)生對應(yīng)的combined-*.ninja
棍郎,二者的*
內(nèi)容相同其障。 以下以AOSP的aosp_arm64-eng為例,展示out/combined-aosp_arm64.ninja
文件的內(nèi)容涂佃。
builddir = out
include out/build-aosp_arm64.ninja
include out/soong/build.ninja
build out/combined-aosp_arm64.ninja: phony out/soong/build.ninja
這類是組合文件励翼,是把build-*.ninja
和out/soong/build.ninja
組合起來。 所以辜荠,使用Soong后汽抚,combined-*.ninja
是編譯執(zhí)行的真正入口。
第三類是out/soong/build.ninja
文件伯病,它是從所有的Android.bp
轉(zhuǎn)換過來的造烁。
build-*.ninja
是從所有的Makefile,用Kati轉(zhuǎn)換過來的午笛,包括build/core/*.mk
和所有的Android.mk
惭蟋。 所以,在不使用Soong時药磺,它是唯一入口告组。 在使用了Soong以后,會新增源于Android.bp
的out/soong/build.ninja
癌佩,所以需要combined-*.ninja
來組合一下木缝。
可以通過以下命令,單獨產(chǎn)生全編譯的Ninja文件围辙。
make nothing
用ninja編譯
在產(chǎn)生全編譯的Ninja文件后我碟,可以繞過Makefile,單獨使用ninja
進(jìn)行編譯姚建。
全編譯(7.0版本)矫俺,相當(dāng)于make
:
ninja -f out/build-aosp_arm64.ninja
單獨編譯模塊,比如Settings,相當(dāng)于make Settings
:
ninja -f out/build-aosp_arm64.ninja Settings
在8.0以上恳守,上面的文件應(yīng)該替換為out/combined-aosp_arm64.ninja
,否則可能找不到某些Target贩虾。
另外催烘,還有辦法不用輸入-f
參數(shù)。 如前所述缎罢,如同Makefile之于make
伊群,ninja
默認(rèn)的編譯文件是build.ninja
。 所以策精,使用軟鏈接舰始,可以避免每次輸入繁瑣的-f
。
ln -s out/combined-aosp_arm64.ninja build.ninja
ninja Settings
用ninja
進(jìn)行單模塊編譯的好處咽袜,除了更快以外丸卷,還不用生成單模塊的Ninja文件,省了四五分鐘询刹。
總結(jié)
在以Ninja在實際編譯中替換Makefile以后谜嫉,Android在編譯時更快了一些。 不過凹联,在首次生成沐兰、或重新生成Ninja文件時,往往額外耗時數(shù)分鐘蔽挠,反而比原先使用Makefile更慢了住闯。
在增量編譯方面,原先由于其Makefile編譯系統(tǒng)的實現(xiàn)問題澳淑,是不完善的比原。 也就是說,在make
編譯完一個項目后杠巡,如果再執(zhí)行make
春寿,會花費較長時間重新編譯部分內(nèi)容。 而使用Ninja以后忽孽,增量編譯做得比較完善绑改,第二次make
將在一分鐘內(nèi)結(jié)束。
除此之外兄一,由于Ninja的把編譯流程集中到了一個文件厘线,并且提供了一些工具命令。 所以編譯信息的提取出革、編譯依賴的分析造壮,變得更加方便了。
Android編譯系統(tǒng)中的Android.bp、Blueprint與Soong
本文簡單介紹Android Nougat(7.0)中引入的Android.bp耳璧,及其相關(guān)工具鏈成箫。
簡介
Android.bp,是用來替換Android.mk的配置文件旨枯。 它使用Blueprint框架來解析蹬昌,最終轉(zhuǎn)換成Ninja文件。
與Android.mk不同的是攀隔,Android.bp是純粹的配置文件皂贩,不包含分支、循環(huán)等流程控制昆汹,也不能做算數(shù)明刷、邏輯運算。 與此同時满粗,Ninja文件也是如此辈末。 這就產(chǎn)生了一些新的問題與需求——在Android項目上進(jìn)行選擇編譯、解析配置映皆、轉(zhuǎn)換成Ninja等——Soong應(yīng)運而生本冲。 Soong其實就相當(dāng)于Makefile編譯系統(tǒng)的核心,即build/make/core/
下面的內(nèi)容劫扒。 它負(fù)責(zé)提供Android.bp的含義定義與解析檬洞,并將之轉(zhuǎn)換為Ninja文件。沟饥。
此外添怔,Soong還會編譯產(chǎn)生一個androidmk
命令,可以手動把Android.mk轉(zhuǎn)換成Android.bp贤旷。 這只對無選擇广料、循環(huán)等復(fù)雜流程控制的Android.mk生效。
Blueprint和Soong都是由Golang寫的項目幼驶。 從Android Nougat開始艾杏,prebuilts/go/
目錄下新增了Golang所需的運行環(huán)境,在編譯時使用盅藻。
Android.bp以及相關(guān)支持购桑,從Android Nougat開始加入,從Android Oreo(8.0)開始默認(rèn)開啟氏淑。 如果需要在Android Nougat的版本使用勃蜘,需要在執(zhí)行編譯時添加變量。
make 'USE_SOONG=true'
單獨編譯blueprint
啟用Soong以后假残,在Android編譯最開始的準(zhǔn)備階段缭贡,會執(zhí)行build/soong/soong.bash
進(jìn)行環(huán)境準(zhǔn)備。 其中會先編譯、安裝Blueprint到out
目錄下阳惹。 也就是說谍失,在編譯Android項目時,Android.bp相關(guān)工具鏈會自動編譯莹汤,無需費神快鱼。
Soong是與Android強關(guān)聯(lián)的一個項目,而Blueprint則相對比較獨立体啰,可以單獨編譯、使用嗽仪。
編譯Blueprint荒勇,首先要具備Golang環(huán)境。 然后闻坚,按照以下步驟執(zhí)行命令沽翔。
go get github.com/google/blueprint
cd $GOPATH/src/github.com/google/blueprint
./bootstrap.bash
./blueprint.bash
ls bin
在新生成的bin
目錄中,包含4個可執(zhí)行文件:
- bpfmt
- bpmodify
- microfactory
- minibp
由于文檔較少窿凤,甚至連幫助命令都不包括命令的描述仅偎,所以其作用只能望文生義。
工具鏈關(guān)系
Android.mk雳殊、Android.bp橘沥、Soong、Blueprint夯秃、Ninja座咆,它們之間到底有什么關(guān)系? 以下用簡單的方式表達(dá)這幾個概念之間的作用關(guān)系仓洼。
Android.bp --> Blueprint --> Soong --> Ninja
Makefile or Android.mk --> kati --> Ninja
(Android.mk --> Soong --> Blueprint --> Android.bp)
Blueprint是生成介陶、解析Android.bp的工具,是Soong的一部分色建。 Soong則是專為Android編譯而設(shè)計的工具哺呜,Blueprint只是解析文件的形式,而Soong則解釋內(nèi)容的含義箕戳。
Android.mk可以通過Soong提供的androidmk
轉(zhuǎn)換成Android.bp某残,但僅限簡單配置。 目前Oreo的編譯流程中陵吸,仍然是使用kati來做的轉(zhuǎn)換驾锰。
現(xiàn)存的Android.mk、既有的Android.bp走越,都會分別被轉(zhuǎn)換成Ninja椭豫。 從Android.mk與其它Makefile,會生成out/build-<product_name>.ninja
文件。 而從Android.bp赏酥,則會生成out/soong/build.ninja
喳整。 此外,還會生成一個較小的out/combined-<product_name>.ninja
文件裸扶,負(fù)責(zé)把二者組合起來框都,作為執(zhí)行入口。
最終呵晨,Ninja文件才是真正直接控制源碼編譯的工具魏保。
Android.bp
樣例與基本概念
// Android.bp sample
cc_defaults(
deps = [
"libc",
],
)
cc_library(
name = "cmd",
srcs = [
"main.c",
],
)
subdirs = ["subdir1", "subdir2"]
前面的樣例中,cc_library
這種()
前面的摸屠,就是模塊(module)谓罗。 這里module的概念,直接對應(yīng)Android.mk中module的概念季二。 而=
前面的name
檩咱、srcs
等,就是該模塊的屬性(property)胯舷。
subdirs
是一個文件級的頂層屬性刻蚯,指定后會查找次級目錄下的Android.bp。 類似于Android.mk中常用的include $(call all-subdir-makefiles)
桑嘶。
模塊是可以繼承屬性的炊汹。 cc_defaults
就是一個文件中所有模塊的父模塊,可以指定公用的屬性逃顶。 在以上代碼中兵扬,cc_library
模塊雖然沒有指定,但已經(jīng)包含了deps
屬性口蝠。
語法
Blueprint文件的語法比較簡單器钟,畢竟只是配置文件。
變量與屬性都是動態(tài)強類型的妙蔗,賦值時確定傲霸。 變量類型只有四種。
- Bool(
true
或false
) - 字符串Strings("string")
- 字符串列表(
["string1", "string2"]
) - 映射關(guān)系Map(
{key1: "value1", key2: ["value2"]}
)
注釋方式眉反,與Golang類似昙啄。 支持行注釋// line
與塊注釋/* block */
。
操作符除了賦值的=
以外寸五,只有+
梳凛。
常用工具
雖然編譯過程中的相關(guān)很多,不過在開發(fā)過程中可能需要手動執(zhí)行的命令卻不多梳杏。
一個是格式化工具bpfmt
韧拒。 與gofmt類似淹接,可以格式化Blueprint文件。 (其實叛溢,代碼基本上都是從gofmt復(fù)制而來塑悼。)
例如,格式化當(dāng)前目錄及其遞歸子目錄下的所有Android.bp:
bpfmt -w .
另一個是androidmk
楷掉,負(fù)責(zé)轉(zhuǎn)換Android.mk為Android.bp厢蒜。 其實,現(xiàn)階段沒有必要學(xué)會寫Android.bp烹植,通過寫Android.mk來轉(zhuǎn)換也行斑鸦。
androidmk Android.mk > Android.bp
Android.mk轉(zhuǎn)換Android.bp實例
下面,以一個AOSP上的簡單模塊草雕,system/core/sdcard/Android.mk
巷屿,來做為案例。
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := sdcard.cpp fuse.cpp
LOCAL_MODULE := sdcard
LOCAL_CFLAGS := -Wall -Wno-unused-parameter -Werror
LOCAL_SHARED_LIBRARIES := libbase libcutils libminijail libpackagelistparser
LOCAL_SANITIZE := integer
include $(BUILD_EXECUTABLE)
這是一個編譯二進(jìn)制可執(zhí)行文件的小模塊促绵,內(nèi)容非常簡單攒庵。 通過執(zhí)行androidmk Android.mk > Android.bp
嘴纺,可以轉(zhuǎn)換成Android.bp败晴。
cc_binary {
srcs: [
"sdcard.cpp",
"fuse.cpp",
],
name: "sdcard",
cflags: [
"-Wall",
"-Wno-unused-parameter",
"-Werror",
],
shared_libs: [
"libbase",
"libcutils",
"libminijail",
"libpackagelistparser",
],
sanitize: {
misc_undefined: ["integer"],
},
}
可以看出,雖然行數(shù)變多栽渴,但其實含義更明確了尖坤。 這個名為sdcard
的模塊,源碼有兩個cpp文件闲擦,依賴庫有四個慢味。 cc_binary
,就相當(dāng)于include $(BUILD_EXECUTABLE)
墅冷。 轉(zhuǎn)換前后纯路,該有的信息都在,只是表達(dá)方式變化了而已寞忿。
注意:如果Android.mk中包含復(fù)雜的邏輯驰唬,則轉(zhuǎn)換結(jié)果會有問題,詳見結(jié)果文件中的注釋腔彰。
至于Android.bp支持多少像cc_binary
叫编、cc_library
這樣的模塊,每個模塊又支持多少像name
霹抛、cflags
這樣的屬性搓逾, 則只能去查找Soong的文檔。
文檔
目前(2017年)杯拐,整個Android.bp工具鏈霞篡,都處于文檔極度缺失的階段世蔗。 除了官方那點可憐的README以外,基本只能去看代碼與注釋寇损,參考其它已經(jīng)存在的Android.bp凸郑。
另外,在已經(jīng)使用Soong編譯的項目中矛市,out/soong/.bootstrap/docs/soong_build.html
描述了所有的可用模塊及其屬性芙沥。 這多少緩解了兩眼一抹黑癥狀,不算太過難受浊吏。 實際上而昨,整個Soong仍然處于發(fā)展期,Google肆無忌憚地修改找田,完全沒考慮兼容歌憨。 在8.0.0寫的Android.bp,也許在8.0.1就會編譯失敗墩衙。 這或許是文檔與編譯綁定的真意吧务嫡。 等Soong完全成熟了,也許Android開發(fā)官網(wǎng)漆改,就會有詳盡的信息心铃。
本站提供了從AOSP的android-8.0.0-r9,編譯出來的一個soong_build.html挫剑,僅供參考去扣。
轉(zhuǎn)載自