Android編譯系統中的Android.bp【轉】


本文轉載自:

轉自:http://note.qidong.name/2017/08/android-blueprint/

Android編譯系統中的Android.bp、Blueprint與Soong

本文簡單介紹Android Nougat(7.0)中引入的Android.bp,及其相關工具鏈。

簡介

Android.bp,是用來替換Android.mk的配置文件。 它使用Blueprint框架來解析,最終轉換成Ninja文件。

與Android.mk不同的是,Android.bp是純粹的配置文件,不包含分支、循環等流程控制,也不能做算數、邏輯運算。 與此同時,Ninja文件也是如此。 這就產生了一些新的問題與需求——在Android項目上進行選擇編譯、解析配置、轉換成Ninja等——Soong應運而生。 Soong其實就相當於Makefile編譯系統的核心,即build/make/core/下面的內容。 它負責提供Android.bp的含義定義與解析,並將之轉換為Ninja文件。。

此外,Soong還會編譯產生一個androidmk命令,可以手動把Android.mk轉換成Android.bp。 這只對無選擇、循環等復雜流程控制的Android.mk生效。

BlueprintSoong都是由Golang寫的項目。 從Android Nougat開始,prebuilts/go/目錄下新增了Golang所需的運行環境,在編譯時使用。

Android.bp以及相關支持,從Android Nougat開始加入,從Android Oreo(8.0)開始默認開啟。 如果需要在Android Nougat的版本使用,需要在執行編譯時添加變量。

make 'USE_SOONG=true' 

單獨編譯blueprint

啟用Soong以后,在Android編譯最開始的准備階段,會執行build/soong/soong.bash進行環境准備。 其中會先編譯、安裝Blueprintout目錄下。 也就是說,在編譯Android項目時,Android.bp相關工具鏈會自動編譯,無需費神。

Soong是與Android強關聯的一個項目,而Blueprint則相對比較獨立,可以單獨編譯、使用。

編譯Blueprint,首先要具備Golang環境。 然后,按照以下步驟執行命令。

  1. go get github.com/google/blueprint
  2. cd $GOPATH/src/github.com/google/blueprint
  3. ./bootstrap.bash
  4. ./blueprint.bash
  5. ls bin

在新生成的bin目錄中,包含4個可執行文件:

  • bpfmt
  • bpmodify
  • microfactory
  • minibp

由於文檔較少,甚至連幫助命令都不包括命令的描述,所以其作用只能望文生義。

工具鏈關系

Android.mk、Android.bp、Soong、Blueprint、Ninja,它們之間到底有什么關系? 以下用簡單的方式表達這幾個概念之間的作用關系。

  1. Android.bp --> Blueprint --> Soong --> Ninja
  2. Makefile or Android.mk --> kati --> Ninja
  3.  
  4. ( Android.mk --> Soong --> Blueprint --> Android.bp)

Blueprint是生成、解析Android.bp的工具,是Soong的一部分。 Soong則是專為Android編譯而設計的工具,Blueprint只是解析文件的形式,而Soong則解釋內容的含義。

Android.mk可以通過Soong提供的androidmk轉換成Android.bp,但僅限簡單配置。 目前Oreo的編譯流程中,仍然是使用kati來做的轉換。

現存的Android.mk、既有的Android.bp,都會分別被轉換成Ninja。 從Android.mk與其它Makefile,會生成out/build-<product_name>.ninja文件。 而從Android.bp,則會生成out/soong/build.ninja。 此外,還會生成一個較小的out/combined-<product_name>.ninja文件,負責把二者組合起來,作為執行入口。

最終,Ninja文件才是真正直接控制源碼編譯的工具。

Android.bp

樣例與基本概念

  1. // Android.bp sample
  2. cc_defaults(
  3. deps = [
  4. "libc",
  5. ],
  6. )
  7.  
  8. cc_library(
  9. name = "cmd",
  10. srcs = [
  11. "main.c",
  12. ],
  13. )
  14.  
  15. subdirs = [ "subdir1", "subdir2"]

前面的樣例中,cc_library這種()前面的,就是模塊(module)。 這里module的概念,直接對應Android.mk中module的概念。 而=前面的namesrcs等,就是該模塊的屬性(property)。

subdirs是一個文件級的頂層屬性,指定后會查找次級目錄下的Android.bp。 類似於Android.mk中常用的include $(call all-subdir-makefiles)

模塊是可以繼承屬性的。 cc_defaults就是一個文件中所有模塊的父模塊,可以指定公用的屬性。 在以上代碼中,cc_library模塊雖然沒有指定,但已經包含了deps屬性。

語法

Blueprint文件的語法比較簡單,畢竟只是配置文件。

變量與屬性都是動態強類型的,賦值時確定。 變量類型只有四種。

  1. Bool(truefalse
  2. 字符串Strings(”string”)
  3. 字符串列表(["string1", "string2"]
  4. 映射關系Map({key1: "value1", key2: ["value2"]}

注釋方式,與Golang類似。 支持行注釋// line與塊注釋/* block */

操作符除了賦值的=以外,只有+

常用工具

雖然編譯過程中的相關很多,不過在開發過程中可能需要手動執行的命令卻不多。

一個是格式化工具bpfmt。 與gofmt類似,可以格式化Blueprint文件。 (其實,代碼基本上都是從gofmt復制而來。)

例如,格式化當前目錄及其遞歸子目錄下的所有Android.bp:

bpfmt -w .

另一個是androidmk,負責轉換Android.mk為Android.bp。 其實,現階段沒有必要學會寫Android.bp,通過寫Android.mk來轉換也行。

androidmk Android.mk > Android.bp

Android.mk轉換Android.bp實例

下面,以一個AOSP上的簡單模塊,system/core/sdcard/Android.mk,來做為案例。

  1. LOCAL_PATH := $(call my-dir)
  2.  
  3. include $(CLEAR_VARS)
  4.  
  5. LOCAL_SRC_FILES := sdcard.cpp fuse.cpp
  6. LOCAL_MODULE := sdcard
  7. LOCAL_CFLAGS := -Wall -Wno-unused-parameter -Werror
  8. LOCAL_SHARED_LIBRARIES := libbase libcutils libminijail libpackagelistparser
  9.  
  10. LOCAL_SANITIZE := integer
  11.  
  12. include $(BUILD_EXECUTABLE)

這是一個編譯二進制可執行文件的小模塊,內容非常簡單。 通過執行androidmk Android.mk > Android.bp,可以轉換成Android.bp。

  1. cc_binary {
  2. srcs: [
  3. "sdcard.cpp",
  4. "fuse.cpp",
  5. ],
  6. name: "sdcard",
  7. cflags: [
  8. "-Wall",
  9. "-Wno-unused-parameter",
  10. "-Werror",
  11. ],
  12. shared_libs: [
  13. "libbase",
  14. "libcutils",
  15. "libminijail",
  16. "libpackagelistparser",
  17. ],
  18. sanitize: {
  19. misc_undefined: [ "integer"],
  20. },
  21. }

可以看出,雖然行數變多,但其實含義更明確了。 這個名為sdcard的模塊,源碼有兩個cpp文件,依賴庫有四個。 cc_binary,就相當於include $(BUILD_EXECUTABLE)。 轉換前后,該有的信息都在,只是表達方式變化了而已。

注意:如果Android.mk中包含復雜的邏輯,則轉換結果會有問題,詳見結果文件中的注釋。

至於Android.bp支持多少像cc_binarycc_library這樣的模塊,每個模塊又支持多少像namecflags這樣的屬性, 則只能去查找Soong的文檔。

文檔

目前(2017年),整個Android.bp工具鏈,都處於文檔極度缺失的階段。 除了官方那點可憐的README以外,基本只能去看代碼與注釋,參考其它已經存在的Android.bp。

另外,在已經使用Soong編譯的項目中,out/soong/.bootstrap/docs/soong_build.html描述了所有的可用模塊及其屬性。 這多少緩解了兩眼一抹黑症狀,不算太過難受。 實際上,整個Soong仍然處於發展期,Google肆無忌憚地修改,完全沒考慮兼容。 在8.0.0寫的Android.bp,也許在8.0.1就會編譯失敗。 這或許是文檔與編譯綁定的真意吧。 等Soong完全成熟了,也許Android開發官網,就會有詳盡的信息。

本站提供了從AOSP的android-8.0.0-r9,編譯出來的一個soong_build.html,僅供參考。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM