@@ -25,40 +25,47 @@ class AndroidRustPlugin : Plugin<Project> {
2525 val minimumSupportedRustVersion = SemanticVersion (extension.minimumSupportedRustVersion)
2626
2727 androidComponents.finalizeDsl { dsl ->
28- val allRustAbiSet = HashSet <Abi >()
28+ val allRustAbiSet = mutableSetOf <Abi >()
2929 val ndkDirectory = androidExtension.ndkDirectory
3030 val ndkVersion = SemanticVersion (androidExtension.ndkVersion)
3131 val extensionBuildDirectory = File (project.buildDir, " intermediates/rust" )
3232
3333 for (buildType in dsl.buildTypes) {
34- val buildTypeName = buildType.name.capitalize(Locale .getDefault())
34+ val buildTypeNameCap = buildType.name.capitalize(Locale .getDefault())
3535
3636 val variantBuildDirectory = File (extensionBuildDirectory, buildType.name)
3737 val variantJniLibsDirectory = File (variantBuildDirectory, " jniLibs" )
3838
39- val rustBuildType = extension.buildTypes[buildType.name]
40- val rustAbiSet = resolveAbiList(project, extension.targets, rustBuildType?.targets)
41- allRustAbiSet.addAll(rustAbiSet)
42-
43- val cleanTaskName = " cleanRust${buildTypeName} "
39+ val cleanTaskName = " cleanRust${buildTypeNameCap} "
4440 val cleanTask = project.tasks.register(cleanTaskName, RustCleanTask ::class .java) {
4541 this .variantJniLibsDirectory.set(variantJniLibsDirectory)
4642 }
4743
48- for (rustAbi in rustAbiSet) {
49- val buildTaskName = " buildRust${buildTypeName} [${rustAbi.androidName} ]"
50- val buildTask = project.tasks.register(buildTaskName, RustBuildTask ::class .java) {
51- this .abi.set(rustAbi)
52- this .apiLevel.set(dsl.defaultConfig.minSdk ? : 21 )
53- this .ndkVersion.set(ndkVersion)
54- this .ndkDirectory.set(ndkDirectory)
55- this .rustProfile.set(rustBuildType?.profile.orEmpty().ifEmpty { extension.profile })
56- this .rustProjectDirectory.set(extension.path)
57- this .variantBuildDirectory.set(variantBuildDirectory)
58- this .variantJniLibsDirectory.set(variantJniLibsDirectory)
44+ for ((moduleName, module) in extension.modules) {
45+ val moduleNameCap = moduleName.capitalize(Locale .getDefault())
46+ val moduleBuildDirectory = File (variantBuildDirectory, moduleName)
47+
48+ val rustBuildType = module.buildTypes[buildType.name]
49+ val rustConfiguration = mergeRustConfigurations(rustBuildType, module, extension)
50+
51+ val rustAbiSet = resolveAbiList(project, rustConfiguration.targets)
52+ allRustAbiSet.addAll(rustAbiSet)
53+
54+ for (rustAbi in rustAbiSet) {
55+ val buildTaskName = " buildRust${buildTypeNameCap}${moduleNameCap} [${rustAbi.androidName} ]"
56+ val buildTask = project.tasks.register(buildTaskName, RustBuildTask ::class .java) {
57+ this .abi.set(rustAbi)
58+ this .apiLevel.set(dsl.defaultConfig.minSdk ? : 21 )
59+ this .ndkVersion.set(ndkVersion)
60+ this .ndkDirectory.set(ndkDirectory)
61+ this .rustProfile.set(rustConfiguration.profile)
62+ this .rustProjectDirectory.set(module.path)
63+ this .cargoTargetDirectory.set(moduleBuildDirectory)
64+ this .variantJniLibsDirectory.set(variantJniLibsDirectory)
65+ }
66+ buildTask.dependsOn(cleanTask)
67+ tasksByBuildType.getOrPut(buildType.name, ::ArrayList ).add(buildTask)
5968 }
60- buildTask.dependsOn(cleanTask)
61- tasksByBuildType.getOrPut(buildType.name, ::ArrayList ).add(buildTask)
6269 }
6370
6471 dsl.sourceSets.findByName(buildType.name)?.jniLibs?.srcDir(variantJniLibsDirectory)
@@ -80,30 +87,43 @@ class AndroidRustPlugin : Plugin<Project> {
8087 }
8188 }
8289
83- private fun resolveAbiList (
84- project : Project ,
85- extension : Collection <String >,
86- buildType : Collection <String >? ,
87- ): Collection <Abi > {
88- val requested = when (buildType != null && buildType.isNotEmpty()) {
89- true -> Abi .fromRustNames(buildType)
90- else -> Abi .fromRustNames(extension)
91- }
90+ private fun resolveAbiList (project : Project , requested : Collection <String >): Collection <Abi > {
91+ val requestedAbi = Abi .fromRustNames(requested)
9292
93- val injected = Abi .fromInjectedBuildAbi(project)
94- if (injected .isEmpty()) {
95- return requested
93+ val injectedAbi = Abi .fromInjectedBuildAbi(project)
94+ if (injectedAbi .isEmpty()) {
95+ return requestedAbi
9696 }
9797
98- val intersection = requested .intersect(injected )
99- check(intersection .isNotEmpty()) {
100- " ABIs requested by IDE ($injected ) are not supported by the build config ($requested )"
98+ val intersectionAbi = requestedAbi .intersect(injectedAbi )
99+ check(intersectionAbi .isNotEmpty()) {
100+ " ABIs requested by IDE ($injectedAbi ) are not supported by the build config ($requested )"
101101 }
102102
103103 return when {
104- intersection.contains(Abi .Arm64 ) -> listOf (Abi .Arm64 )
105- intersection.contains(Abi .X86_64 ) -> listOf (Abi .X86_64 )
106- else -> listOf (intersection.first())
104+ intersectionAbi.contains(Abi .Arm64 ) -> listOf (Abi .Arm64 )
105+ intersectionAbi.contains(Abi .X86_64 ) -> listOf (Abi .X86_64 )
106+ else -> listOf (intersectionAbi.first())
107+ }
108+ }
109+
110+ private fun mergeRustConfigurations (vararg configurations : AndroidRustConfiguration ? ): AndroidRustConfiguration {
111+ val defaultConfiguration = AndroidRustConfiguration ().also {
112+ it.profile = " release"
113+ it.targets = Abi .values().mapTo(ArrayList (), Abi ::rustName)
107114 }
115+
116+ return configurations.asSequence()
117+ .filterNotNull()
118+ .plus(defaultConfiguration)
119+ .reduce { result, base ->
120+ if (result.profile.isEmpty()) {
121+ result.profile = base.profile
122+ }
123+ if (result.targets.isEmpty()) {
124+ result.targets = base.targets
125+ }
126+ result
127+ }
108128 }
109129}
0 commit comments