ก่อนการเปิดตัว Android 7.0 นั้น Android ใช้ GNU Make เพื่ออธิบายและดำเนินการกฎการสร้างโดยเฉพาะ ระบบ Make build ได้รับการรองรับและใช้งานอย่างกว้างขวาง แต่ในระดับของ Android กลับช้า เสี่ยงต่อข้อผิดพลาด ไม่สามารถปรับขนาดได้ และทดสอบได้ยาก ระบบ Soong build มอบความยืดหยุ่นที่จำเป็นสำหรับรุ่น Android
ด้วยเหตุนี้ นักพัฒนาแพลตฟอร์มจึงควรเปลี่ยนจาก Make มาใช้ Soong โดยเร็วที่สุด ส่งคำถามไปที่ Google Group ที่สร้าง Android เพื่อรับการสนับสนุน
ซุงคืออะไร?
ระบบ Soong build เปิดตัวใน Android 7.0 (Nougat) เพื่อแทนที่ Make ใช้ประโยชน์จากเครื่องมือโคลน Kati GNU Make และส่วนประกอบระบบ Ninja build เพื่อเร่งความเร็วในการสร้าง Android
ดูคำอธิบาย Android Make Build System ใน Android Open Source Project (AOSP) สำหรับ คำแนะนำ ทั่วไปและ Build System Changes สำหรับ Android.mk Writers เพื่อเรียนรู้เกี่ยวกับการแก้ไขที่จำเป็นเพื่อปรับจาก Make เป็น Soong
ดู รายการที่เกี่ยวข้องกับการสร้าง ในอภิธานศัพท์สำหรับคำจำกัดความของคำศัพท์สำคัญและ ไฟล์อ้างอิง Soong สำหรับรายละเอียดทั้งหมด
เปรียบเทียบเมคกับซูง
นี่คือการเปรียบเทียบระหว่าง Make configuration กับ Soong ที่ทำสิ่งเดียวกันในไฟล์การกำหนดค่า Soong (Blueprint หรือ .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,
},
},
}
ดู การกำหนดค่า Simple Build สำหรับตัวอย่างการกำหนดค่า 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
ระบุไฟล์ต้นฉบับที่ใช้ในการสร้างโมดูลเป็นรายการสตริง คุณสามารถอ้างอิงผลลัพธ์ของโมดูลอื่นๆ ที่สร้างไฟล์ต้นฉบับ เช่น genrule
หรือ filegroup
ได้โดยใช้ไวยากรณ์อ้างอิงโมดูล ":<module-name>"
สำหรับรายการประเภทโมดูลที่ถูกต้องและคุณสมบัติ โปรดดูที่ การอ้างอิงโมดูล Soong
ประเภท
ตัวแปรและคุณสมบัติถูกพิมพ์อย่างชัดเจน โดยมีตัวแปรแบบไดนามิกตามการกำหนดครั้งแรก และคุณสมบัติตั้งค่าแบบคงที่ตามประเภทโมดูล ประเภทที่รองรับคือ:
- บูลีน (
true
หรือfalse
) - จำนวนเต็ม (
int
) - สตริง (
"string"
) - รายการสตริง (
["string1", "string2"]
) - แผนที่ (
{key1: "value1", key2: ["value2"]}
)
แผนที่อาจมีค่าประเภทใดก็ได้ รวมถึงแผนที่แบบซ้อน รายการและแผนที่อาจมีเครื่องหมายจุลภาคต่อท้ายหลังค่าสุดท้าย
ลูกโลก
คุณสมบัติที่รับรายการไฟล์ เช่น srcs
สามารถใช้รูปแบบ glob ได้เช่นกัน รูปแบบ Glob สามารถมีไวด์การ์ด UNIX ปกติ *
ได้ เช่น *.java
รูปแบบ Glob ยังสามารถมี **
wildcard เดียวเป็นองค์ประกอบเส้นทาง ซึ่งตรงกับองค์ประกอบเส้นทางเป็นศูนย์หรือมากกว่า ตัวอย่างเช่น java/**/*.java
จับคู่ทั้งรูปแบบ java/Main.java
และ java/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 มีตัวจัดรูปแบบมาตรฐานสำหรับไฟล์ Blueprint ซึ่งคล้ายกับ gofmt หากต้องการฟอร์แมตไฟล์ Android.bp
ทั้งหมดในไดเร็กทอรีปัจจุบันซ้ำ ๆ ให้รัน:
bpfmt -w .
รูปแบบ Canonical ประกอบด้วยการเยื้องสี่ช่องว่าง การขึ้นบรรทัดใหม่หลังทุกองค์ประกอบของรายการหลายองค์ประกอบ และเครื่องหมายจุลภาคต่อท้ายในรายการและแผนที่
โมดูลพิเศษ
กลุ่มโมดูลพิเศษบางกลุ่มมีลักษณะเฉพาะ
โมดูลเริ่มต้น
โมดูลเริ่มต้นสามารถใช้เพื่อทำซ้ำคุณสมบัติเดียวกันในหลายโมดูล ตัวอย่างเช่น:
cc_defaults {
name: "gzip_defaults",
shared_libs: ["libz"],
stl: "none",
}
cc_binary {
name: "gzip",
defaults: ["gzip_defaults"],
srcs: ["src/test/minigzip.c"],
}
โมดูลที่สร้างไว้ล่วงหน้า
โมดูลที่สร้างไว้ล่วงหน้าบางประเภทอนุญาตให้โมดูลมีชื่อเดียวกันกับโมดูลที่อิงตามแหล่งที่มา ตัวอย่างเช่น อาจมี cc_prebuilt_binary
ชื่อ foo
เมื่อมี cc_binary
ที่มีชื่อเดียวกันอยู่แล้ว สิ่งนี้ทำให้นักพัฒนามีความยืดหยุ่นในการเลือกเวอร์ชันที่จะรวมไว้ในผลิตภัณฑ์ขั้นสุดท้าย หากการกำหนดค่า build มีทั้งสองเวอร์ชัน ค่าแฟล็ก 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"],
}
โปรดทราบว่าเนมสเปซไม่มีคุณสมบัติของชื่อ เส้นทางของมันจะถูกกำหนดเป็นชื่อโดยอัตโนมัติ
แต่ละโมดูล Soong ได้รับการกำหนดเนมสเปซตามตำแหน่งในแผนผัง แต่ละโมดูล Soong จะถือว่าอยู่ในเนมสเปซที่กำหนดโดย soong_namespace
ที่พบในไฟล์ Android.bp
ในไดเร็กทอรีปัจจุบันหรือไดเร็กทอรีบรรพบุรุษที่ใกล้เคียงที่สุด หากไม่พบโมดูล soong_namespace
ดังกล่าว โมดูลจะถือว่าอยู่ในเนมสเปซรูทโดยนัย
นี่คือตัวอย่าง: Soong พยายามแก้ไขการพึ่งพา D ที่ประกาศโดยโมดูล M ในเนมสเปซ N ที่นำเข้าเนมสเปซ I1, I2, I3...
- จากนั้นถ้า D เป็นชื่อแบบเต็มของฟอร์ม
//namespace:module
จะค้นหาเฉพาะเนมสเปซที่ระบุเท่านั้นสำหรับชื่อโมดูลที่ระบุ - มิฉะนั้น Soong จะค้นหาโมดูลชื่อ D ที่ประกาศในเนมสเปซ N ก่อน
- หากไม่มีโมดูลนั้น Soong จะค้นหาโมดูลชื่อ D ในเนมสเปซ I1, I2, I3...
- สุดท้าย Soong จะดูในเนมสเปซรูท