如何在build.gradle中获取当前运行的Gradle assemble任务名或ABI?
解决Gradle按ABI打包时动态禁用Native Libraries构建的问题
我来帮你搞定这个需求!在Gradle中我们可以通过解析当前执行的任务名提取目标ABI,再根据这个ABI动态控制Native Libraries的编译或打包,具体实现步骤如下:
一、从任务名中提取目标ABI
Gradle提供了gradle.startParameter.taskNames来获取当前执行的所有任务列表,我们可以在项目评估阶段遍历这个列表,通过正则匹配提取出任务名里的ABI标识:
// 定义变量存储当前要构建的目标ABI def targetAbi = null // 项目评估完成后解析任务名(此时所有任务已初始化) gradle.projectsEvaluated { gradle.startParameter.taskNames.each { taskName -> // 匹配assemble<ABI><BuildType>格式的任务,比如assembleMipsDebug、assembleArmeabi-v7aRelease def abiMatcher = taskName =~ /assemble([A-Za-z\-]+)(Debug|Release)/ if (abiMatcher.matches()) { // 提取ABI并转为小写格式(确保和native库目录名一致) targetAbi = abiMatcher[0][1].toLowerCase() println "当前目标ABI: $targetAbi" } } }
这段代码会自动识别类似assembleMipsDebug的任务,把mips提取出来存到targetAbi变量里,带连字符的ABI(比如armeabi-v7a)也能正常匹配。
二、根据目标ABI动态控制Native Libraries构建
接下来我们可以根据targetAbi的值,调整Native Libraries的编译或打包配置,分两种场景说明:
场景1:动态控制CMake/NDK-Build的编译过程
如果你用CMake或NDK-Build编译Native代码,可以把targetAbi作为参数传递给构建脚本,在脚本中判断是否编译指定库:
用CMake的例子
在build.gradle的externalNativeBuild中传递参数:
android { // 先配置ABI拆分(确保只生成对应ABI的APK) splits { abi { enable true reset() include 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64', 'mips' universalApk false } } externalNativeBuild { cmake { path "CMakeLists.txt" // 把目标ABI传递给CMake arguments "-DTARGET_ABI=$targetAbi" } } }
然后在CMakeLists.txt中判断是否编译指定库:
# 只有当目标ABI不是mips时,才编译foo库 if(NOT TARGET_ABI STREQUAL "mips") add_library(foo SHARED src/main/cpp/foo.cpp) # 其他链接、配置逻辑... endif()
用NDK-Build的例子
在build.gradle中传递参数:
android { splits { abi { enable true reset() include 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64', 'mips' universalApk false } } externalNativeBuild { ndkBuild { path "Android.mk" arguments "TARGET_ABI=$targetAbi" } } }
在Android.mk中控制模块编译:
# 如果是mips架构,跳过bar模块的编译 ifeq ($(TARGET_ABI),mips) LOCAL_MODULES_TO_SKIP := bar else # 正常编译所有模块 include $(call all-subdir-makefiles) endif
场景2:过滤已编译的Native库(适用于预编译库)
如果你用的是预编译好的Native库,可以直接在Gradle中过滤要打包的库目录:
android { sourceSets { main { jniLibs.srcDirs = ["src/main/jniLibs"] // 根据目标ABI过滤库目录 if (targetAbi == 'mips') { // 只保留mips的库,排除其他架构 jniLibs.exclude '**/armeabi-v7a/**', '**/arm64-v8a/**', '**/x86/**', '**/x86_64/**' } else { // 排除mips的库 jniLibs.exclude '**/mips/**' } } } }
三、注意事项
- 必须在
gradle.projectsEvaluated阶段解析任务名:这个阶段Gradle已经完成了所有任务的初始化,能正确获取到执行的任务列表;如果在更早的阶段(比如项目刚初始化时),任务列表可能还未生成。 - 多任务执行的情况:如果同时执行多个assemble任务(比如
assembleMipsDebug和assembleArmeabiDebug),targetAbi会被最后一个匹配的任务覆盖。如果需要支持多任务,你可以调整逻辑,把所有匹配到的ABI都收集起来处理。
内容的提问来源于stack exchange,提问作者Poka Yoke
相关产品推荐
相关产品推荐

