Gradle升级至7.3.3后main作为productFlavors名报重复键错误
问题原因
Gradle 7.3及以上版本将main设为内置保留命名,会为所有项目默认预注册对应核心源集(SourceSet)。在productFlavors中手动声明同名main风味时,会触发同键重复注册,抛出Multiple entries with same key: main=[] and main=[]报错,修改flavor名称后冲突消失就是这个原因。
推荐方案(无兼容风险,完全保留
main的使用体验) 不需要强行占用内置保留名,通过内部临时命名+映射规则的方式,可实现和直接命名main完全一致的使用效果,不会引发版本兼容问题:
- 第一步:将
productFlavors中原本的main风味改为临时内部名(比如mainCore),原有配置完全保留,不需要修改任何逻辑
flavorDimensions "mode", "client" productFlavors { /////// Distribution Modes /////// mainCore { // 仅内部注册使用,对外不暴露 dimension "mode" versionName generateVersionName() manifestPlaceholders = [ app_label: "@string/app_name", appIcon: "@mipmap/ic_launcher", appIconRound: "@mipmap/ic_launcher_round" ] } beta { dimension "mode" applicationIdSuffix ".beta" manifestPlaceholders = [ app_label: "@string/app_name", appIcon: "@mipmap/ic_launcher_beta", appIconRound: "@mipmap/ic_launcher_beta_round" ] } // 其余原有flavor配置保持不变 }
- 第二步:在
android配置块内(productFlavors块之后)添加映射规则,让内部临时名完全对外替换为main,不需要调整原有项目目录结构:
android { // 其余原有配置(compileSdk、defaultConfig等)保持不变 // 1. 源集映射:直接读取原有src/main路径下的代码、资源,不需要移动文件 sourceSets { mainCore { java.srcDirs = ['src/main/java'] res.srcDirs = ['src/main/res'] manifest.srcFile 'src/main/AndroidManifest.xml' jniLibs.srcDirs = ['src/main/jniLibs'] assets.srcDirs = ['src/main/assets'] } } // 2. 构建产物名映射:输出apk/aab时自动替换mainCore为main applicationVariants.all { variant -> variant.outputs.all { output -> output.outputFileName = output.outputFileName.replace("mainCore", "main") } } // 3. 构建任务别名:保留原有的assembleMain、installMain等命令使用习惯 gradle.projectsEvaluated { tasks.matching { it.name.contains("MainCore") }.all { originTask -> def aliasName = originTask.name.replace("MainCore", "Main") tasks.create(aliasName) { dependsOn originTask group = originTask.group } } } }
配置完成后同步Gradle即可,使用体验和直接将flavor命名为main没有区别:原有代码路径不需要修改、构建命令可以继续用main关键字、产物命名正常显示main,且不会触发版本兼容问题。
备选Hack方案(可直接在productFlavors中写main,存在兼容风险)
如果一定要直接在productFlavors块中声明main,可以在app模块build.gradle文件的最顶部(android块之前)加入如下配置,提前移除内置注册的main源集规避冲突:
// 注意:该方案为非官方hack手段,后续升级Gradle/AGP版本时可能失效 afterEvaluate { android.sourceSets.remove(android.sourceSets.findByName("main")) }
添加后即可正常在productFlavors中声明main风味,注意需要在main风味配置中补全默认源集路径绑定,否则会找不到代码、资源文件。
内容的提问来源于stack exchange,提问作者Orcun Sevsay
相关产品推荐
相关产品推荐

