Soong Build System

לפני שחרורו של אנדרואיד 7.0, אנדרואיד השתמשה ב- GNU Make באופן בלעדי כדי לתאר ולבצע את כללי הבנייה שלה. מערכת ה-Make build זוכה לתמיכה נרחבת ולשימוש נרחב, אך בקנה מידה של אנדרואיד הפכה לאטית, מועדת לשגיאות, בלתי ניתנת להרחבה וקשה לבדיקה. מערכת הבנייה של Soong מספקת את הגמישות הנדרשת עבור בניית אנדרואיד.

מסיבה זו, מפתחי פלטפורמות צפויים לעבור מ-Make ולאמץ את Soong בהקדם האפשרי. שלח שאלות לקבוצת Google המבוססת על אנדרואיד כדי לקבל תמיכה.

מה זה סונג?

מערכת הבנייה Soong הוצגה באנדרואיד 7.0 (Nougat) כדי להחליף את Make. הוא ממנף את כלי השיבוט Kati GNU Make ואת רכיב מערכת בניית Ninja כדי להאיץ את הבנייה של אנדרואיד.

עיין בתיאור מערכת ה-Android Make Build בפרויקט הקוד הפתוח של Android (AOSP) לקבלת הנחיות כלליות ושינויי מערכת עבור כותבי Android.mk כדי ללמוד על השינויים הדרושים להתאמה מ-Make to Soong.

ראה את הערכים הקשורים ל-build במילון המונחים להגדרות של מונחי מפתח ואת קובצי ההפניה של Soong לפרטים מלאים.

השוואת בצע וסונג

להלן השוואה בין יצירת תצורה ל-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,
           },
     },
}

ראה תצורת בנייה פשוטה לדוגמאות תצורת 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 Modules Reference .

סוגים

משתנים ומאפיינים מוקלדים בצורה חזקה, כאשר משתנים מבוססים באופן דינמי על ההקצאה הראשונה, ומאפיינים מוגדרים באופן סטטי על ידי סוג המודול. הסוגים הנתמכים הם:

  • בוליאניות ( true או false )
  • מספרים שלמים ( int )
  • מחרוזות ( "string" )
  • רשימות של מחרוזות ( ["string1", "string2"] )
  • מפות ( {key1: "value1", key2: ["value2"]} )

מפות עשויות להכיל ערכים מכל סוג, כולל מפות מקוננות. לרשימות ומפות עשויות להיות פסיקים עוקבים אחרי הערך האחרון.

גלובס

מאפיינים שלוקחים רשימה של קבצים, כגון srcs , יכולים גם לקבל דפוסי גלוב. תבניות גלוב יכולות להכיל את התו הכללי הרגיל של UNIX * , למשל *.java . תבניות גלוב יכולות להכיל גם תו כללי ** בודד כרכיב נתיב, המתאים לאפס או יותר רכיבי נתיב. לדוגמה, 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 יכולים // הערות /* */

מפעילים

ניתן להוסיף מחרוזות, רשימות של מחרוזות ומפות באמצעות האופרטור +. ניתן לסכם מספרים שלמים באמצעות האופרטור + . הוספת מפה מייצרת את איחוד המפתחות בשתי המפות, תוך הוספת הערכים של כל המפתחות הקיימים בשתי המפות.

תנאים

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 .

הפורמט הקנוני כולל כניסות של ארבע רווחים, שורות חדשות אחרי כל רכיב של רשימה מרובה אלמנטים ופסיק נגרר ברשימות ובמפות.

מודולים מיוחדים

לכמה קבוצות מודול מיוחדות יש מאפיינים ייחודיים.

ברירת המחדל של מודולים

ניתן להשתמש במודול ברירת מחדל כדי לחזור על אותם מאפיינים במספר מודולים. לדוגמה:

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 . לאחר השלמת ההמרה של אנדרואיד ל-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...

  1. אז אם D הוא שם מלא של הצורה //namespace:module , רק מרחב השמות שצוין יחפש את שם המודול שצוין.
  2. אחרת, Soong מחפש תחילה מודול בשם D המוצהר במרחב השמות N.
  3. אם המודול הזה לא קיים, Soong מחפש מודול בשם D במרחבי השמות I1, I2, I3...
  4. לבסוף, סונג מסתכל במרחב השמות של השורש.