Как распараллелить externalNativeBuild для разных ABI? - PullRequest
0 голосов
/ 18 октября 2018

Фон

В настоящее время я работаю над проектом Android, который содержит достаточное количество нативного кода.Нативный код построен для нескольких ABI.По разным причинам собственный код до сих пор создавался с использованием пользовательской задачи Gradle, которая вызывает ndk-build.cmd.

. Сейчас я нахожусь в процессе изменения этого значения, чтобы использовать externalNativeBuild для интеграции с NDK,и списки CMake вместо старых Android.mk файлов.Кажется, это лучший поддерживаемый / документированный способ ведения дел.


Проблема

Одна приятная вещь в старом методе ndk-build заключалась в том, что он собиралдля нескольких ABI параллельно - например, версия ARM и версия библиотеки x86 могут быть построены параллельно.
Это особенно полезно в моем случае, потому что я должен использовать сторонний инструмент на этапе соединения, который 1) занимает очень много времени (минут), и 2) в основном однопоточный.Следовательно, параллельное построение библиотеки для нескольких ABI помогло значительно сократить время сборки.

При сборке с помощью CMake / Ninja я не могу воспроизвести это поведение.Ninja должен распараллеливать сборки по умолчанию, и он вполне может это делать для данного ABI (т.е. компилировать несколько исходных файлов параллельно для одного ABI ).Но из того, что я могу сказать, он никогда не начинает сборку библиотеки для другого ABI, пока не завершит сборку для текущего ABI.


Вопрос

При использованииCMake / Ninja через externalNativeBuild, есть ли способ сказать системе сборки, что я хочу, чтобы она создавала свой собственный код для нескольких 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

Из этого вывода может быть не очевидно, что две библиотеки построены последовательно,но это становится очевидным, если у вас есть что-то, что занимает заметное количество времени для связывания.

Я пробовал это как с версиями CMake / Ninja, которые вы можете загрузить с помощью SDK Manager, так и с некоторыми более новымиверсии (CMake 3.12.3,Ниндзя 1.8.2) и видел одинаковое поведение в обоих случаях.

...