Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/android/183.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Android 如何并行化不同ABI的externalNativeBuild?_Android_Cmake_Android Ndk_Ninja - Fatal编程技术网

Android 如何并行化不同ABI的externalNativeBuild?

Android 如何并行化不同ABI的externalNativeBuild?,android,cmake,android-ndk,ninja,Android,Cmake,Android Ndk,Ninja,背景 我目前正在从事一个Android项目,该项目包含大量的本地代码。本机代码是为多个ABI构建的。由于各种原因,到目前为止,本机代码是使用调用ndk build.cmd的自定义Gradle任务构建的 现在我正在将其更改为使用externalNativeBuild进行NDK集成,并使用CMake列表代替旧的Android.mk文件。这似乎是一种更好的支持/记录方式 问题 旧的ndk build方法的一个优点是它可以并行构建多个abi,例如,可以并行构建ARM版本和x86版本的库。 这对我来说尤

背景

我目前正在从事一个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管理器下载的CMake/Ninja版本以及一些较新的版本(CMake 3.12.3、Ninja 1.8.2)尝试了这两种方法,并在这两种情况下看到了相同的行为。

恕我直言,我建议放弃这项任务。请注意,当从externalNativeBuild运行时,ndk build也会发生相同的“反并行”行为。gradle将依次构建每个ABI版本,而不是运行
ndk build-j
。但对于所有ABI,并行构建几乎没有什么好处。在你的项目中集成C++构建是很好的,但是只是为了调试的目的。这就是为什么我只在Jenkins上构建所有ABI,而不在那里使用gradle集成。注意:别忘了拆分APK!“但是,对于一般项目来说,所有ABI的并行构建几乎没有什么好处”,是的。但在我的例子中,它将把构建时间缩短近一半(因为每个ABI变体的大部分构建时间都花在运行我提到的第三方单线程工具上)。“所有ABI的并行构建几乎没有什么好处”,这并不是因为并行化效率不高,但因为只有在ABI中使用集成构建才有意义,所以您当前正在调试。确定。我只是想避免必须维护两个不同的解决方案,或者坚持使用过时的东西,并且可能在将来的NDK版本中被删除。基于谷歌的Android文档,
externalNativeBuild{cmake{}
显然是他们对未来的设想。我相信ndk build将继续存在。如今,CMake解决方案在NDK中的“原生CMake Android支持”和“CMake工具链文件”之间存在不一致性。但这并不重要,带忍者的CMake将自动执行并行构建。问题是Gradle按顺序运行每个ABI。您可以从命令行为所有ABI运行相同的CMakeList.txt。