Android NDK תומך בשימוש ב-CMake כדי
להדר את קוד C ו-C++ לאפליקציה שלכם. בדף הזה מוסבר איך משתמשים
CMake באמצעות NDK באמצעות ExternalNativeBuild
של הפלאגין של Android Gradle או כאשר
בהפעלה ישירה של CMake.
קובץ ה-toolchain של CMake
NDK תומך ב-CMake באמצעות קובץ Toolchain. קובצי Toolchain הם קובצי CMake
להתאמה אישית של ההתנהגות של ה-toolchain לביצוע הידור מוצלב. שרשרת הכלים
משמש עבור ה-NDK נמצא ב-NDK ב-
<NDK>/build/cmake/android.toolchain.cmake
פרמטרים של build כמו ABI , minSdkVersion
וכו' ניתנים בפקודה
כשמפעילים את cmake
. לרשימת ארגומנטים נתמכים אפשר לעיין במאמר
הקטע Toolchain instances.
"החדש" קובץ Toolchain
בשלב מוקדם יותר, קבוצות NDK ניסו הטמעה חדשה של קובץ Toolchain יצמצם את ההבדלים בהתנהגות בין השימוש בקובץ ה-toolchain של ה-NDK באמצעות התמיכה המובנית של CMake. בסופו של דבר, נדרש נפח משמעותי עבודה (שלא הושלמה), אבל לא שיפרה בפועל את ההתנהגות, ולכן אנחנו כבר לא מטפלים בנושא הזה.
"החדש" לקובץ Toolchain יש רגרסיות של התנהגות בהשוואה לקובץ ה-toolchain "מדור קודם".
Toolchain. פעולת ברירת המחדל היא תהליך העבודה המומלץ. אם אתם
באמצעות -DANDROID_USE_LEGACY_TOOLCHAIN_FILE=OFF
, אנחנו ממליצים להסיר את הדגל הזה
מה-build שלך. קובץ ה-toolchain החדש מעולם לא זהה לזה של הגרסה הקודמת
קובץ Toolchain, ולכן סביר להניח שיש רגרסיות של התנהגות.
למרות שמומלץ לא להשתמש בקובץ Toolchain החדש, אין כרגע להסיר אותו מה-NDK. פעולה כזו תפגע בגרסאות build שמסתמכות על את ההבדלים בהתנהגות בין קובצי ה-toolchain החדשים לקבצים הקודמים, למרבה הצער, שינוי השם של האפשרות כדי להבהיר ש"מדור קודם" הוא למעשה מומלץ גם לגרום נזק למשתמשים באפשרות הזו. אם אתם שמחים להשתמש את קובץ ה-toolchain החדש שאין צורך להעביר, אבל חשוב לדעת שיש באגים ההתנהגות החדשה של קובץ ה-toolchain לא תטופל, ובמקום זאת שתצטרכו לבצע את ההעברה.
שימוש
גרדל
השימוש בקובץ Toolchain של CMake הוא אוטומטי כשמשתמשים
externalNativeBuild
צפייה בקטעים הוספת קוד C ו-C++ של Android Studio
לקבלת מידע נוסף על הפרויקט.
שורת הפקודה
כשמפתחים באמצעות CMake מחוץ ל-Gradle, קובץ ה-toolchain עצמו יש להעביר את הארגומנטים שלו ל-CMake. לדוגמה:
$ cmake \
-DCMAKE_TOOLCHAIN_FILE=$NDK/build/cmake/android.toolchain.cmake \
-DANDROID_ABI=$ABI \
-DANDROID_PLATFORM=android-$MINSDKVERSION \
$OTHER_ARGS
ארגומנטים של 'צרור כלים'
ניתן להעביר את הארגומנטים הבאים לקובץ Toolchain של CMake. אם יוצרים
עם Gradle, מוסיפים ארגומנטים
android.defaultConfig.externalNativeBuild.cmake.arguments
כפי שמתואר
מסמכי ExternalNativeBuild אם בונים משורת הפקודה, מעבירים את הארגומנטים
יוצרים ביחד עם -D
. לדוגמה, כדי לאלץ את Armeabi-v7a לא לבנות באמצעות ניאון
תמיכה, צריך להעביר את -DANDROID_ARM_NEON=FALSE
.
ANDROID_ABI
ממשק ה-ABI של היעד. מידע נוסף על ממשקי ABI נתמכים מופיע במאמר ממשקי ABI של Android.
גרדל
הארגומנט הזה מופיע ב-Gradle באופן אוטומטי. לא להגדיר במפורש
ארגומנט בקובץ build.gradle
. כדי לקבוע לאילו יעדים של ABIs Gradle:
להשתמש ב-abiFilters
כפי שמתואר בממשקי ABI של Android.
שורת הפקודה
יצירת גרסאות build ליעד אחד בכל build. כדי לטרגט ליותר ממכשיר Android אחד צריך ליצור ממשק ABI פעם אחת לכל ABI. מומלץ להשתמש בגרסת build אחרת של כל ממשק ABI כדי למנוע התנגשויות בין גרסאות build.
ערך | הערות |
---|---|
armeabi-v7a |
|
armeabi-v7a with NEON |
בדיוק כמו במלון armeabi-v7a . |
arm64-v8a |
|
x86 |
|
x86_64 |
ANDROID_ARM_MODE
המדיניות קובעת אם ליצור הוראות לזרוע או לזרוע הבקרה עבור Armeabi-v7a. לא השפעה על ממשקי ABI אחרים. מידע נוסף זמין במאמר ממשקי ABI של Android התיעוד.
ערך | הערות |
---|---|
זרוע | |
אגודל | פעולת ברירת המחדל. |
ANDROID_NATIVE_API_LEVEL
כינוי עבור ANDROID_PLATFORM.
ANDROID_PLATFORM
מציינת את רמת ה-API המינימלית שנתמכת על ידי האפליקציה או הספרייה. הזה
תואם לערך minSdkVersion
של האפליקציה.
גרדל
כשמשתמשים בפלאגין Android Gradle, הערך הזה מוגדר באופן אוטומטי בתור
תואם ל-minSdkVersion
של האפליקציה ואין להגדיר אותו באופן ידני.
שורת הפקודה
כשמפעילים את CMake ישירות, הערך הזה מוגדר כברירת מחדל לרמת ה-API הנמוכה ביותר. נתמך על ידי ה-NDK בשימוש. לדוגמה, עם NDK r20, הערך הזה מוגדר כברירת מחדל לרמת API 16.
אפשר להזין את הפרמטר הזה בכמה פורמטים:
android-$API_LEVEL
$API_LEVEL
android-$API_LETTER
הפורמט $API_LETTER
מאפשר לציין את android-N
בלי
לקבוע את המספר שמשויך לגרסה הזו. שימו לב שבחלק מהגרסאות
קיבלה עלייה ב-API ללא הגדלה של אות. אפשר לציין את ממשקי ה-API האלה
על ידי הוספת הסיומת -MR1
. לדוגמה, רמת API 25 היא android-N-MR1
.
ANDROID_STL
מציינת באיזה STL להשתמש עבור האפליקציה הזו. למידע נוסף, ראה C++
תמיכה בספריות. כברירת מחדל, ייעשה שימוש ב-c++_static
.
ערך | הערות |
---|---|
c++_shared | גרסת הספרייה המשותפת של libc++. |
c++_static | גרסת הספרייה הסטטית של libc++. |
ללא | אין תמיכה בספריות רגילות ב-C++. |
מערכת | STL של המערכת |
ניהול דגלי מהדר
אם אתם צריכים להעביר דגלים ספציפיים ל-compiler או ל-linker ב-build שלכם, לעיין במסמכי התיעוד של CMake בשביל set_target_compile_options כמה אפשרויות קשורות. הקטע "למידע נוסף" בחלק התחתון של הדף יש את רמזים שימושיים.
באופן כללי, השיטה המומלצת היא להחיל דגלים מהדר
היקף זמין. הסימונים שרוצים להחיל על כל היעדים (כמו
-Werror
) לא נוחות לחזור על כל מודול, אבל הן עדיין צריכות להתרחש רק לעיתים רחוקות
מוחלות באופן גלובלי (CMAKE_CXX_FLAGS
), כי עלולות להיות להן השפעות לא רצויות על
ויחסי תלות עם צדדים שלישיים בפרויקט שלכם. במקרים כאלה, הדגלים יכולים להיות
ברמת הספרייה (add_compile_options
).
בשביל קבוצת משנה מצומצמת של דגלי מהדר, אפשר להגדיר אותם גם ב-build.gradle
באמצעות cppFlags
או מאפיינים דומים. אין לעשות את זה. דגלים
שיועברו ל-CMake מ-Gradle יהיו התנהגות קדימות מפתיעה,
מקרים שמחליפים דגלים שמועברים במרומז על ידי ההטמעה,
שנדרש ליצירה של קוד Android. עדיף תמיד לטפל בהתנהגות של CMake
ישירות ב-CMake. אם אתם צריכים לשלוט בדגלי מהדר לכל AGP buildType
,
למידע נוסף, אפשר לעיין במאמר עבודה עם סוגי build של AGP ב-CMake.
עבודה עם סוגי build של AGP ב-CMake
אם אתם צריכים להתאים את ההתנהגות של CMake ל-Gradle buildType
בהתאמה אישית, אפשר להשתמש
build כדי להעביר דגל CMake נוסף (לא דגל מהדר) ש
CMake סקריפטים של build יכולים לקרוא. לדוגמה, אם הזנת את המילה 'חינם', ו'פרימיום'
ליצור וריאנטים שנשלטים על ידי build.gradle.kts, וצריך להעביר
שהנתונים האלה ל-CMake:
android {
buildTypes {
free {
externalNativeBuild {
cmake {
arguments.add("-DPRODUCT_VARIANT_PREMIUM=OFF")
}
}
}
premium {
externalNativeBuild {
cmake {
arguments.add("-DPRODUCT_VARIANT_PREMIUM=ON")
}
}
}
}
}
לאחר מכן, ב-CMakeLists.txt:
if (DPRODUCT_VARIANT_PREMIUM)
# Do stuff for the premium build.
else()
# Do stuff for the free build.
endif()
שם המשתנה תלוי בכם, אבל חשוב להימנע ממילים עם
קידומת ANDROID_
, APP_
או CMAKE_
כדי למנוע התנגשות או בלבול עם
דגלים קיימים.
אפשר לראות דוגמה בדוגמה של Sanitizers NDK.
הסבר על הפקודה של CMake build
במהלך ניפוי באגים של CMake, כדאי לדעת מהו ה-build הספציפי ארגומנטים שבהם Gradle משתמשת במהלך הידור צולב ל-Android.
הפלאגין Android Gradle שומר את ארגומנטים של ה-build שבהם הוא משתמש כדי לבצע
יצירת גרסת build לכל ממשק ABI וסוג build
מתאימים ל-build_command.txt
. הקבצים האלה נמצאים במקומות הבאים
ספרייה:
<project-root>/<module-root>/.cxx/cmake/<build-type>/<ABI>/
קטע הקוד הבא מציג דוגמה לארגומנטים של CMake כדי ליצור
גרסה של hello-jni
שמיועדת לניפוי באגים ומטרגטת את armeabi-v7a
של הארכיטקטורה,
Executable : ${HOME}/Android/Sdk/cmake/3.10.2.4988404/bin/cmake
arguments :
-H${HOME}/Dev/github-projects/googlesamples/ndk-samples/hello-jni/app/src/main/cpp
-DCMAKE_FIND_ROOT_PATH=${HOME}/Dev/github-projects/googlesamples/ndk-samples/hello-jni/app/.cxx/cmake/universalDebug/prefab/armeabi-v7a/prefab
-DCMAKE_BUILD_TYPE=Debug
-DCMAKE_TOOLCHAIN_FILE=${HOME}/Android/Sdk/ndk/22.1.7171670/build/cmake/android.toolchain.cmake
-DANDROID_ABI=armeabi-v7a
-DANDROID_NDK=${HOME}/Android/Sdk/ndk/22.1.7171670
-DANDROID_PLATFORM=android-23
-DCMAKE_ANDROID_ARCH_ABI=armeabi-v7a
-DCMAKE_ANDROID_NDK=${HOME}/Android/Sdk/ndk/22.1.7171670
-DCMAKE_EXPORT_COMPILE_COMMANDS=ON
-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=${HOME}/Dev/github-projects/googlesamples/ndk-samples/hello-jni/app/build/intermediates/cmake/universalDebug/obj/armeabi-v7a
-DCMAKE_RUNTIME_OUTPUT_DIRECTORY=${HOME}/Dev/github-projects/googlesamples/ndk-samples/hello-jni/app/build/intermediates/cmake/universalDebug/obj/armeabi-v7a
-DCMAKE_MAKE_PROGRAM=${HOME}/Android/Sdk/cmake/3.10.2.4988404/bin/ninja
-DCMAKE_SYSTEM_NAME=Android
-DCMAKE_SYSTEM_VERSION=23
-B${HOME}/Dev/github-projects/googlesamples/ndk-samples/hello-jni/app/.cxx/cmake/universalDebug/armeabi-v7a
-GNinja
jvmArgs :
Build command args: []
Version: 1
שימוש בספריות מוכנות מראש
אם הספרייה המובנית מראש שצריך לייבא מופצת כ-AAR, צריך לפעול לפי מסמכי התלות של Studio כדי לייבא אותם ולהשתמש בהם. אם לא משתמשים ב-AGP, אפשר לעקוב אחר https://google.github.io/prefab/example-workflow.html, אבל סביר להניח שיש הרבה קל יותר לעבור ל-AGP.
לגבי ספריות שלא מופצות כ-AAR, יש הוראות בנוגע לשימוש
לספריות עם CMake, יש לעיין בתיעוד של add_library
בנוגע ל-IMPORTED
יעדים במדריך ל-CMake.
פיתוח קוד של צד שלישי
יש כמה דרכים לפתח קוד של צד שלישי כחלק מ-CMake ולבחור מבין האפשרויות המתאימות ביותר בהתאם למצב שלכם. הטוב ביותר תהיה בדרך כלל לא לעשות את זה בכלל. במקום זאת, יוצרים AAR עבור ו צורכים אותם באפליקציה שלכם. אתם לא חייבים לפרסם את המלצות ה-AAR. היא יכולה להיות פנימית בפרויקט Gradle שלכם.
אם זה לא אפשרי:
- לספק (כלומר, להעתיק) את המקור של הצד השלישי למאגר שלכם ולהשתמש בו add_subdirectory כדי לבנות אותו. זה פועל רק אם הספרייה השנייה שנוצרו באמצעות CMake.
- מגדירים ExternalProject (פרויקט חיצוני).
- בונים את הספרייה בנפרד מהפרויקט ופועלים לפי ההוראות אפשר להשתמש בספריות מוכנות מראש כדי לייבא את הקובץ כתוכן שנוצר מראש.
תמיכה ב-YASM ב-CMake
NDK מספק תמיכה ב-CMake בקוד להרכבת מבנים שכתוב ב- YASM כדי להריץ ב-x86 וב-x86-64 של הארכיטקטורה, YASM הוא כלי הרכבה בקוד פתוח של x86 ו-x86-64 של ארכיטקטורת NASM.
כדי לבנות קוד הרכבה באמצעות CMake, מבצעים את השינויים הבאים בפרויקט
CMakeLists.txt
:
- קוראים לפונקציה
enable_language
שהערך שלו מוגדר ל-ASM_NASM
. - תלוי אם בונים ספרייה משותפת או קובץ הפעלה
בינארי, קוראים לפונקציה
add_library
אוadd_executable
. לחשבון את הארגומנטים, מעבירים ברשימה של קובצי מקור שמורכבת מקובצי.asm
לתוכנית ההרכבה ב-YASM ולקובצי.c
של ה-C המשויך של ספריות או פונקציות.
קטע הקוד הבא מראה איך אפשר להגדיר את CMakeLists.txt
ליצור תוכנית YASM כספרייה משותפת.
cmake_minimum_required(VERSION 3.6.0)
enable_language(ASM_NASM)
add_library(test-yasm SHARED jni/test-yasm.c jni/print_hello.asm)
דוגמה לאופן שבו אפשר לפתח תוכנת YASM כקובץ הפעלה, זמינה ב-yasm לביצוע הבדיקה במאגר ה-GIT של NDK.
דיווח על בעיות
אם נתקלתם בבעיות ב-NDK או בקובץ ה-toolchain של CMake, אפשר לדווח עליהן דרך הכלי למעקב אחרי בעיות android-ndk/ndk ב-GitHub. ל-Gradle או אם יש בעיות בפלאגין Android Gradle, אפשר לדווח על באג ב-Studio במקום זאת.