Android的Kati舌胶、Ninja捆蜀、Android.bp、Blueprint與Soong簡介

Android中的Kati

android makefile ninja

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簡介

android makefile 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)文件名為Makefilemakefile秉犹,也常用.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è)計失誤的話惫撰,那么mmmmm使用不同的編譯文件羔沙,就是顯然的bug了。 二者相差一個下劃線_厨钻,通過mvcp扼雏,可以通用。

第二類是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-*.ninjaout/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.bpout/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 ninja

本文簡單介紹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生效。

BlueprintSoong都是由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)備。 其中會先編譯、安裝Blueprintout目錄下阳惹。 也就是說谍失,在編譯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)強類型的妙蔗,賦值時確定傲霸。 變量類型只有四種。

  1. Bool(truefalse
  2. 字符串Strings("string")
  3. 字符串列表(["string1", "string2"]
  4. 映射關(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)載自

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末樊破,一起剝皮案震驚了整個濱河市愉棱,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌哲戚,老刑警劉巖奔滑,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異顺少,居然都是意外死亡朋其,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進(jìn)店門祈纯,熙熙樓的掌柜王于貴愁眉苦臉地迎上來令宿,“玉大人,你說我怎么就攤上這事腕窥×C唬” “怎么了?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵簇爆,是天一觀的道長癞松。 經(jīng)常有香客問我爽撒,道長响蓉,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任枫甲,我火速辦了婚禮,結(jié)果婚禮上想幻,老公的妹妹穿的比我還像新娘。我一直安慰自己闹究,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布渣淤。 她就那樣靜靜地躺著,像睡著了一般价认。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上率挣,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天刻伊,我揣著相機與錄音露戒,去河邊找鬼椒功。 笑死,一個胖子當(dāng)著我的面吹牛智什,可吹牛的內(nèi)容都是我干的动漾。 我是一名探鬼主播,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼荠锭,長吁一口氣:“原來是場噩夢啊……” “哼旱眯!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起证九,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤删豺,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后愧怜,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體呀页,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年拥坛,在試婚紗的時候發(fā)現(xiàn)自己被綠了蓬蝶。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片尘分。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖丸氛,靈堂內(nèi)的尸體忽然破棺而出培愁,到底是詐尸還是另有隱情,我是刑警寧澤缓窜,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布定续,位于F島的核電站,受9級特大地震影響禾锤,放射性物質(zhì)發(fā)生泄漏香罐。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一时肿、第九天 我趴在偏房一處隱蔽的房頂上張望庇茫。 院中可真熱鬧,春花似錦螃成、人聲如沸旦签。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽羔巢。三九已至竿秆,卻和暖如春稿壁,著一層夾襖步出監(jiān)牢的瞬間傅是,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工帽驯, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留尼变,地道東北人享甸。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓蛉威,卻偏偏與公主長得像,于是被迫代替她去往敵國和親哲虾。 傳聞我的和親對象是個殘疾皇子束凑,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,792評論 2 345