android配置cmake

介紹完cmake基礎知識,再來將cmake與Android NDK,gradle結合使用。
附錄Android NDK原生API
Android NDK原生API
附錄Android NDK入門指南
Android NDK入門指南
附錄Android配置cmake
Android配置cmake

Android添加NDK包和靜態包示例

cmake_minimum_required(VERSION 3.4.1)
 
add_library(native-lib SHARED src/main/cpp/native-lib.cpp)
 
add_library(static-lib STATIC IMPORTED)
set_target_properties(static-lib PROPERTIES IMPORTED_LOCATION
        ${CMAKE_CURRENT_SOURCE_DIR}/build/intermediates/cmake/debug/obj/${CMAKE_ANDROID_ARCH_ABI}/libstatic-lib.a)
 
find_library(log-lib log)
 
target_link_libraries(native-lib static-lib ${log-lib})

CMake 編譯腳本是一個純文本文件,您必須將其命名爲 CMakeLists.txt,並在其中包含 CMake 編譯您的 C/C++ 庫時需要使用的命令。如果原生源代碼文件還沒有 CMake 編譯腳本,您需要自行創建一個,並在其中包含適當的 CMake 命令。

本部分將介紹您應該在編譯腳本中包含哪些基本命令,以便指示 CMake 在創建原生庫時使用哪些源代碼文件。要了解詳情,請參閱介紹 CMake 命令的官方文檔。

在配置新的 CMake 編譯腳本後,您需要配置 Gradle 以將 CMake 項目作爲編譯依賴項包含在內,從而讓 Gradle 編譯原生庫,並將其與應用的 APK 打包在一起。

注意:如果項目使用的是 ndk-build,您不需要創建 CMake 編譯腳本。您只需配置 Gradle 以包含現有的原生庫項目即可;爲此,您需要提供 Android.mk 文件的路徑。

創建 CMake 編譯腳本

要創建一個可以用作 CMake 編譯腳本的純文本文件,請按以下步驟操作:

1、從 IDE 的左側打開 Project 窗格,然後從下拉菜單中選擇 Project 視圖。
2、右鍵點擊 your-module 的根目錄,然後依次選擇 New > File。

注意:您可以在所需的任何位置創建編譯腳本。不過,在配置編譯腳本時,原生源代碼文件和庫的路徑將與編譯腳本的位置相關。

3、輸入“CMakeLists.txt”作爲文件名,然後點擊 OK。

現在,您可以通過添加 CMake 命令來配置您的編譯腳本。要指示 CMake 通過原生源代碼創建原生庫,請將向您的編譯腳本添加 cmake_minimum_required() 和 add_library() 命令:

# 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 中即可滿足大多數項目要求。

在使用 add_library() 向 CMake 編譯腳本添加源代碼文件或庫時,Android Studio 還會在您同步項目後在 Project 視圖中顯示相關的頭文件。不過,爲了讓 CMake 能夠在編譯時找到頭文件,您需要向 CMake 編譯文件添加 include_directories() 命令,並指定頭文件的路徑:

add_library(...)

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

CMake 使用以下規範來爲庫文件命名:

liblibrary-name.so

例如,如果您在編譯腳本中指定“native-lib”作爲共享庫的名稱,CMake 就會創建一個名爲 libnative-lib.so 的文件。不過,在 Java 或 Kotlin 代碼中加載此庫時,請使用您在 CMake 編譯腳本中指定的名稱:

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

注意:如果重命名或移除了 CMake 編譯腳本中的庫,您需要在 Gradle 應用相關更改或從 APK 中移除舊版庫之前清除您的項目。要清除項目,請在菜單欄中依次選擇 Build > Clean Project。

Android Studio 會自動向 Project 窗格中的 cpp 組添加源代碼文件和頭文件。通過使用多個 add_library() 命令,您可以爲 CMake 定義要通過其他源代碼文件編譯的更多庫。

添加 NDK API

Android NDK 提供了一套您可能會覺得非常實用的原生 API 和庫。通過在項目的 CMakeLists.txt 腳本文件中包含 NDK 庫,您可以使用其中任何 API。

Android 平臺上已存在預編譯的 NDK 庫,因此您無需編譯它們或將它們打包到 APK 中。由於 NDK 庫已成爲 CMake 搜索路徑的一部分,因此您甚至無需在本地 NDK 安裝中指定庫的位置,您只需爲 CMake 提供您想要使用的庫的名稱,並將其與您自己的原生庫相關聯即可。

附錄Android NDK原聲API
Android NDK原生API

向 CMake 編譯腳本添加 find_library() 命令以找到 NDK 庫並將其路徑存儲爲一個變量。您可以使用此變量在編譯腳本的其他部分引用 NDK 庫。以下示例可以找到特定於 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 庫中的函數,您需要使用 CMake 腳本中的 target_link_libraries() 命令來關聯庫:

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 還以源代碼的形式包含一些庫,您在編譯和關聯原生庫時需要使用這些代碼。您可以使用 CMake 編譯腳本中的 add_library() 命令將源代碼編譯到原生庫中。要提供本地 NDK 庫的路徑,您可以使用 Android Studio 自動爲您定義的 ANDROID_NDK 路徑變量。

以下命令可以指示 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 架構提供單獨的軟件包(或應用二進制接口 (ABI)),並將其組織到單獨的目錄中。此方法既有助於庫充分利用特定的 CPU 架構,又能讓您只使用所需的庫版本。要向 CMake 編譯腳本添加庫的多個 ABI 版本,而不必爲庫的每個版本編寫多個命令,您可以使用 ANDROID_ABI 路徑變量。此變量使用的是 NDK 支持的一組默認 ABI,或者您手動配置 Gradle 以使用的一組經過過濾的 ABI。例如:

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/ )

注意:如果您想要打包不屬於編譯時依賴項的預編譯庫(例如在添加屬於 imported-lib 依賴項的預編譯庫時),您無需按以下說明操作來關聯庫。

要將預編譯庫關聯到您自己的原生庫,請將其添加到 CMake 編譯腳本的 target_link_libraries() 命令中:

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

要將預編譯庫打包到 APK 中,您需要使用 sourceSets 塊手動配置 Gradle 以包含 .so 文件的路徑。編譯 APK 後,您可以使用 APK 分析器驗證 Gradle 會將哪些庫打包到您的 APK 中。

包含其他 CMake 項目

如果想要編譯多個 CMake 項目並在 Android 項目中包含它們的輸出,您可以使用一個 CMakeLists.txt 文件(即您關聯到 Gradle 的那個文件)作爲頂級 CMake 編譯腳本,並添加其他 CMake 項目作爲此編譯腳本的依賴項。以下頂級 CMake 編譯腳本使用 add_subdirectory() 命令將另一個 CMakeLists.txt 文件指定爲編譯依賴項,然後關聯其輸出,就像處理任何其他預編譯庫一樣。

# 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 )
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章