宋建系統

在 Android 7.0 發布之前,Android 僅使用GNU Make來描述和執行其構建規則。 Make 構建系統得到了廣泛的支持和使用,但在 Android 規模上變得緩慢、容易出錯、不可擴展且難以測試。 Soong 構建系統提供了 Android 構建所需的靈活性。

因此,平台開發者有望盡快從Make轉向採用Soong。將問題發送至android-building Google Group 以獲得支持。

宋是什麼?

Android 7.0 (Nougat) 中引入了Soong 構建系統來取代 Make。它利用Kati GNU Make 克隆工具和Ninja構建系統組件來加速 Android 的構建。

請參閱 Android 開源項目 (AOSP) 中的Android Make 構建系統描述以獲取一般說明,並參閱 Android.mk 編寫者的構建系統更改以了解從 Make 適應到 Soong 所需的修改。

請參閱詞彙表中與構建相關的條目以了解關鍵術語的定義,並參閱 Soong 參考文件以了解完整的詳細信息。

Make和宋比較

以下是 Make 配置與 Soong 在 Soong 配置(藍圖或.bp )文件中完成相同操作的比較。

舉例說明

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)
LOCAL_MODULE := libxmlrpc++
LOCAL_MODULE_HOST_OS := linux

LOCAL_RTTI_FLAG := -frtti
LOCAL_CPPFLAGS := -Wall -Werror -fexceptions
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/src

LOCAL_SRC_FILES := $(call \
     all-cpp-files-under,src)
include $(BUILD_SHARED_LIBRARY)

宋例子

cc_library_shared {
     name: “libxmlrpc++”,

     rtti: true,
     cppflags: [
           “-Wall”,
           “-Werror”,
           “-fexceptions”,
     ],
     export_include_dirs: [“src”],
     srcs: [“src/**/*.cpp”],

     target: {
           darwin: {
                enabled: false,
           },
     },
}

有關特定於測試的 Soong 配置示例,請參閱簡單構建配置

Android.bp 文件格式

按照設計, Android.bp文件很簡單。它們不包含條件或控制流語句;所有復雜性都由用 Go 編寫的構建邏輯處理。如果可能, Android.bp文件的語法和語義與Bazel BUILD 文件類似。

模塊

Android.bp文件中的模塊以模塊類型開頭,後跟一組屬性name: "value",格式為:

cc_binary {
    name: "gzip",
    srcs: ["src/test/minigzip.c"],
    shared_libs: ["libz"],
    stl: "none",
}

每個模塊都必須有一個name屬性,並且該值在所有Android.bp文件中必須是唯一的,命名空間和預構建模塊中的name屬性值除外,這些值可能會重複。

srcs屬性指定用於構建模塊的源文件,作為字符串列表。您可以使用模塊引用語法":<module-name>"來引用生成源文件的其他模塊的輸出,例如genrulefilegroup

有關有效模塊類型及其屬性的列表,請參閱Soong Modules Reference

類型

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

  • 布爾值( truefalse
  • 整數 ( int )
  • 字符串( "string"
  • 字符串列表 ( ["string1", "string2"] )
  • 地圖 ( {key1: "value1", key2: ["value2"]} )

映射可以包含任何類型的值,包括嵌套映射。列表和映射的最後一個值後面可能有逗號。

格洛布斯

採用文件列表的屬性(例如srcs )也可以採用 glob 模式。 Glob 模式可以包含普通的 UNIX 通配符* ,例如*.java 。 Glob 模式還可以包含單個**通配符作為路徑元素,它匹配零個或多個路徑元素。例如, java/**/*.java匹配java/Main.javajava/com/android/Main.java模式。

變量

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

gzip_srcs = ["src/test/minigzip.c"],
cc_binary {
    name: "gzip",
    srcs: gzip_srcs,
    shared_libs: ["libz"],
    stl: "none",
}

變量的作用域為聲明它們的文件的其餘部分以及任何子藍圖文件。變量是不可變的,但有一個例外:可以使用+=賦值將它們附加到後面,但只能在引用它們之前進行。

評論

Android.bp文件可以包含 C 風格的多行/* */和 C++ 風格的單行//註釋。

運營商

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

條件句

Soong 不支持Android.bp文件中的條件。相反,需要條件的構建規則的複雜性在 Go 中處理,可以使用高級語言功能,並且可以跟踪條件引入的隱式依賴關係。大多數條件都會轉換為映射屬性,其中選擇映射中的值之一併將其附加到頂級屬性。

例如,要支持特定於體系結構的文件:

cc_library {
    ...
    srcs: ["generic.cpp"],
    arch: {
        arm: {
            srcs: ["arm.cpp"],
        },
        x86: {
            srcs: ["x86.cpp"],
        },
    },
}

格式化程序

Soong 包含一個藍圖文件的規範格式化程序,類似於gofmt 。要遞歸地重新格式化當前目錄中的所有Android.bp文件,請運行:

bpfmt -w .

規範格式包括四空格縮進、多元素列表的每個元素後面的換行以及列表和映射中的尾隨逗號。

特殊模塊

一些特殊的模塊組具有獨特的特性。

默認模塊

默認模塊可用於在多個模塊中重複相同的屬性。例如:

cc_defaults {
    name: "gzip_defaults",
    shared_libs: ["libz"],
    stl: "none",
}

cc_binary {
    name: "gzip",
    defaults: ["gzip_defaults"],
    srcs: ["src/test/minigzip.c"],
}

預建模塊

某些預構建的模塊類型允許模塊與其基於源的對應模塊具有相同的名稱。例如,當已經存在同名的cc_binary時,可能會有一個名為foocc_prebuilt_binary 。這使開發人員可以靈活地選擇要包含在最終產品中的版本。如果構建配置包含兩個版本,則預構建模塊定義中的prefer標誌值指示哪個版本具有優先級。請注意,某些預構建模塊的名稱不以prebuilt開頭,例如android_app_import

命名空間模塊

在 Android 完全從 Make 轉換為 Soong 之前,Make 產品配置必須指定PRODUCT_SOONG_NAMESPACES值。它的值應該是以空格分隔的名稱空間列表,Soong 將其導出到 Make 以由m命令構建。 Android 轉換為 Soong 完成後,啟用命名空間的詳細信息可能會發生變化。

Soong 為不同目錄中的模塊提供了指定相同名稱的能力,只要每個模塊在單獨的命名空間中聲明即可。命名空間可以這樣聲明:

soong_namespace {
    imports: ["path/to/otherNamespace1", "path/to/otherNamespace2"],
}

請注意,命名空間沒有 name 屬性;它的路徑會自動指定為其名稱。

每個 Soong 模塊都會根據其在樹中的位置分配一個命名空間。每個 Soong 模塊都被認為位於當前目錄或最近祖先目錄中Android.bp文件中的soong_namespace定義的命名空間中。如果沒有找到這樣的soong_namespace模塊,則該模塊被認為位於隱式根命名空間中。

下面是一個示例:Soong 嘗試解析命名空間 N 中模塊 M 聲明的依賴項 D,該模塊導入命名空間 I1、I2、I3…

  1. 然後,如果 D 是//namespace:module形式的完全限定名稱,則僅在指定的命名空間中搜索指定的模塊名稱。
  2. 否則,Soong 首先查找在命名空間 N 中聲明的名為 D 的模塊。
  3. 如果該模塊不存在,Soong 會在命名空間 I1、I2、I3… 中查找名為 D 的模塊。
  4. 最後,Soong 查看根命名空間。