针对不同处理器架构的Gradle android构建
我想使用Gradle为4种不同的Android CPU处理器架构(armeabi armeabi-v7a x86 mips)构建4个独立的APK 我在libs文件夹中为4个CPU架构构建了本机OpenCV库 我希望每个apk只包含与正确的CPU架构相对应的OpenCV库 当前生成脚本如下所示:针对不同处理器架构的Gradle android构建,android,opencv,gradle,multiprocessor,android-gradle-plugin,Android,Opencv,Gradle,Multiprocessor,Android Gradle Plugin,我想使用Gradle为4种不同的Android CPU处理器架构(armeabi armeabi-v7a x86 mips)构建4个独立的APK 我在libs文件夹中为4个CPU架构构建了本机OpenCV库 我希望每个apk只包含与正确的CPU架构相对应的OpenCV库 当前生成脚本如下所示: apply plugin: 'android' dependencies { compile fileTree(dir: 'libs', include: '*.jar') compil
apply plugin: 'android'
dependencies {
compile fileTree(dir: 'libs', include: '*.jar')
compile project(':workspace:OpenCV4Android:sdk:java')
}
android {
compileSdkVersion 11
buildToolsVersion "18.1.0"
sourceSets {
main {
manifest.srcFile 'AndroidManifest.xml'
java.srcDirs = ['src']
resources.srcDirs = ['src']
aidl.srcDirs = ['src']
renderscript.srcDirs = ['src']
res.srcDirs = ['res']
assets.srcDirs = ['assets']
}
// Move the tests to tests/java, tests/res, etc...
instrumentTest.setRoot('tests')
debug.setRoot('build-types/debug')
release.setRoot('build-types/release')
flavorGroups "abi", "version"
productFlavors {
x86 {
flavorGroup "abi"
}
arm {
flavorGroup "abi"
}
mips {
flavorGroup "abi"
}
}
}
}
有人能帮我解决这个问题吗
干杯,我没有gradle的答案,但我想我现在有了一个适用于任何Android构建工具的通用答案。以下是我关于如何为每个受支持的处理器体系结构创建单独的APK文件的想法:
@echo off
REM My "fat" apk is named atVoice.apk. Change below to whatever or set from %1
set apkfile=atVoice
del *.apk
REM My tools build atVoice-release.apk in bin project sub-dir.
REM Copy it here for splitting.
copy ..\bin\%apkfile%-release.apk %apkfile%.apk
zip -d %apkfile%.apk META-INF/*
REM ------------------- armeabi ------------------------
unzip %apkfile%.apk AndroidManifest.xml
copy/y %apkfile%.apk %apkfile%.zip
zip -d %apkfile%.zip lib/armeabi-v7a/* lib/x86/* lib/mips/*
aminc AndroidManifest.xml 1
zip -f %apkfile%.zip
ren %apkfile%.zip %apkfile%_armeabi.apk
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore d:\users\greg\.android\Hyperionics.keystore -storepass MyPass %apkfile%_armeabi.apk MyKeyName
zipalign 4 %apkfile%_armeabi.apk %apkfile%_armeabi-aligned.apk
del %apkfile%_armeabi.apk
ren %apkfile%_armeabi-aligned.apk %apkfile%_armeabi.apk
REM ------------------- armeabi-v7a ---------------------
copy/y %apkfile%.apk %apkfile%.zip
zip -d %apkfile%.zip lib/armeabi/* lib/x86/* lib/mips/*
aminc AndroidManifest.xml 1
zip -f %apkfile%.zip
ren %apkfile%.zip %apkfile%_armeabi-v7a.apk
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore d:\users\greg\.android\Hyperionics.keystore -storepass MyPass %apkfile%_armeabi-v7a.apk MyKeyName
zipalign 4 %apkfile%_armeabi-v7a.apk %apkfile%_armeabi-v7a-aligned.apk
del %apkfile%_armeabi-v7a.apk
ren %apkfile%_armeabi-v7a-aligned.apk %apkfile%_armeabi-v7a.apk
REM ------------------- x86 ---------------------
copy/y %apkfile%.apk %apkfile%.zip
zip -d %apkfile%.zip lib/armeabi/* lib/armeabi-v7a/* lib/mips/*
aminc AndroidManifest.xml 9
zip -f %apkfile%.zip
ren %apkfile%.zip %apkfile%_x86.apk
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore d:\users\greg\.android\Hyperionics.keystore -storepass MyPass %apkfile%_x86.apk MyKeyName
zipalign 4 %apkfile%_x86.apk %apkfile%_x86-aligned.apk
del %apkfile%_x86.apk
ren %apkfile%_x86-aligned.apk %apkfile%_x86.apk
REM ------------------- MIPS ---------------------
copy/y %apkfile%.apk %apkfile%.zip
zip -d %apkfile%.zip lib/armeabi/* lib/armeabi-v7a/* lib/x86/*
aminc AndroidManifest.xml 10
zip -f %apkfile%.zip
ren %apkfile%.zip %apkfile%_mips.apk
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore d:\users\greg\.android\Hyperionics.keystore -storepass MyPass %apkfile%_mips.apk MyKeyName
zipalign 4 %apkfile%_mips.apk %apkfile%_mips-aligned.apk
del %apkfile%_mips.apk
ren %apkfile%_mips-aligned.apk %apkfile%_mips.apk
del AndroidManifest.xml
del %apkfile%.apk
:done
Greg更新-自发布此帖子以来,gradle构建过程取得了很大进展,因此此答案可能不是推荐的最佳实践,新的更改甚至可能会阻止它。运用你自己的判断力 为此,首先,必须将本机库分别放在以下文件夹层次结构中
lib
-armeabi
-arm.so
-*.so
-
然后压缩lib(不带“s”)文件夹(例如arm.zip和x86.zip),并将“zip”扩展名重命名为“jar”(例如arm.jar和x86.jar)。将这些JAR放在适当的文件夹中(例如armeabi/libs和x86/libs)。现在我们将包括每种口味的依赖项。但我们不能使用“编译文件”…'”。我们必须使用“编译文件…”
e、 g
====
这里有一个更复杂的环境。您不仅有处理器体系结构变体,而且还有处理器的调试库(.jar、.so)。这里的示例有用于Arm调试的Debug.jar和用于Arm发布的NonDebug.jar;对于Arm和X86都是如此。这种配置可以通过使用gradle来实现。请阅读我的SO答案,了解调试文件夹的结构
android {
compileSdkVersion 18
buildToolsVersion "19.0.0"
final DEBUG_ROOT = "build-types/debug"
final RELEASE_ROOT = "build-types/release"
project.ext.set("projRoot", "")
buildTypes {
debug {
project.projRoot = DEBUG_ROOT
dependencies {
debugCompile files(DEBUG_ROOT+"/libs/Debug.jar")
}
}
release {
project.projRoot = RELEASE_ROOT
dependencies {
releaseCompile files(RELEASE_ROOT+"/libs/NonDebug.jar")
}
runProguard true
proguardFile 'proguard.cfg'
}
}
sourceSets {
final PROJ_ROOT = project.ext.get("projRoot")
final BUILD_TYPE_RES = PROJ_ROOT + "/res"
main {
manifest.srcFile 'src/main/AndroidManifest.xml'
java.srcDirs = ['src/main/java']
//resources.srcDirs = ['src/main']
//aidl.srcDirs = ['src/main']
//renderscript.srcDirs = ['src/main']
res.srcDirs = ['src/main/res',BUILD_TYPE_RES]
assets.srcDirs = ['src/main/assets']
}
flavorGroups 'abi'
productFlavors {
arm {
flavorGroup 'abi'
final ARM_LIB_PATH = PROJ_ROOT + "/arm/libs/armeabi.jar"
dependencies {
armCompile files(ARM_LIB_PATH)
}
}
x86 {
flavorGroup 'abi'
final X86_LIB_PATH = PROJ_ROOT + "/x86/libs/x86.jar"
dependencies {
x86Compile files(X86_LIB_PATH)
}
}
}
// Move the tests to tests/java, tests/res, etc...
instrumentTest.setRoot('tests')
// Move the build types to build-types/<type>
// For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ...
// This moves them out of them default location under src/<type>/... which would
// conflict with src/ being used by the main source set.
// Adding new build types or product flavors should be accompanied
// by a similar customization.
debug.setRoot(DEBUG_ROOT)
release.setRoot(RELEASE_ROOT)
}
android{
编译DK18版
buildToolsVersion“19.0.0”
最终调试\u ROOT=“生成类型/调试”
最终版本\u ROOT=“构建类型/版本”
project.ext.set(“projRoot”,“projRoot”)
建筑类型{
调试{
project.projRoot=DEBUG\u ROOT
依赖关系{
调试编译文件(DEBUG_ROOT+“/libs/DEBUG.jar”)
}
}
释放{
project.projRoot=RELEASE\u ROOT
依赖关系{
releaseCompile文件(RELEASE_ROOT+“/libs/NonDebug.jar”)
}
runProguard true
proguard文件“proguard.cfg”
}
}
源集{
final PROJ_ROOT=project.ext.get(“projRoot”)
最终构建类型\u RES=PROJ\u ROOT+“/RES”
主要{
manifest.src文件“src/main/AndroidManifest.xml”
java.srcDirs=['src/main/java']
//resources.srcDirs=['src/main']
//aidl.srcDirs=['src/main']
//renderscript.srcDirs=['src/main']
res.srcDirs=['src/main/res',BUILD\u TYPE\u res]
assets.srcDirs=['src/main/assets']
}
风味组“abi”
产品风味{
手臂{
风味组“abi”
final ARM_LIB_PATH=PROJ_ROOT+“/ARM/libs/armeabi.jar”
依赖关系{
armCompile文件(ARM\u LIB\u路径)
}
}
x86{
风味组“abi”
最终X86_LIB_PATH=PROJ_ROOT+“/X86/libs/X86.jar”
依赖关系{
X86编译文件(X86_LIB_路径)
}
}
}
//将测试移动到tests/java、tests/res等。。。
instrumentTest.setRoot('tests'))
//移动
lib
-x86
-x86.so
-*.so
flavorGroups 'abi'
productFlavors {
arm {
flavorGroup 'abi'
dependencies {
armCompile files('arm/libs/armeabi.jar')
}
}
x86 {
flavorGroup 'abi'
dependencies {
x86Compile files('x86/libs/x86.jar')
}
}
}
android {
compileSdkVersion 18
buildToolsVersion "19.0.0"
final DEBUG_ROOT = "build-types/debug"
final RELEASE_ROOT = "build-types/release"
project.ext.set("projRoot", "")
buildTypes {
debug {
project.projRoot = DEBUG_ROOT
dependencies {
debugCompile files(DEBUG_ROOT+"/libs/Debug.jar")
}
}
release {
project.projRoot = RELEASE_ROOT
dependencies {
releaseCompile files(RELEASE_ROOT+"/libs/NonDebug.jar")
}
runProguard true
proguardFile 'proguard.cfg'
}
}
sourceSets {
final PROJ_ROOT = project.ext.get("projRoot")
final BUILD_TYPE_RES = PROJ_ROOT + "/res"
main {
manifest.srcFile 'src/main/AndroidManifest.xml'
java.srcDirs = ['src/main/java']
//resources.srcDirs = ['src/main']
//aidl.srcDirs = ['src/main']
//renderscript.srcDirs = ['src/main']
res.srcDirs = ['src/main/res',BUILD_TYPE_RES]
assets.srcDirs = ['src/main/assets']
}
flavorGroups 'abi'
productFlavors {
arm {
flavorGroup 'abi'
final ARM_LIB_PATH = PROJ_ROOT + "/arm/libs/armeabi.jar"
dependencies {
armCompile files(ARM_LIB_PATH)
}
}
x86 {
flavorGroup 'abi'
final X86_LIB_PATH = PROJ_ROOT + "/x86/libs/x86.jar"
dependencies {
x86Compile files(X86_LIB_PATH)
}
}
}
// Move the tests to tests/java, tests/res, etc...
instrumentTest.setRoot('tests')
// Move the build types to build-types/<type>
// For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ...
// This moves them out of them default location under src/<type>/... which would
// conflict with src/ being used by the main source set.
// Adding new build types or product flavors should be accompanied
// by a similar customization.
debug.setRoot(DEBUG_ROOT)
release.setRoot(RELEASE_ROOT)
}
src
-main
-jniLibs
-armeabi
-arm.so
-armeabi-v7a
-armv7.so
-x86
-x86.so
-mips
-mips.so
android {
...
splits {
abi {
enable true
reset()
include 'x86', 'armeabi-v7a', 'mips', 'armeabi'
universalApk false
}
}
}
// map for the version code
ext.versionCodes = ['armeabi-v7a':1, mips:2, x86:3]
import com.android.build.OutputFile
android.applicationVariants.all { variant ->
// assign different version code for each output
variant.outputs.each { output ->
output.versionCodeOverride =
project.ext.versionCodes.get(output.getFilter(OutputFile.ABI)) * 1000000 + android.defaultConfig.versionCode
}
}
android {
flavorDimensions "abi"
productFlavors {
fat {
flavorDimension "abi"
ndk {
abiFilters "x86", "armeabi-v7a", "armeabi"
versionCode = 0;
}
}
arm {
flavorDimension "abi"
ndk {
abiFilter "armeabi"
versionCode = 1;
}
}
armv7a {
flavorDimension "abi"
ndk {
abiFilter "armeabi-v7a"
versionCode = 3;
}
}
x86 {
flavorDimension "abi"
ndk {
abiFilter "x86"
versionCode = 6;
}
}
}
}
// Each APK needs a different version code when submitted to Google,
// bump the versionCode we set in defaultConfig
android.applicationVariants.all { variant ->
// Ugly hard coded flavorDimensions position
// If you have more than one flavorDimension, make sure to target the position for "abi"
def abiVersion = variant.productFlavors.get(0).versionCode
variant.mergedFlavor.versionCode = abiVersion * 1000 + android.defaultConfig.versionCode
}
android {
// Rest of Gradle file
splits {
abi {
enable true
reset()
include 'armeabi', 'armeabi-v7a', 'x86'
universalApk true
}
}
}
//Ensures architecture specific APKs have a higher version code
//(otherwise an x86 build would end up using the arm build, which x86 devices can run)
ext.versionCodes = [armeabi:1, 'armeabi-v7a':3, x86:6]
android.applicationVariants.all { variant ->
// assign different version code for each output
variant.outputs.each { output ->
int abiVersionCode = project.ext.versionCodes.get(output.getFilter(OutputFile.ABI)) ?: 0
output.versionCodeOverride = (abiVersionCode * 1000) + android.defaultConfig.versionCode
}
}