Gradle多Flavor项目中如何避免重复编译原生代码
解决多Flavor项目中原生代码重复编译的问题
刚好之前踩过这个坑,给你几个实用的解决方案,能让通用原生代码只编译一次:
方案1:把通用代码放到main共享目录
这是最简单直接的方式——Android Gradle插件默认会把src/main/下的资源、代码作为所有Flavor的共享部分。你只需要:
- 将通用的C/C++代码移到
src/main/jni/目录下 - 如果有预编译的
.so库,放到src/main/jniLibs/对应的ABI子目录里
这样Gradle在构建任何Flavor时,都会复用main目录下原生代码的编译结果,不会重复编译。
方案2:自定义共享SourceSet
如果不想把通用代码放到main里(比如想和Flavor专属代码明确区分),可以单独定义一个共享的SourceSet,让所有Flavor继承它:
在app模块的build.gradle中添加配置:
android { // 先定义一个存放通用原生代码的SourceSet sourceSets { commonNative { jni.srcDirs = ['src/commonNative/jni'] // 如果有头文件或预编译库,也可以指定: // jniLibs.srcDirs = ['src/commonNative/jniLibs'] } // 让每个Flavor都继承这个共享SourceSet flavor1 { jni.srcDirs += commonNative.jni.srcDirs jniLibs.srcDirs += commonNative.jniLibs.srcDirs } flavor2 { jni.srcDirs += commonNative.jni.srcDirs jniLibs.srcDirs += commonNative.jniLibs.srcDirs } // 其他Flavor同理配置 } }
配置完成后,Gradle会将commonNative目录下的代码视为所有Flavor的共享依赖,仅编译一次,所有Flavor复用这个编译产物。
方案3:预编译通用原生代码
如果你的通用原生代码比较稳定,不需要频繁修改,可以提前编译成.so库,然后让所有Flavor直接依赖预编译产物:
- 用NDK Build或CMake单独编译通用代码,生成对应ABI的
.so文件 - 在项目中创建一个共享目录(比如
libs/common/),把.so文件按ABI分类存放(比如libs/common/armeabi-v7a/libcommon.so) - 在
build.gradle中指定这个目录为所有Flavor的jniLibs来源:
android { sourceSets { main { jniLibs.srcDirs += ['libs/common'] } } }
这种方式完全避免了重复编译,适合代码变动少的场景。
额外小技巧:用宏处理少量Flavor差异
如果通用代码里有极少数需要根据Flavor调整的逻辑,不用拆分代码,直接用宏定义处理即可。比如在CMakeLists.txt中根据当前Flavor注入宏:
# 获取当前构建的Flavor(需要在Gradle中传递参数) set(FLAVOR ${CMAKE_FLAVOR}) if(${FLAVOR} STREQUAL "flavor1") add_definitions(-DFLAVOR_SPECIAL=1) else() add_definitions(-DFLAVOR_SPECIAL=0) endif()
然后在Gradle中传递Flavor参数:
android { defaultConfig { externalNativeBuild { cmake { arguments "-DCMAKE_FLAVOR=${productFlavors.name}" } } } }
这样在C/C++代码里就能用#ifdef FLAVOR_SPECIAL来处理差异,大部分代码依然保持共享,只编译一次。
内容的提问来源于stack exchange,提问作者Joan P.S
相关产品推荐
相关产品推荐

