如果您不使用 CMake 或 ndk-build,但希望完全集成 Android Gradle 插件 (AGP) C/C++ 构建和 Android Studio,您可以通过创建一个 shell 脚本创建自定义 C/C++ 构建系统,该脚本以 Ninja 构建文件格式写入构建信息。
Android Studio 和 AGP 已添加对自定义 C/C++ 构建系统的实验性支持。此功能从 Android Studio Dolphin | 2021.3.1 Canary 4 开始可用。
概述
C/C++ 项目(尤其是针对多个平台的项目)的常见模式是从一些底层表示形式为每个平台生成项目。此模式的一个突出示例是 CMake。CMake 可以从保存在 CMakeLists.txt
文件中的单个底层表示形式为 Android、iOS 和其他平台生成项目。
虽然 AGP 直接支持 CMake,但还有其他可用的项目生成器不受直接支持
这些类型的项目生成器要么支持 Ninja 作为 C/C++ 构建的后端表示形式,要么可以调整为生成 Ninja 作为后端表示形式。
配置正确后,具有集成 C/C++ 项目系统生成器的 AGP 项目使用户能够
从命令行和 Android Studio 构建。
在 Android Studio 中使用完整的语言服务支持(例如,转到定义)编辑源代码。
使用 Android Studio 调试器调试原生和混合进程。
如何修改构建以使用自定义 C/C++ 构建配置脚本
本节介绍了从 AGP 使用自定义 C/C++ 构建配置脚本的步骤。
步骤 1:修改模块级 build.gradle
文件以引用配置脚本
要在 AGP 中启用 Ninja 支持,请在模块级 build.gradle
文件中配置 experimentalProperties
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++ 项目文件的路径。此文件的格式可以是您想要的任何格式。对该文件进行的更改将触发 Android Studio 中的 Gradle 同步提示。ninja.configure
是脚本文件的路径,Gradle 在需要配置 C/C++ 项目时将执行该脚本。项目在第一次构建、在 Android Studio 中进行 Gradle 同步或配置脚本输入之一发生更改时进行配置。ninja.arguments
是一个参数列表,这些参数将传递给由 ninja.configure 定义的脚本。此列表中的元素可以引用一组宏,这些宏的值取决于 AGP 中的当前配置上下文。${ndk.moduleMakeFile}
是ninja.configure
文件的完整路径。因此,在示例中,它将是C:\path\to\configure-ninja.bat
。${ndk.variantName}
是当前正在构建的 AGP 变体的名称。例如,debug 或 release。${ndk.abi}
是当前正在构建的 AGP ABI 的名称。例如,x86
或arm64-v8a
。
${ndk.buildRoot}
是一个文件夹的名称,由 AGP 生成,脚本将其输出写入该文件夹。这将在步骤 2:创建配置脚本中详细说明。${ndk.ndkVersion}
是要使用的 NDK 的版本。这通常是传递给build.gradle
文件中 android.ndkVersion 的值,或者如果不存在则为默认值。${ndk.minPlatform}
是 AGP 请求的最小目标 Android 平台。
ninja.targets
是应该构建的特定 Ninja 目标的列表。
步骤 2:创建配置脚本
配置脚本(在前面的示例中为 configure-ninja.bat
)的最低责任是生成一个 build.ninja
文件,该文件在使用 Ninja 构建时,将编译并链接项目的所有原生输出。通常这些是 .o
(对象)、.a
(存档)和 .so
(共享对象)文件。
配置脚本可以根据您的需要将 build.ninja
文件写入两个不同的位置。
如果 AGP 可以选择一个位置,则配置脚本会将
build.ninja
写入${ndk.buildRoot}
宏中设置的位置。如果配置脚本需要选择
build.ninja
文件的位置,则它还会在${ndk.buildRoot}
宏中设置的位置写入一个名为build.ninja.txt
的文件。此文件包含配置脚本写入的build.ninja
文件的完整路径。
build.ninja
文件的结构
通常,大多数准确表示 Android C/C++ 构建的结构都可以工作。AGP 和 Android Studio 需要的主要元素是
C/C++ 源文件列表以及 Clang 编译它们所需的标志。
输出库列表。这些通常是
.so
(共享对象)文件,但也可能是.a
(存档)或可执行文件(无扩展名)。
如果您需要有关如何生成 build.ninja
文件的示例,您可以查看使用 build.ninja
生成器时 CMake 的输出。
这是一个最小的 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
规则声明命名输出
如果可能,建议 build.ninja
结构使用 phony
规则为构建输出提供易于阅读的名称。例如,如果您有一个名为 c:/path/to/lib.so
的输出,您可以为其提供一个易于阅读的名称,如下所示。
build curl: phony /path/to/lib.so
这样做的优势在于,您可以将此名称指定为 build.gradle
文件中的构建目标。例如,
android {
defaultConfig {
externalNativeBuild {
...
experimentalProperties["ninja.targets"] = [ "curl" ]
指定“all”目标
当您指定 all
目标时,这将是当 build.gradle
文件中未明确指定目标时 AGP 构建的默认库集。
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
指定备用构建方法(可选)
更高级的用例是包装一个不是基于 Ninja 的现有构建系统。在这种情况下,您仍然需要使用它们的标志以及输出库来表示所有源,以便 Android Studio 可以提供适当的语言服务功能,例如自动完成和转到定义。但是,您希望 AGP 在实际构建期间委托给底层构建系统。
为此,您可以使用具有特定扩展名 .passthrough
的 Ninja 构建输出。
举一个更具体的例子,假设您想包装一个 MSBuild。您的配置脚本将像往常一样生成 build.ninja
,但它还会添加一个 passthrough 目标,该目标定义了 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 并点击帮助 > 提交反馈。请务必参考“自定义 C/C++ 构建系统”以帮助引导错误。
如果您未安装 Android Studio,要报告错误,请使用此模板提交错误。