הגדרת CMake

סקריפט CMake הוא קובץ טקסט פשוט שצריך לתת לו שם CMakeLists.txt, וכולל פקודות שבהן CMake משתמש כדי לבנות ספריות C/C++. אם למקורות המותאמים שלכם אין עדיין build של CMake עליך ליצור אחד בעצמך ולכלול את CMake המתאים פקודות. מידע נוסף על התקנת CMake זמין במאמר התקנה והגדרה של ה-NDK ו-CMake.

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

אחרי שמגדירים סקריפט build חדש ל-CMake, צריך: איך מגדירים את Gradle לכלול את פרויקט CMake כתלות ב-build, כך ש-Gradle יבנה אורז את הספרייה המקורית עם ה-APK של האפליקציה.

הערה: אם בפרויקט שלכם נעשה שימוש ב-ndk-build, אין צורך יוצרים סקריפט build ל-CMake. אתם יכולים פשוט הגדרת Gradle לכלול את פרויקט הספרייה המקורית הקיימת, על ידי מתן נתיב Android.mk.

יצירת סקריפט build ל-CMake

כדי ליצור קובץ טקסט פשוט שאפשר להשתמש בו כסקריפט build של CMake, כך עושים את זה:

  1. פותחים את החלונית Project (פרויקט) מהצד השמאלי של סביבת הפיתוח המשולבת (IDE) ובוחרים את תצוגה פרויקט בתפריט הנפתח.
  2. לוחצים לחיצה ימנית על תיקיית השורש של your-module. בוחרים באפשרות חדש > קובץ.

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

  3. מזינים 'CMakeLists.txt'. בתור שם הקובץ ולוחצים על אישור.

עכשיו אפשר להגדיר את סקריפט ה-build על ידי הוספת פקודות CMake. כדי ללמד CMake כדי ליצור ספרייה נייטיב מקוד מקור מותאם, מוסיפים את הפקודות cmake_minimum_required() ו-add_library() לסקריפט ה-build:

# Sets the minimum version of CMake required to build your native library.
# This ensures that a certain set of CMake features is available to
# your build.

cmake_minimum_required(VERSION 3.4.1)

# Specifies a library name, specifies whether the library is STATIC or
# SHARED, and provides relative paths to the source code. You can
# define multiple libraries by adding multiple add_library() commands,
# and CMake builds them for you. When you build your app, Gradle
# automatically packages shared libraries with your APK.

add_library( # Specifies the name of the library.
             native-lib

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             src/main/cpp/native-lib.cpp )

טיפ: בדומה לאופן שבו אפשר לומר ל-CMake, ליצור ספרייה מותאמת מ- קובצי מקור, אפשר להשתמש הפקודה add_executable() כדי להנחות את CMake ליצור במקום זאת להפעלה מקובצי המקור האלה. אבל כשיוצרים קובצי הפעלה השימוש במקורות מותאמים הוא אופציונלי, ויש צורך לבנות ספריות מקוריות לארוז לתוך ה-APK עומד ברוב הדרישות של הפרויקטים.

כשמוסיפים קובץ מקור או ספרייה לסקריפט build של CMake באמצעות add_library(), ב-Android Studio מוצגים גם קובצי כותרות משויכים בתצוגה Project (פרויקט) אחרי שמסנכרנים את הפרויקט. אבל, בעוד כדי ש-CMake יאתר את קובצי הכותרות במהלך זמן ההרכבה, צריך מוסיפים את הפקודה include_directories() ל-CMake build וציון הנתיב לכותרות:

add_library(...)

# Specifies a path to native header files.
include_directories(src/main/cpp/include/)

המוסכמה שבה משתמשים ב-CMake כדי לתת שם לקובץ בספרייה:

liblibrary-name.so

לדוגמה, אם מציינים 'native-lib' בתור שם הספרייה המשותפת בסקריפט ה-build, CMake יוצר קובץ בשם libnative-lib.so עם זאת, כשטוענים את הספרייה הזו בקוד Java או Kotlin, צריך להשתמש בשם שציינתם בסקריפט של CMake build:

Kotlin

companion object {
    init {
        System.loadLibrary("native-lib");
    }
}

Java

static {
    System.loadLibrary("native-lib");
}

הערה: אם משנים שם של ספרייה או מסירים אותה ב-build של CMake, עליכם לנקות את הפרויקט לפני ש-Gradle יחיל את השינויים מסיר את הגרסה הישנה יותר של הספרייה מה-APK. כדי לנקות את פרויקט, בוחרים Build > ניקוי הפרויקט בסרגל התפריטים.

Android Studio מוסיף באופן אוטומטי את קובצי המקור והכותרות קבוצת cpp בחלונית Project. על ידי שימוש כמה פקודות add_library(), אפשר להגדיר ספריות ל-CMake ולבנייה מקובצי מקור אחרים.

הוספת ממשקי API של NDK

Android NDK מספק קבוצה של ספריות וממשקי API מקוריים שניתן למצוא שימושי. כדי להשתמש בכל אחד מממשקי ה-API האלה, אפשר לכלול את ספריות ה-NDK בפרויקט קובץ סקריפט CMakeLists.txt.

ספריות NDK מוכנות מראש כבר קיימות בפלטפורמת Android, כך צריך לפתח אותן או לארוז אותן ב-APK. בגלל שספריות ה-NDK כבר חלק מנתיב החיפוש של CMake, אין צורך אפילו לציין מיקום הספרייה בהתקנת ה-NDK המקומית - צריך רק צריך לציין ל-CMake את שם הספרייה שרוצים להשתמש בה ולקשר אותה לספרייה המקורית שלכם.

מוסיפים את הפקודה find_library() ל-build של CMake סקריפט לאיתור ספריית NDK ולאחסון הנתיב שלה כמשתנה. אתם משתמשים את המשתנה הזה כך שיפנה לספריית ה-NDK בחלקים אחרים של סקריפט ה-build. הדוגמה הבאה מאתרת את ספריית התמיכה ביומנים ספציפית ל-Android ושומר את הנתיב שלו ב-log-lib:

find_library( # Defines the name of the path variable that stores the
              # location of the NDK library.
              log-lib

              # Specifies the name of the NDK library that
              # CMake needs to locate.
              log )

כדי שספריית הנייטיב שלך תוכל לקרוא לפונקציות בlog צריך לקשר את הספריות באמצעות הפקודה target_link_libraries() סקריפט build ל-CMake:

find_library(...)

# Links your native library against one or more other native libraries.
target_link_libraries( # Specifies the target library.
                       native-lib

                       # Links the log library to the target library.
                       ${log-lib} )

ה-NDK כולל גם כמה ספריות כקוד מקור שצריך ליצור ולקשר אותו לספריית הנייטיב שלך. אפשר להדר את קוד המקור באמצעות הפקודה add_library() בקובץ ה-CMake, סקריפט build. כדי לספק נתיב לספריית NDK המקומית, אפשר להשתמש משתנה נתיב אחד (ANDROID_NDK), שנקבע ל-Android Studio באופן אוטומטי שמגדירות בשבילכם.

הפקודה הבאה מנחה את CMake ליצור android_native_app_glue.c, שמנהלת את NativeActivity אירועים במחזור החיים וקלט מגע לספרייה סטטית, ומקשר אותם אל native-lib:

add_library( app-glue
             STATIC
             ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c )

# You need to link static libraries against your shared native library.
target_link_libraries( native-lib app-glue ${log-lib} )

הוספת ספריות אחרות מוכנות מראש

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

add_library( imported-lib
             SHARED
             IMPORTED )

צריך לציין את הנתיב לספרייה באמצעות הפקודה set_target_properties() בתור שמוצגת בהמשך.

חלק מהספריות מספקות חבילות נפרדות לארכיטקטורות מעבד (CPU) ספציפיות, או Application Binary Interfaces (ABI), וגם לארגן אותם בספריות נפרדות. הגישה הזו עוזרת לספריות של הארכיטקטורות של המעבד (CPU), אבל הוא מאפשר להשתמש רק של הספרייה הרצויה. כדי להוסיף כמה גרסאות ABI של ספרייה לסקריפט build של CMake, בלי שתצטרכו לכתוב פקודות מרובות בכל גרסה של הספרייה, אפשר להשתמש בנתיב ANDROID_ABI. מותאם אישית. המשתנה הזה משתמש ברשימה של ערכי ברירת המחדל ABI שנתמכים ב-NDK, או ברשימה מסוננת של ממשקי ABI להגדיר באופן ידני את Gradle לשימוש. לדוגמה:

add_library(...)
set_target_properties( # Specifies the target library.
                       imported-lib

                       # Specifies the parameter you want to define.
                       PROPERTIES IMPORTED_LOCATION

                       # Provides the path to the library you want to import.
                       imported-lib/src/${ANDROID_ABI}/libimported-lib.so )

כדי לאתר את קובצי הכותרות תוך כדי הידור ב-CMake, צריך להשתמש בקוד את הפקודה include_directories() וכוללים את הנתיב קובצי כותרות:

include_directories( imported-lib/include/ )

הערה: אם אתם רוצים לארוז ספרייה שהוגדרה מראש שאינה או תלות בזמן build - לדוגמה, כשמוסיפים ספרייה שהוגדרה מראש שאפשר לסמוך עליהן ב-imported-lib, אינכם צריכים לבצע את הפונקציה כדי לקשר את הספרייה.

כדי לקשר את הספרייה שנוצרה מראש לספריית הנייטיב שלכם, צריך להוסיף אותה הפקודה target_link_libraries() בסקריפט ה-build של CMake:

target_link_libraries( native-lib imported-lib app-glue ${log-lib} )

כדי לארוז את הספרייה המובנית מראש ב-APK, עליך להגדיר באופן ידני את Gradle עם הבלוק sourceSets כדי כוללים את הנתיב לקובץ .so שלכם. אחרי בניית ה-APK, שיכול לבדוק אילו ספריות חבילות של Gradle ל-APK שלך באמצעות כלי הניתוח ל-APK.

הכללת פרויקטים אחרים של CMake

אם אתם רוצים ליצור כמה פרויקטים של CMake ולכלול את הפלט שלהם בפרויקט Android, אפשר להשתמש בקובץ CMakeLists.txt אחד בתור סקריפט build של CMake ברמה העליונה ( קישור ל-Gradle) ולהוסיף עוד פרויקטים של CMake כיחסי התלות של ה-build. סקריפט. סקריפט ה-build הבא של CMake ברמה העליונה משתמש ב הפקודה add_subdirectory() שצריך לציין קובץ CMakeLists.txt אחר כתלות ב-build ואז קישורים ביחס לפלט שלה, בדיוק כמו בכל ספרייה אחרת שהוגדרה מראש.

# Sets lib_src_DIR to the path of the target CMake project.
set( lib_src_DIR ../gmath )

# Sets lib_build_DIR to the path of the desired output directory.
set( lib_build_DIR ../gmath/outputs )
file(MAKE_DIRECTORY ${lib_build_DIR})

# Adds the CMakeLists.txt file located in the specified directory
# as a build dependency.
add_subdirectory( # Specifies the directory of the CMakeLists.txt file.
                  ${lib_src_DIR}

                  # Specifies the directory for the build outputs.
                  ${lib_build_DIR} )

# Adds the output of the additional CMake build as a prebuilt static
# library and names it lib_gmath.
add_library( lib_gmath STATIC IMPORTED )
set_target_properties( lib_gmath PROPERTIES IMPORTED_LOCATION
                       ${lib_build_DIR}/${ANDROID_ABI}/lib_gmath.a )
include_directories( ${lib_src_DIR}/include )

# Links the top-level CMake build output against lib_gmath.
target_link_libraries( native-lib ... lib_gmath )

מפעילים את CMake משורת הפקודה

אפשר להשתמש בפקודה הבאה כדי לקרוא ל-CMake כדי ליצור פרויקט נינג'ה מחוץ ל- של Android Studio:

cmake
-Hpath/to/cmakelists/folder
-Bpath/to/generated/ninja/project/debug/ABI
-DANDROID_ABI=ABI                               // For example, arm64-v8a
-DANDROID_PLATFORM=platform-version-string      // For example, android-16
-DANDROID_NDK=android-sdk/ndk/ndk-version
-DCMAKE_TOOLCHAIN_FILE=android-sdk/ndk/ndk-version/build/cmake/android.toolchain.cmake
-G Ninja

הפקודה הזו תיצור את פרויקט הנינג'ה שאותו אפשר להריץ כדי ליצור ספריות הפעלה של Android (.so קבצים). CMAKE_TOOLCHAIN_FILE הוא שנדרשים כדי להשתמש בתמיכת CMake של NDK. ל-CMake 3.21 ואילך, CMake מובנה אפשר גם להשתמש בתמיכה ב-NDK, אבל צריך להשתמש בקבוצת משתנים אחרת כפי שמתואר במסמכי התיעוד של CMake Cross-Comiling for Android.