אם אתם לא משתמשים ב-CMake או ב-ndk-build אבל רוצים שילוב מלא של Android Gradle Plugin (AGP) ל-C/C++ ו-Android Studio, אתם יכולים ליצור מערכת build מותאמת אישית ל-C/C++ על ידי יצירת סקריפט מעטפת שכותב את פרטי ה-build בפורמט קובץ ה-build של Ninja.
נוספה תמיכה ניסיונית במערכות build בהתאמה אישית של C/C++ ל-Android Studio ול-AGP. התכונה הזו זמינה החל מגרסה Android Studio Dolphin | 2021.3.1 Canary 4.
סקירה כללית
דפוס נפוץ בפרויקטים של C/C++, במיוחד בפרויקטים שמטרגטים כמה פלטפורמות, הוא ליצור פרויקטים לכל אחת מהפלטפורמות האלה מתוך ייצוג בסיסי כלשהו.
דוגמה בולטת לתבנית הזו היא CMake. CMake יכול ליצור פרויקטים ל-Android, ל-iOS ולפלטפורמות אחרות מתוך ייצוג בסיסי יחיד שנשמר בקובץ CMakeLists.txt
.
AGP תומך ישירות ב-CMake, אבל יש גנרטורים אחרים של פרויקטים שאינם נתמכים ישירות:
סוגי הגנרטורים האלה תומכים ב-Ninja כמייצג לקצה העורפי של ה-build ב-C/C++ או שניתן להתאים אותם ליצירת Ninja כמייצג לקצה העורפי.
כשפרויקט AGP מוגדר בצורה נכונה עם גנרטור משולב של מערכת פרויקטים ב-C/C++, המשתמשים יכולים:
פיתוח מתוך שורת הפקודה ומ-Android Studio.
עריכת מקורות עם תמיכה מלאה בשירותי השפה (לדוגמה, הגדרה מוגדרת מראש) ב-Android Studio.
שימוש בניפוי הבאגים של Android Studio כדי לנפות באגים בתהליכים מקומיים ובתהליכים מעורבים.
איך משנים את ה-build כך שישתמש בסקריפט מותאם אישית של הגדרות build ב-C/C++
בקטע הזה מוסבר איך להשתמש בסקריפט מותאם אישית של הגדרות build ב-C/C++ מ-AGP.
שלב 1: משנים את הקובץ build.gradle
ברמת המודול כך שיפנה לסקריפט תצורה
כדי להפעיל תמיכה ב-Ninja ב-AGP, מגדירים את experimentalProperties
בקובץ build.gradle
ברמת המודול:
android {
defaultConfig {
externalNativeBuild {
experimentalProperties["ninja.abiFilters"] = [ "x86", "arm64-v8a" ]
experimentalProperties["ninja.path"] = "source-file-list.txt"
experimentalProperties["ninja.configure"] = "configure-ninja"
experimentalProperties["ninja.arguments"] = [
"\${ndk.moduleMakeFile}",
"--variant=\${ndk.variantName}",
"--abi=Android-\${ndk.abi}",
"--configuration-dir=\${ndk.configurationDir}",
"--ndk-version=\${ndk.moduleNdkVersion}",
"--min-sdk-version=\${ndk.minSdkVersion}"
]
}
}
מערכת AGP מפרשת את המאפיינים באופן הבא:
ninja.abiFilters
היא רשימה של ממשקי ABI ליצירה. הערכים התקפים הם:x86
,x86-64
,armeabi-v7a
ו-arm64-v8a
.ninja.path
הוא נתיב לקובץ פרויקט ב-C/C++. הפורמט של הקובץ הזה יכול להיות כל מה שתרצו. שינויים בקובץ הזה יגרמו להצגת הודעה על סנכרון Gradle ב-Android Studio.ninja.configure
הוא נתיב לקובץ סקריפט שיופעל על ידי Gradle כשצריך להגדיר את הפרויקט ב-C/C++. הפרויקט מוגדר ב-build הראשון, במהלך סנכרון Gradle ב-Android Studio או כשאחד מהקלטים של סקריפט ההגדרה משתנה.ninja.arguments
היא רשימת ארגומנטים שתועברו לסקריפט שמוגדר על ידי ninja.configure. רכיבים ברשימה הזו יכולים להפנות לקבוצת מאקרו שהערכים שלה תלויים בהקשר התצורה הנוכחי ב-AGP:${ndk.moduleMakeFile}
הוא הנתיב המלא לקובץninja.configure
. בדוגמה הזו, זה יהיהC:\path\to\configure-ninja.bat
.${ndk.variantName}
הוא השם של גרסת ה-AGP הנוכחית שנוצרת. לדוגמה, ניפוי באגים או פרסום.${ndk.abi}
הוא השם של AGP ABI הנוכחי שנוצר. לדוגמה,x86
אוarm64-v8a
.
${ndk.buildRoot}
הוא שם התיקייה שנוצרה על ידי AGP, שבה הסקריפט כותב את הפלט שלו. פרטים נוספים מופיעים בקטע שלב 2: יצירת סקריפט ההגדרה.${ndk.ndkVersion}
היא הגרסה של NDK שבה צריך להשתמש. בדרך כלל זהו הערך שמוענק ל-android.ndkVersion בקובץbuild.gradle
, או ערך ברירת מחדל אם לא קיים ערך.${ndk.minPlatform}
היא פלטפורמת היעד המינימלית ל-Android שנדרשת על ידי AGP.
ninja.targets
היא רשימה של יעדי Ninja הספציפיים שצריך ליצור.
שלב 2: יוצרים את סקריפט ההגדרה
האחריות המינימלית של סקריפט התצורה (configure-ninja.bat
בדוגמה הקודמת) היא ליצור קובץ build.ninja
, שבזמן ה-build עם Ninja יתבצע בו הידור וקישור של כל הפלטים המקומיים של הפרויקט. בדרך כלל אלה קבצים מסוג .o
(אובייקט), .a
(ארכיון) ו-.so
(אובייקט משותף).
סקריפט ההגדרה יכול לכתוב את הקובץ build.ninja
בשני מקומות שונים, בהתאם לצרכים שלכם.
אם מותר ל-AGP לבחור מיקום, סקריפט ההגדרה יכתוב את הערך
build.ninja
במיקום שהוגדר במאקרו${ndk.buildRoot}
.אם סקריפט התצורה צריך לבחור את המיקום של קובץ
build.ninja
, הוא גם יכתוב קובץ בשםbuild.ninja.txt
במיקום שהוגדר במאקרו${ndk.buildRoot}
. הקובץ הזה מכיל את הנתיב המלא לקובץbuild.ninja
שסקריפט התצורה כתב.
המבנה של הקובץ build.ninja
באופן כללי, רוב המבנים שמייצגים בצורה מדויקת גרסה של Android שנוצרה באמצעות C/C++ יפעלו. הרכיבים העיקריים הנדרשים ל-AGP ול-Android Studio הם:
רשימת קובצי המקור של C/C++ יחד עם הדגלים הנדרשים ל-Clang כדי לקמפל אותם.
רשימת ספריות הפלט. בדרך כלל אלה קובצי
.so
(אובייקט משותף), אבל הם יכולים להיות גם קובצי.a
(ארכיון) או קובצי הפעלה (ללא סיומת).
אם אתם צריכים דוגמאות ליצירת קובץ build.ninja
, אתם יכולים לעיין בפלט של CMake כשמשתמשים בגנרטור build.ninja
.
דוגמה לתבנית build.ninja
מינימלית.
rule COMPILE
command = /path/to/ndk/clang -c $in -o $out {other flags}
rule LINK
command = /path/to/ndk/clang $in -o $out {other flags}
build source.o : COMPILE source.cpp
build lib.so : LINK source.o
שיטות מומלצות
בנוסף לדרישות (רשימת קובצי המקור וספריות הפלט), ריכזנו כאן כמה שיטות מומלצות.
הצהרה על משתני פלט עם שמות באמצעות כללי phony
כשהדבר אפשרי, מומלץ להשתמש בכללי phony
במבנה build.ninja
כדי לתת לשמות של הפלט של ה-build שמות שאנשים יכולים לקרוא. לדוגמה, אם יש לכם פלט בשם c:/path/to/lib.so
, אתם יכולים לתת לו שם קריא באופן הבא.
build curl: phony /path/to/lib.so
היתרון של כך הוא שתוכלו לציין את השם הזה כיעד build בקובץ build.gradle
. לדוגמה,
android {
defaultConfig {
externalNativeBuild {
...
experimentalProperties["ninja.targets"] = [ "curl" ]
ציון יעד 'הכול'
כשמציינים יעד all
, זו תהיה קבוצת ברירת המחדל של הספריות שייווצרו על ידי AGP אם לא יצוינו יעדים באופן מפורש בקובץ build.gradle
.
rule COMPILE
command = /path/to/ndk/clang $in -o $out {other flags}
rule LINK
command = /path/to/ndk/clang $in -o $out {other flags}
build foo.o : COMPILE foo.cpp
build bar.o : COMPILE bar.cpp
build libfoo.so : LINK foo.o
build libbar.so : LINK bar.o
build all: phony libfoo.so libbar.so
ציון שיטת build חלופית (אופציונלי)
תרחיש לדוגמה מתקדם יותר הוא גיבוב של מערכת build קיימת שלא מבוססת על Ninja. במקרה כזה, עדיין צריך לייצג את כל המקורות עם הדגלים שלהם יחד עם ספריות הפלט, כדי ש-Android Studio יוכל להציג את התכונות המתאימות של שירות השפה, כמו השלמה אוטומטית והעברה להגדרה. עם זאת, אתם רוצים ש-AGP יפנה למערכת ה-build הבסיסית במהלך ה-build בפועל.
כדי לעשות זאת, אפשר להשתמש בפלט של build ב-Ninja עם סיומת ספציפית .passthrough
.
דוגמה קונקרטית יותר: נניח שאתם רוצים לעטוף MSBuild. סקריפט התצורה ייצור את build.ninja
כרגיל, אבל הוא גם יוסיף יעד העברה שמגדיר איך AGP יפעיל את MSBuild.
rule COMPILE
command = /path/to/ndk/clang $in -o $out {other flags}
rule LINK
command = /path/to/ndk/clang $in -o $out {other flags}
rule MBSUILD_CURL
command = /path/to/msbuild {flags to build curl with MSBuild}
build source.o : COMPILE source.cpp
build lib.so : LINK source.o
build curl : phony lib.so
build curl.passthrough : MBSUILD_CURL
שליחת משוב
התכונה הזו ניסיונית, ולכן נשמח לקבל ממך משוב. אתם יכולים לשלוח משוב דרך הערוצים הבאים:
כדי לשלוח משוב כללי, אפשר להוסיף תגובה לבאג הזה.
כדי לדווח על באג, פותחים את Android Studio ולוחצים על עזרה > שליחת משוב. חשוב לעיין במאמר 'מערכות build מותאמות אישית של C/C++' כדי לעזור לנו לכוון את הבאג.
אם לא התקנתם את Android Studio, תוכלו לדווח על באג באמצעות התבנית הזו.