背景
我目前正在处理一个包含大量本机代码的Android项目。本机代码是为多个ABI构建的。由于各种原因,到目前为止,本机代码是使用调用ndk-build.cmd
的自定义Gradle任务构建的。
现在,我正在将其更改为使用externalNativeBuild
进行NDK集成,并使用CMake列表而不是旧的Android.mk
文件。似乎是一种更好的受支持/记录的处理方式。
问题
关于旧的ndk-build
方法的一件好事是,它将为多个ABI并行构建-例如该库的ARM版本和x86版本可以并行构建。
这对我的情况特别有用,因为在链接阶段需要我使用第三方工具,其中1)完成需要很长时间(几分钟),而2)大多是单线程的。因此,为多个ABI并行构建库有助于大大缩短构建时间。
使用CMake / Ninja进行构建时,我无法复制此行为。 Ninja默认情况下应该并行化构建,对于给定的ABI,它很可能做到了这一点(即,针对同一ABI 以并行方式编译多个源文件)。但是据我所知,直到完成为当前ABI的构建,它才开始为另一个ABI构建库。
问题
通过externalNativeBuild
使用CMake / Ninja时,有什么方法可以告诉构建系统我希望它为多个ABI并行构建本机代码吗?
示例
一个简单的示例来说明这一点,就像Android Studio中的“新建项目”模板一样简单,即:
CMakeLists.txt:
cmake_minimum_required(VERSION 3.4.1)
add_library(native-lib SHARED
src/main/cpp/native-lib.cpp )
app / build.gradle:
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
defaultConfig {
applicationId "com.example.cmakemultiabis"
minSdkVersion 21
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags ""
}
}
ndk {
abiFilters 'armeabi-v7a', 'x86'
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:27.1.1'
implementation 'com.android.support.constraint:constraint-layout:1.1.3'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}
然后使用gradlew assembleRelease
将为您提供:
> Task :app:externalNativeBuildRelease
Build native-lib x86
[1/2] Building CXX object CMakeFiles/native-lib.dir/src/main/cpp/native-lib.cpp.o
[2/2] Linking CXX shared library ..\..\..\..\build\intermediates\cmake\release\obj\x86\libnative-lib.so
Build native-lib armeabi-v7a
[1/2] Building CXX object CMakeFiles/native-lib.dir/src/main/cpp/native-lib.cpp.o
[2/2] Linking CXX shared library ..\..\..\..\build\intermediates\cmake\release\obj\armeabi-v7a\libnative-lib.so
从该输出可能并不明显,这两个库是顺序构建的,但是如果您有一些链接需要花费大量时间的链接,这确实很明显。
我已经尝试过使用可通过SDK Manager下载的CMake / Ninja版本以及一些较新的版本(CMake 3.12.3,Ninja 1.8.2)来进行此操作,并且在两种情况下都看到了相同的行为。