documentation: https://d.android.com/studio/projects/add-native-code.html
前言
网络上有很多关于CMakeList.txt的介绍文章,大多针对性很强。为了可以看见整片森林,我查看了Configuration CMake的官方文档。以下是文档的全部内容,附上自己的翻译和见解。
A CMake build script is a plain text file that you must name CMakeLists.txt
and includes commands CMake uses to build your C/C++ libraries. If your native sources don’t already have a CMake build script, you need to create one yourself and include the appropriate CMake commands.
CMake构建脚本是一个只能命名为CMakeLists.txt的纯文本文件,包含CMake用于构建C/C++库的命令。如果你的native源没有CMake构建脚本,你应该自己创建一个包含适当CMake 命令。
This section covers some basic commands you should include in your build script in order to tell CMake which sources to use when creating your native library. To learn more, read the official documentation about CMake commands.
本节介绍一些你应该包含在构建脚本的基本命令,以便告诉CMake,在创建你的native库时要用到哪些资源。更多见CMake commands.官方文档。
After you configure a new CMake build script, you need to configure Gradle to include your CMake project as a build dependency, so that Gradle builds and packages your native library with your app's APK.
配置新的Cmake构建脚本后,你需要configure Gradle包含你的CMake的工程作为构建依赖,这样Gradle构建和和你的app's APK一起打包native库。
Note: If your project uses ndk-build, you don’t need to create a CMake build script. You can simply configure Gradle to include your existing native library project by providing a path to yourAndroid.mk
file.
注意:如果你的工程使用 ndk-build,你没有必要创建一个CMake构建脚本。你可以简单地configure Gradle来包含现有的native库项目,方法是提供一个Android.mk文件的路径。
Create a CMake build script(创建一个CMake编译脚本)
To create a plain text file that you can use as your CMake build script, proceed as follows:
- Open the Project pane from the left side of the IDE and select the Project view from the drop-down menu.
- Right-click on the root directory of your-module and select New > File.
Note: You can create the build script in any location you want. However, when configuring the build script, paths to your native source files and libraries are relative to the location of the build script.
- Enter "CMakeLists.txt" as the filename and click OK.
为了创建一个你可以用来作为你的CMake编译脚本的纯文本文件,按如下执行:
1. 打开位于IDE左边的工程面板并且在下拉的菜单中选择工程视图。
2.右击模块的根目录,选择New>File。
注意:你可以在任何你想要的位置创建构建脚本。然而,当配置这构建脚本时,你的native源文件和库是相对于构建脚本的路径。
3. 输入“CMakeLists.txt”作为文件名,然后点击OK。
You can now configure your build script by adding CMake commands. To instruct CMake to create a native library from native source code, add the cmake_minimum_required()
and add_library()
commands to your build script:
你现在可以通过添加CMake命令来配置你的构建脚本。为了指导CMake从native源代码创建native库,添加 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 )
Tip: Similar to how you can tell CMake to create a native library from source files, you can use theadd_executable()
command to tell CMake to instead create an executable from those source files. However, building executables from your native sources is optional, and building native libraries to package into your APK satisfies most project requirements.
建议:类似告诉CMake如何从源文件中创建一个本地库,你可以用add_executable()命令告诉CMake代替从其它的源文件创建一个executable。然而,从你的native源文件构建
executables是可选的,并且构建native库打包到你的APK满足大多数工程的需求。
When you add a source file or library to your CMake build script using add_library()
, Android Studio also shows associated header files in the Project view after you sync your project. However, in order for CMake to locate your header files during compile time, you need to add the include_directories()
command to your CMake build script and specify the path to your headers:
当你添加一个源文件或者库到你的CMake构建脚本时,使用add_library()
,同步你的工程后,Android Studio还会在“项目”视图显示关联的头文件。然而,为了让CMake在编译时间定位你的头文件,你应该添加include_directories()命令到你的CMake构建脚本并且指定头文过去常常
convention 件路径:
add_library(...)
# Specifies a path to native header files.
include_directories(src/main/cpp/include/)
The convention CMake uses to name the file of your library is as follows:
惯例CMake按如下来命名你的库文件
liblibrary-name.so
For example, if you specify "native-lib" as the name of your shared library in the build script, CMake creates a file named libnative-lib.so
. However, when loading this library in your Java or Kotlin code, use the name you specified in the CMake build script:
例如,如果你在构建脚本中指定"native-lib"作为共享库的名字,CMake创建一个名为libnative-lib.so的文件。然而,当在你的Java或者Kotlin代码中加载这个库,用你在CMake构建脚本指定的名字。
static {
System.loadLibrary("native-lib");
}
Note: If you rename or remove a library in your CMake build script, you need to clean your project before Gradle applies the changes or removes the older version of the library from your APK. To clean your project, select Build > Clean Project from the menu bar.
注意:如果你在你的CMake构建脚本中重命名或者删除库,在Gradle中应用这些改变或者从你的APK中删除更老的库版本前必须clean你的工程。为了clean你的工程,从菜单条中选择Build > Clean Project。
Android Studio automatically adds the source files and headers to the cpp group in the Project pane. By using multiple add_library()
commands, you can define additional libraries for CMake to build from other source files.
Android Studio会自动添加源文件和头文件到"项目"窗口的cpp 组中。通过使用多个 add_library()命令,你可以为从其它源文件构建的CMake定义附加库。
Add NDK APIs(添加NDK的APIs)
The Android NDK provides a set of native APIs and libraries that you may find useful. You can use any of these APIs by including the NDK libraries in your project’s CMakeLists.txt
script file.
Android NDK提供一组你可能认为有用的API是和库。通过在你的工程的 CMakeLists.txt脚本文件包含
the NDK libraries,你可以使用任何这些APIs。
Prebuilt NDK libraries already exist on the Android platform, so you don’t need to build them or package them into your APK. Because the NDK libraries are already a part of CMake’s search path, you don’t even need to specify the location of the library in your local NDK installation—you only need to provide CMake with the name of the library you want to use and link it against your own native library.
重构在Android平台已经存在的NDK库,这样你没必要构建它们或者打包它们进你的APK。因为NDK已经是CMake’s搜索路径的一部分,在你的局部NDK安装时,你甚至不需要指定库的位置——你只需要提供CMake你想要用的库的名字,并将它链接到你自己的native库。
Add the find_library()
command to your CMake build script to locate an NDK library and store its path as a variable. You use this variable to refer to the NDK library in other parts of the build script. The following sample locates the Android-specific log support library and stores its path in log-lib
:
添加 find_library()命令到你的CMake构建脚本定位NDK库,并且用一个变量存储他的路径。你用此变量引用构建脚本其他部分中的NDK库。这下面的例子定位这
Android-specific log support library并且用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 )
In order for your native library to call functions in the log
library, you need to link the libraries using the target_link_libraries()
command in your CMake build script:
为了在你的native库中调用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} )
The NDK also includes some libraries as source code that you need to build and link to your native library. You can compile the source code into a native library by using the add_library()
command in your CMake build script. To provide a path to your local NDK library, you can use theANDROID_NDK
path variable, which Android Studio automatically defines for you.
NDK还可以包含一些库,作为你需要构建并链接到native库的源码库。你可以通过用在CMake构建脚本中的add_library()命令编译源代码到native库。为了提供一个到你本机NDK库的路径,你可以使用Android Studio动态为你定义的ANDROID_NDK路径变量。
The following command tells CMake to build android_native_app_glue.c
, which manages NativeActivity
lifecycle events and touch input, into a static library and links it to native-lib
下面的命令告诉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} )
Add other prebuilt libraries(添加其他的重建库)
Adding a prebuilt library is similar to specifying another native library for CMake to build. However, because the library is already built, you need to use the IMPORTED
flag to tell CMake that you only want to import the library into your project:
添加一个预构建库类似于为CMake指定另一个要构建的native库。然而,因为库已经构建,你只需要用IMPORTED
标志告诉CMake你只想将库导入到项目中。
add_library( imported-lib
SHARED
IMPORTED )
You then need to specify the path to the library using the set_target_properties()
command as shown below.
然后,你需要使用 set_target_properties()命令指定库的路径,如下所示。
Some libraries provide separate packages for specific CPU architectures, or Application Binary Interfaces (ABI), and organize them into separate directories. This approach helps libraries take advantage of certain CPU architectures while allowing you to use only the versions of the library you want. To add multiple ABI versions of a library to your CMake build script, without having to write multiple commands for each version of the library, you can use the ANDROID_ABI
path variable. This variable uses a list of the default ABIs that the NDK supports, or a filtered list of ABIs you manually configure Gradle to use. For example:
一些库为特定的CPU体系结构提供单独的包,或 Application Binary Interfaces (ABI),并且经它们组织成单独的目录。这种方法可以帮助库利用某些CPU体系结构,同时只允许你使用所需的库版本。为了添加多个ABI库版本到你的CMake构建脚本,不必为库的每个版本编写多个命令,你可以用ANDROID_ABI路径变量。这变量使用默认的
ABIs that the NDK supports列表,或者manually configure Gradle使用的ABIs过滤列表。例如:
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 )
For CMake to locate your header files during compile time, you need to use the include_directories()
command and include the path to your header files:
为了在编译期间可以定位到你的头文件,你需要用 include_directories()命令并且包含你的头文件的路径。
include_directories( imported-lib/include/ )
Note: If you want to package a prebuilt library that is not a build-time dependency—for example, when adding a prebuilt library that is a dependency of imported-lib
, you do not need perform the following instructions to link the library.
注意:如果要打包不是构建时依赖项的预构建库——比如,当添加一个imported-lib依赖项的预构建库,你不需要执行以下的说明来链接库。
To link the prebuilt library to your own native library, add it to the target_link_libraries()
command in your CMake build script:
为了链接这预构建库到你自己的native库,添加预构建库到CMake构建脚本的target_link_libraries()命令中。
target_link_libraries( native-lib imported-lib app-glue ${log-lib} )
To package the prebuilt library into your APK, you need to manually configure Gradle with the sourceSets
block to include the path to your .so
file. After building your APK, you can verify which libraries Gradle packages into your APK by using the APK Analyzer.
为了打包预构建库到你的APK中,你需要用sourceSets
manually configure Gradle ,包含你的.so文件的路径。构建APK后,你可以用APK Analyzer确认哪个库Gradle打包进你的APK。
Include other CMake projects(包括其它的CMake工程)
If you want to build multiple CMake projects and include their outputs in your Android project, you can use one CMakeLists.txt
file as the top-level CMake build script (which is the one you link to Gradle) and add additional CMake projects as dependencies of that build script. The following top-level CMake build script uses the add_subdirectory()
command to specify another CMakeLists.txt
file as a build dependency and then links against its output just as it would with any other prebuilt library.
如果你想要构建多个CMake工程并且在你的Android工程中包含它们的输出,你可以把其中的一个CMakeLists.txt文件作为一个顶层的CMake构建脚本(它被指定链接到Gradle)并且添加附加的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 )