Android.bp基於Android 10學習筆記

Android.bp簡介

Android 7.0之後希望用Android.bp替換Android.mk,bp簡單的配置更方便Ninja 文件的產生,而Blueprint和Soong 就此產生。Android 利用Blueprint和Soong 來解析bp文件,經過最終轉換爲ninja files。 Blueprint和Soong都是由Golang寫的項目。 從Android Nougat開始,prebuilts/go/目錄下新增了Golang所需的運行環境,在編譯時使用。Android.bp以及相關支持,從Android Nougat開始加入,從 Android Oreo(8.0)開始默認開啓。 如果需要在Android Nougat的版本使用,需要在執行編譯時添加變量: make ‘USE_SOONG=true’ Soong是以前Android基於make的編譯系統的替代品。它以Android.bp文件替代Android.mk,Android.bp文件用類似JSON的簡潔聲明來描述需要構建的模塊。

參考文檔:

再來說一說跟着Android版本相應的發展演變過程:

  1. Android 7.0引入ninja和kati
  2. Android 8.0使用Android.bp來替換Android.mk,引入Soong
  3. Android 9.0強制使用Android.bp

轉換關係

在這裏插入圖片描述

通過Kati將Android.mk轉換成ninja格式的文件,通過Blueprint+Soong將Android.bp轉換成ninja格式的文件,通過androidmk將將Android.mk轉換成Android.bp,但針對沒有分支、循環等流程控制的Android.mk纔有效。

這裏涉及到Ninja, kati, Soong, bp概念,接下來分別簡單介紹一下。

  • Ninja

ninja是一個編譯框架,會根據相應的ninja格式的配置文件進行編譯,但是ninja文件一般不會手動修改,而是通過將Android.bp文件轉換成ninja格文件來編譯。

  • Android.bp

Android.bp的出現就是爲了替換Android.mk文件。bp跟mk文件不同,它是純粹的配置,沒有分支、循環等流程控制,不能做算數邏輯運算。如果需要控制邏輯,那麼只能通過Go語言編寫。

  • Soong

Soong類似於之前的Makefile編譯系統的核心,負責提供Android.bp語義解析,並將之轉換成Ninja文件。Soong還會編譯生成一個androidmk命令,用於將Android.mk文件轉換爲Android.bp文件,不過這個轉換功能僅限於沒有分支、循環等流程控制的Android.mk纔有效。

  • Blueprint

Blueprint是生成、解析Android.bp的工具,是Soong的一部分。Soong負責Android編譯而設計的工具,而Blueprint只是解析文件格式,Soong解析內容的具體含義。Blueprint和Soong都是由Golang寫的項目,從Android 7.0,prebuilts/go/目錄下新增Golang所需的運行環境,在編譯時使用。

  • Kati

kati是專爲Android開發的一個基於Golang和C++的工具,主要功能是把Android中的Android.mk文件轉換成Ninja文件。代碼路徑是build/kati/,編譯後的產物是ckati。

Android.bp語法初識

  • 例子1
cc_library_shared {				//編譯成動態庫,類似於Android.mk中的BUILD_SHARED_LIBRARY
    name: "libbluetooth_jni",	//編譯出的模塊的名稱,類似於Android.mk中的LOCAL_MODULE
    srcs: [ 					//源文件,類似於Android.mk中的LOCAL_SRC_FILES
        "com_android_bluetooth_btservice_AdapterService.cpp",
        "com_android_bluetooth_hfp.cpp",
        "com_android_bluetooth_hfpclient.cpp",
        "com_android_bluetooth_a2dp.cpp",
        "com_android_bluetooth_a2dp_sink.cpp",
        "com_android_bluetooth_avrcp.cpp",
        "com_android_bluetooth_avrcp_controller.cpp",
        "com_android_bluetooth_hid.cpp",
        "com_android_bluetooth_hidd.cpp",
        "com_android_bluetooth_hdp.cpp",
        "com_android_bluetooth_pan.cpp",
        "com_android_bluetooth_gatt.cpp",
        "com_android_bluetooth_sdp.cpp",
    ],
    include_dirs: [				//用戶指定的頭文件查找路徑,類似於Android.mk中的LOCAL_C_INCLUDES
        "libnativehelper/include/nativehelper",
        "system/bt/types",
    ],
    shared_libs: [				//編譯所依賴的動態庫,類似於Android.mk中的LOCAL_SHARED_LIBRARIES
        "libandroid_runtime",
        "libchrome",
        "libnativehelper",
        "libcutils",
        "libutils",
        "liblog",
        "libhardware",
    ],
    static_libs: [				//編譯所依賴的靜態庫,類似於Android.mk中的LOCAL_STATIC_LIBRARIES
        "libbluetooth-types",
    ],
    cflags: [					///編譯flag,類似於Android.mk中的LOCAL_CFLAGS
        "-Wall",
        "-Wextra",
        "-Wno-unused-parameter",
    ],
}

  • 例子2
cc_binary {             //編譯成可執行文件,cc_library_shared編譯成動態庫
    name: "bt_test",    //編譯出的可執行文件的名字爲bt_test
    vendor: true,       //編譯出來放在/vendor目錄下(默認是放在/system目錄下)
    srcs: ["bt_test.cpp"], //源文件,格式["a.cpp", "b.cpp"]
    cflags: [
        "-Wall",
        "-Werror",
        "-Wno-unused-parameter",
    ],                    //編譯flag
    include_dirs: [
        "hardware/interfaces/halnode/1.0/default",    //用戶值定的頭文件查找路徑
    ],
    shared_libs: [       //編譯依賴的動態庫
        "liblog",
        "libutils",
        "libhidltransport",
        "[email protected]",
        "libhidlbase",
        "libbase",
    ],
}
  • 例子3

srcs 屬性以字符串列表的形式指定用於編譯模塊的源文件。您可以使用模塊引用語法 “:” 來引用生成源文件的其他模塊的輸出,如 genrule 或 filegroup。是不是感覺一頭霧水,好嗎,還是上實例說明:

~/ssd/qcom_64/msm8953-9$ cd frameworks/base/core/java/
~/ssd/qcom_64/msm8953-9/frameworks/base/core/java$ vi Android.bp

filegroup {
    name: "IKeyAttestationApplicationIdProvider.aidl",
    srcs: ["android/security/keymaster/IKeyAttestationApplicationIdProvider.aidl"],
}

filegroup {
    name: "IDropBoxManagerService.aidl",
    srcs: ["com/android/internal/os/IDropBoxManagerService.aidl"],

~/ssd/qcom_64/msm8953-9/frameworks/base/core$ cd ..
~/ssd/qcom_64/msm8953-9/frameworks/base$ vi libs/services/Android.bp

cc_library_shared {
    name: "libservices",
    srcs: [
        ":IDropBoxManagerService.aidl",
        "src/os/DropBoxManager.cpp",
        "src/os/StatsDimensionsValue.cpp",
        "src/os/StatsLogEventWrapper.cpp",
    ],  

    shared_libs: [
        "libbinder",
        "liblog",
        "libcutils",
        "libutils",
    ],

模塊

從前面的列子可以看出定義一個模塊從模塊的類型開始,模塊有不同的類型,如前面例子中的cc_library_shared,當然類型還有很多種,譬如cc_binary android_app cc_library_static等等。模塊包含一些屬性格式爲“property-name:property-value”,其中name屬性必須指定,其屬性值必須是全局唯一的。

其中默認模塊可用於在多個模塊中重複相同的屬性,是不是用文字表達很模糊,好嗎,上實例:

cc_defaults {//		//默認模塊名稱
    name: "default_module",
    shared_libs: ["libz"],
    stl: "none",
}
cc_binary {
    name: "test1",
    defaults: ["default_module"],	//引用默認模塊名稱
    srcs: ["src/test/test.c"],
}

類型

變量和屬性是強類型,變量根據第一項賦值動態變化,屬性由模塊類型靜態設置。支持的類型爲:

  • 布爾值(true 或 false)
  • 整數 (int)
  • 字符串 (“string”)
  • 字符串列表 ([“string1”, “string2”])
  • 映射 ({key1: “value1”, key2: [“value2”]})
  • 映射可以包含任何類型的值,包括嵌套映射。列表和映射可能在最後一個值後面有終止逗號。

其它可用選項

  • subdirs = [“ndk”]   //指定進入下層ndk目錄進行編譯

  • export_include_dirs: [   //從其他模塊添加頭文件檢索路徑 “include”, “include/camera” ],

  • export_shared_lib_headers: [“libcamera_metadata”],

  • local_include_dirs: [“aidl”],   //如果從當前目錄添加路徑時使用,將./aidl目錄加入頭文件的搜索路徑

  • static_libs: [“libupdater”],   //指定對庫libupdater進行靜態鏈接 static_executable: true,

變量

Android.bp文件可包含頂級變量賦值:

test_srcs = ["src/test.c"],
cc_binary {
    name: "test",
    srcs: test_srcs,
}

變量範圍限定爲聲明它們的文件的其餘部分,以及任何子藍圖文件。變量是不可變的,但有一個例外 —— 它們可以附上+= 賦值,但僅在變量被引用之前。

註釋

我們知道Android.mk中可以進行註釋,當然Android.bp裏面也可以,Android.mk中使用"#"然後添加註釋,Android.bp使用單行註釋//和多行註釋/* */兩種方式。

運算符

可以使用 + 運算符附加字符串、字符串列表和映射。可以使用 + 運算符對整數求和。附加映射會生成兩個映射中鍵的並集,並附加在兩個映射中都存在的所有鍵的值。

###條件語句
Soong 不支持 Android.bp 文件中的條件語句。但是,編譯規則中需要條件語句的複雜問題將在 Go(在這種語言中,您可以使用高級語言功能,並且可以跟蹤條件語句引入的隱式依賴項)中處理。大多數條件語句都會轉換爲映射屬性,其中選擇了映射中的某個值並將其附加到頂級屬性。

例如,要支持特定於架構的文件,請使用以下命令:

cc_library {
    ...
    srcs: ["generic.cpp"],
    arch: {
        arm: {
            srcs: ["arm.cpp"],
        },
        x86: {
            srcs: ["x86.cpp"],
        },
    },
}
system/core/libusbhost$ cat Android.bp 

cc_library {
    name: "libusbhost",
    vendor_available: true,
    vndk: {
        enabled: true,
    },
    host_supported: true,
    srcs: ["usbhost.c"],
    cflags: ["-Werror"],
    export_include_dirs: ["include"],
    target: {   //相當於if
        android: {    //編譯Android上運行的程序 相當於if
            cflags: [
                "-g",
                "-DUSE_LIBLOG",
            ],
            shared_libs: ["liblog"],
        },
        darwin: {    //編譯darwin上運行的程序
            enabled: false,
        },
    },
}

支持模塊類型

Android.bp可以支持android_app、cc_binary、cc_binary_host等多種類型,具體定義在Android源碼的build/soong/androidmk/cmd/androidmk/android.go可以查看,具體如下:

var moduleTypes = map[string]string{
    "BUILD_SHARED_LIBRARY":        "cc_library_shared",
    "BUILD_STATIC_LIBRARY":        "cc_library_static",
    "BUILD_HOST_SHARED_LIBRARY":   "cc_library_host_shared",
    "BUILD_HOST_STATIC_LIBRARY":   "cc_library_host_static",
    "BUILD_HEADER_LIBRARY":        "cc_library_headers",
    "BUILD_EXECUTABLE":            "cc_binary",
    "BUILD_HOST_EXECUTABLE":       "cc_binary_host",
    "BUILD_NATIVE_TEST":           "cc_test",
    "BUILD_HOST_NATIVE_TEST":      "cc_test_host",
    "BUILD_NATIVE_BENCHMARK":      "cc_benchmark",
    "BUILD_HOST_NATIVE_BENCHMARK": "cc_benchmark_host",

    "BUILD_JAVA_LIBRARY":             "java_library",
    "BUILD_STATIC_JAVA_LIBRARY":      "java_library_static",
    "BUILD_HOST_JAVA_LIBRARY":        "java_library_host",
    "BUILD_HOST_DALVIK_JAVA_LIBRARY": "java_library_host_dalvik",
    "BUILD_PACKAGE":                  "android_app",
}

支持預編譯類型

Android.bp可以支持多種預編譯類型,具體定義在Android源碼的build/soong/androidmk/cmd/androidmk/android.go可以查看,如下圖所示:

var prebuiltTypes = map[string]string{
    "SHARED_LIBRARIES": "cc_prebuilt_library_shared",
    "STATIC_LIBRARIES": "cc_prebuilt_library_static",
    "EXECUTABLES":      "cc_prebuilt_binary",
    "JAVA_LIBRARIES":   "prebuilt_java_library",
}

常用工具

(1)bpfmt 一個是格式化工具bpfmt。 與gofmt類似,可以格式化Blueprint文件。 (其實,代碼基本上都是從gofmt複製而來。)eg 格式化當前目錄及其遞歸子目錄下的所有Android.bp:

wugn # bpfmt -w .

(2)androidmk 另一個是androidmk,負責轉換Android.mk爲Android.bp。

wugn: # androidmk Android.mk > Android.bp
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章