קבצי Android.bp פשוטים מאוד. הם לא מכילים הצהרות של תנאים או של זרימת בקרה. כל המורכבות מטופלת על ידי לוגיקת בנייה שנכתבה ב-Go.
מודולים
מודול בקובץ 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 שנוצר על ידי הרצת m soong_docs. הפלט יהיה ב-out/soong/docs/soong_build.html.
סוגים
למשתנים ולמאפיינים יש הקלדה חזקה, כאשר המשתנים מבוססים באופן דינמי על ההקצאה הראשונה, והמאפיינים מוגדרים באופן סטטי לפי סוג המודול. הסוגים הנתמכים הם:
- ערכים בוליאניים (
trueאוfalse) - מספרים שלמים (
int) - מחרוזות (
"string") - רשימות של מחרוזות (
["string1", "string2"]) - מפות (
{key1: "value1", key2: ["value2"]})
מפות יכולות להכיל ערכים מכל סוג, כולל מפות במבנה היררכי. יכול להיות שיהיו פסיקים בסוף הרשימות והמפות אחרי הערך האחרון.
Globs
מאפיינים שמקבלים רשימה של קבצים, כמו 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",
}
המשתנים מוגבלים לשאר הקובץ שבו הם מוצהרים, וגם לכל קובץ Blueprint צאצא. המשתנים הם בלתי ניתנים לשינוי, למעט מקרה אחד: אפשר להוסיף להם ערך באמצעות הקצאת +=, אבל רק לפני שמתבצעת הפניה אליהם.
תגובות
קבצים של Android.bp יכולים להכיל הערות /* */ מרובות שורות בסגנון C והערות // של שורה אחת בסגנון C++.
מפעילים
אפשר להוסיף מחרוזות, רשימות של מחרוזות ומפות באמצעות האופרטור +.
אפשר לחשב סכום של מספרים שלמים באמצעות האופרטור +. הוספה של מפה יוצרת איחוד של המפתחות בשתי המפות, והוספה של הערכים של כל המפתחות שקיימים בשתי המפות.
מודולים של ברירות מחדל
מפתחים יכולים להשתמש במודול ברירת מחדל כדי לחזור על אותם מאפיינים בכמה מודולים. לדוגמה:
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, צריך לציין ערך PRODUCT_SOONG_NAMESPACES בהגדרת המוצר ב-Make. הערך שלו צריך להיות רשימה של מרחבי שמות שמופרדים ברווחים, ש-Soong מייצא ל-Make כדי לבנות אותם באמצעות הפקודה m. אחרי שההמרה של Android ל-Soong תושלם, יכול להיות שפרטי ההפעלה של מרחבי השמות ישתנו.
מערכת Soong מאפשרת למודולים בספריות שונות לציין את אותו שם, כל עוד כל מודול מוצהר במרחב שמות נפרד. מפתחים יכולים להצהיר על מרחב שמות:
soong_namespace {
imports: ["path/to/otherNamespace1", "path/to/otherNamespace2"],
}
שימו לב שלמרחב שמות אין מאפיין name, והנתיב שלו מוקצה אוטומטית כשם שלו.
לכל מודול Soong מוקצה מרחב שמות על סמך המיקום שלו בעץ.
כל מודול Soong נחשב כחלק ממרחב השמות שמוגדר על ידי soong_namespace שנמצא בקובץ Android.bp בספרייה הנוכחית או בספרייה הקרובה ביותר ברמת האב. אם לא נמצא מודול soong_namespace כזה, המודול נחשב כנמצא במרחב השמות הבסיסי המרומז.
לדוגמה: סונג מנסה לפתור את התלות D שהוגדרה על ידי המודול M במרחב השמות N שמייבא את מרחבי השמות I1, I2, I3…
- אם D הוא שם מוגדר במלואו מהצורה
//namespace:module, החיפוש יתבצע רק במרחב השמות שצוין עבור שם המודול שצוין. - אחרת, Soong יחפש קודם מודול בשם D שהוגדר במרחב השמות N.
- אם המודול הזה לא קיים, Soong מחפש מודול בשם D במרחבי השמות I1, I2, I3…
- מערכת Soong מחפשת במרחב השמות הבסיסי.
משפטי תנאי
Soong לא תומך בתנאים בקובצי Android.bp. במקום זאת, מורכבות בכללי בנייה שדורשים תנאים מטופלת ב-Go, שבה אפשר להשתמש בתכונות שפה ברמה גבוהה, ולעקוב אחרי תלות משתמעת שנוצרת על ידי תנאים. רוב התנאים מומרים למאפיין מיפוי, שבו אחד מהערכים במיפוי נבחר ומצורף למאפיינים ברמה העליונה.
לדוגמה, כדי לתמוך בקבצים ספציפיים לארכיטקטורה:
cc_library {
...
srcs: ["generic.cpp"],
arch: {
arm: {
srcs: ["arm.cpp"],
},
x86: {
srcs: ["x86.cpp"],
},
},
}
Formatter
Soong כולל מעצב קנוני לקובצי Blueprint, בדומה ל-gofmt. כדי לפרמט מחדש באופן רקורסיבי את כל הקבצים Android.bp בספרייה הנוכחית, מריצים את הפקודה:
bpfmt -w .
הפורמט הקנוני כולל הזחות של ארבעה רווחים, שורות חדשות אחרי כל רכיב ברשימה מרובת רכיבים ופסיק בסוף רשימות ומפות.