AOSP源码树中能否配置多Kotlin编译器版本并按需使用?
在AOSP中同时使用多版本Kotlin编译器的实现方案
可以实现,但需要通过定制Soong规则、隔离编译器资源来规避模块冲突和版本兼容问题,以下是具体可行的方案:
1. 隔离多版本Kotlin编译器资源
将不同版本的Kotlin编译器放置在独立的目录下(比如prebuilts/tools/common/kotlin/<version>),并为每个版本编写独立的Android.bp,使用唯一的模块名称避免冲突:
// prebuilts/tools/common/kotlin/1.9/Android.bp java_import { name: "kotlin-compiler-1.9", jars: ["lib/kotlin-compiler.jar", "lib/kotlin-compiler-embeddable.jar"], visibility: ["//visibility:private"], } java_import { name: "kotlin-stdlib-1.9", jars: ["lib/kotlin-stdlib.jar", "lib/kotlin-stdlib-jdk8.jar"], visibility: ["//visibility:private"], }
默认版本的编译器保持原目录和模块名称不变,确保全局项目默认使用它。
2. 为特定模块定制编译规则
方式一:扩展Soong核心规则(推荐长期方案)
修改build/soong/kotlin/kotlin.go,为Kotlin编译模块添加版本指定属性,并在编译逻辑中选择对应版本的编译器:
// 注册自定义Kotlin库模块类型 func init() { android.RegisterModuleType("kotlin_library_versioned", VersionedKotlinLibraryFactory) } func VersionedKotlinLibraryFactory() android.Module { module := NewKotlinLibrary() // 添加版本指定属性 module.AddProperties(&struct { Kotlin_compiler_version string `android:"arch_variant"` }{}) return module } // 在编译阶段根据属性选择编译器依赖 func (m *kotlinLibrary) getCompilerDeps(ctx android.ModuleContext) []string { props := m.properties.(*struct { Kotlin_compiler_version string }) if props.Kotlin_compiler_version == "1.9" { return []string{"//prebuilts/tools/common/kotlin/1.9:kotlin-compiler-1.9"} } // 默认使用全局编译器 return []string{"//prebuilts/tools/common/kotlin:kotlin-compiler"} }
之后在需要指定版本的项目中使用kotlin_library_versioned替代默认的kotlin_library,并设置版本属性:
kotlin_library_versioned { name: "MyCustomLib", kotlin_compiler_version: "1.9", srcs: ["src/main/kotlin/**/*.kt"], // 其他配置... }
方式二:局部替换依赖与编译命令(临时快速方案)
如果不想修改Soong核心代码,可在问题项目的Android.bp中直接替换依赖并指定编译命令:
android_app { name: "ProblemApp", srcs: ["src/main/kotlin/**/*.kt"], // 替换默认stdlib为指定版本 static_libs: [ "//prebuilts/tools/common/kotlin/1.9:kotlin-stdlib-1.9", // 其他依赖... ], // 自定义编译命令,指定使用目标版本的kotlinc compile_cmd: "$(PREBUILT_TOOLS)/kotlin/1.9/bin/kotlinc $(srcs) -cp $(classpath) -d $(out_dir)/classes.jar", }
3. 解决模块重复问题
- 所有自定义版本的编译器模块必须使用唯一名称,且设置
visibility: ["//visibility:private"],仅允许指定项目引用 - 确保默认版本的编译器模块未被覆盖,全局项目默认依赖它
4. 注意事项
- 依赖传递:如果某项目使用了指定版本的Kotlin,其依赖的库也需确保兼容该版本,否则可能出现编译或运行时异常
- 编译缓存:修改编译器版本后,需清理对应项目的编译缓存(
make clean-<module-name>)避免缓存冲突
内容的提问来源于stack exchange,提问作者Gawcio
相关产品推荐
相关产品推荐

