Hệ thống xây dựng Soong

Trước khi phát hành Android 7.0, Android chỉ sử dụng GNU Make để mô tả và thực thi các quy tắc xây dựng của nó. Hệ thống Make build được hỗ trợ và sử dụng rộng rãi nhưng ở quy mô của Android trở nên chậm, dễ xảy ra lỗi, không thể mở rộng và khó kiểm tra. Hệ thống xây dựng Soong cung cấp tính linh hoạt cần thiết cho các bản dựng Android.

Vì lý do này, các nhà phát triển nền tảng dự kiến ​​sẽ chuyển từ Make và áp dụng Soong càng sớm càng tốt. Gửi câu hỏi tới Nhóm Google xây dựng android để nhận được hỗ trợ.

Song là gì?

Hệ thống xây dựng Soong được giới thiệu trong Android 7.0 (Nougat) để thay thế Make. Nó tận dụng công cụ nhân bản Kati GNU Make và thành phần hệ thống xây dựng Ninja để tăng tốc độ xây dựng Android.

Xem mô tả Android Make Build System trong Dự án mã nguồn mở Android (AOSP) để biết hướng dẫn chung và Thay đổi hệ thống xây dựng dành cho người viết Android.mk để tìm hiểu về các sửa đổi cần thiết để thích ứng từ Make to Soong.

Xem các mục liên quan đến bản dựng trong bảng chú giải thuật ngữ để biết định nghĩa của các thuật ngữ chính và tệp tham chiếu Soong để biết chi tiết đầy đủ.

So sánh Make và Soong

Dưới đây là so sánh việc Tạo cấu hình với việc Soong thực hiện điều tương tự trong tệp cấu hình Soong (Blueprint hoặc .bp ).

Làm ví dụ

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)

Ví dụ về sớm

cc_library_shared {
     name: “libxmlrpc++”,

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

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

Xem Cấu hình bản dựng đơn giản để biết các ví dụ về cấu hình Soong dành riêng cho thử nghiệm.

Định dạng tệp Android.bp

Theo thiết kế, các tệp Android.bp rất đơn giản. Chúng không chứa các câu lệnh điều kiện hoặc luồng điều khiển; tất cả sự phức tạp đều được xử lý bằng logic xây dựng được viết bằng Go. Khi có thể, cú pháp và ngữ nghĩa của tệp Android.bp tương tự như tệp Bazel BUILD .

Mô-đun

Mô-đun trong tệp Android.bp bắt đầu bằng loại mô-đun, theo sau là tập hợp thuộc tính có name: "value", định dạng:

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

Mỗi mô-đun phải có một thuộc tính name và giá trị phải là duy nhất trên tất cả các tệp Android.bp , ngoại trừ các giá trị thuộc tính name trong không gian tên và các mô-đun tạo sẵn có thể lặp lại.

Thuộc tính srcs chỉ định các tệp nguồn được sử dụng để xây dựng mô-đun dưới dạng danh sách các chuỗi. Bạn có thể tham chiếu đầu ra của các mô-đun khác tạo ra tệp nguồn, như genrule hoặc filegroup , bằng cách sử dụng cú pháp tham chiếu mô-đun ":<module-name>" .

Để biết danh sách các loại mô-đun hợp lệ và thuộc tính của chúng, hãy xem Tham khảo mô-đun Soong .

Các loại

Các biến và thuộc tính được định kiểu mạnh, với các biến động dựa trên phép gán đầu tiên và các thuộc tính được đặt tĩnh theo loại mô-đun. Các loại được hỗ trợ là:

  • Boolean ( true hoặc false )
  • Số nguyên ( int )
  • Chuỗi ( "string" )
  • Danh sách các chuỗi ( ["string1", "string2"] )
  • Bản đồ ( {key1: "value1", key2: ["value2"]} )

Bản đồ có thể chứa bất kỳ loại giá trị nào, bao gồm cả bản đồ lồng nhau. Danh sách và bản đồ có thể có dấu phẩy ở cuối giá trị cuối cùng.

quả cầu

Các thuộc tính lấy danh sách các tệp, chẳng hạn như srcs , cũng có thể lấy các mẫu toàn cục. Các mẫu toàn cầu có thể chứa ký tự đại diện UNIX bình thường * , ví dụ *.java . Các mẫu toàn cầu cũng có thể chứa một ký tự đại diện ** duy nhất làm phần tử đường dẫn, khớp với 0 hoặc nhiều phần tử đường dẫn. Ví dụ: java/**/*.java khớp với cả hai mẫu java/Main.javajava/com/android/Main.java .

Biến

Tệp Android.bp có thể chứa các phép gán biến cấp cao nhất:

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

Các biến nằm trong phạm vi phần còn lại của tệp mà chúng được khai báo, cũng như bất kỳ tệp Blueprint con nào. Các biến là bất biến với một ngoại lệ: chúng có thể được thêm vào bằng phép gán += , nhưng chỉ trước khi chúng được tham chiếu.

Bình luận

Các // Android.bp có thể chứa các nhận xét /* */ một dòng nhiều dòng kiểu C và kiểu C++.

Toán tử

Các chuỗi, danh sách chuỗi và bản đồ có thể được nối thêm bằng toán tử +. Các số nguyên có thể được tính tổng bằng toán tử + . Việc thêm một bản đồ sẽ tạo ra sự kết hợp các khóa trong cả hai bản đồ, nối thêm các giá trị của bất kỳ khóa nào có trong cả hai bản đồ.

Câu điều kiện

Soong không hỗ trợ các điều kiện trong tệp Android.bp . Thay vào đó, sự phức tạp trong các quy tắc xây dựng yêu cầu các điều kiện sẽ được xử lý trong Go, nơi có thể sử dụng các tính năng ngôn ngữ cấp cao và có thể theo dõi các phần phụ thuộc ngầm do các điều kiện đưa ra. Hầu hết các điều kiện được chuyển đổi thành thuộc tính bản đồ, trong đó một trong các giá trị trong bản đồ được chọn và gắn vào thuộc tính cấp cao nhất.

Ví dụ: để hỗ trợ các tệp dành riêng cho kiến ​​trúc:

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

Trình định dạng

Soong bao gồm một trình định dạng chuẩn cho các tập tin Blueprint, tương tự như gofmt . Để định dạng lại đệ quy tất cả các tệp Android.bp trong thư mục hiện tại, hãy chạy:

bpfmt -w .

Định dạng chuẩn bao gồm thụt lề bốn dấu cách, dòng mới sau mỗi phần tử của danh sách nhiều phần tử và dấu phẩy ở cuối trong danh sách và bản đồ.

Các mô-đun đặc biệt

Một số nhóm mô-đun đặc biệt có những đặc điểm riêng.

Mô-đun mặc định

Một mô-đun mặc định có thể được sử dụng để lặp lại các thuộc tính giống nhau trong nhiều mô-đun. Ví dụ:

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

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

Các mô-đun dựng sẵn

Một số loại mô-đun dựng sẵn cho phép mô-đun có cùng tên với các mô-đun tương ứng dựa trên nguồn của nó. Ví dụ: có thể có cc_prebuilt_binary có tên foo khi đã có cc_binary có cùng tên. Điều này mang lại cho các nhà phát triển sự linh hoạt trong việc chọn phiên bản nào sẽ đưa vào sản phẩm cuối cùng của họ. Nếu cấu hình bản dựng chứa cả hai phiên bản, giá trị cờ prefer trong định nghĩa mô-đun dựng sẵn sẽ cho biết phiên bản nào được ưu tiên. Lưu ý rằng một số mô-đun dựng sẵn có tên không bắt đầu bằng prebuilt , chẳng hạn như android_app_import .

Mô-đun không gian tên

Cho đến khi Android chuyển đổi hoàn toàn từ Make sang Soong, cấu hình Make sản phẩm phải chỉ định giá trị PRODUCT_SOONG_NAMESPACES . Giá trị của nó phải là danh sách các không gian tên được phân tách bằng dấu cách mà Soong xuất sang Make để được xây dựng bằng lệnh m . Sau khi quá trình chuyển đổi Android sang Soong hoàn tất, chi tiết về việc bật không gian tên có thể thay đổi.

Soong cung cấp khả năng cho các mô-đun trong các thư mục khác nhau chỉ định cùng một tên, miễn là mỗi mô-đun được khai báo trong một không gian tên riêng biệt. Một không gian tên có thể được khai báo như thế này:

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

Lưu ý rằng không gian tên không có thuộc tính tên; đường dẫn của nó được tự động gán làm tên của nó.

Mỗi mô-đun Soong được gán một không gian tên dựa trên vị trí của nó trong cây. Mỗi mô-đun Soong được coi là nằm trong không gian tên được xác định bởi soong_namespace được tìm thấy trong tệp Android.bp trong thư mục hiện tại hoặc thư mục tổ tiên gần nhất. Nếu không tìm thấy mô-đun soong_namespace như vậy, mô-đun đó được coi là nằm trong không gian tên gốc ẩn.

Đây là một ví dụ: Soong cố gắng giải quyết phần phụ thuộc D được mô-đun M khai báo trong không gian tên N nhập các không gian tên I1, I2, I3…

  1. Sau đó, nếu D là tên đủ điều kiện có dạng //namespace:module , thì chỉ tìm kiếm không gian tên đã chỉ định cho tên mô-đun đã chỉ định.
  2. Mặt khác, đầu tiên Soong tìm kiếm mô-đun có tên D được khai báo trong không gian tên N.
  3. Nếu mô-đun đó không tồn tại, Soong sẽ tìm mô-đun có tên D trong các không gian tên I1, I2, I3…
  4. Cuối cùng, Soong tìm trong không gian tên gốc.