Import sources for Android SDK, include proper identifiers for Gradle dependencies
This commit is contained in:
@@ -20,6 +20,7 @@ import org.gradle.api.provider.Provider
|
||||
import org.gradle.api.tasks.Exec
|
||||
import org.gradle.api.tasks.TaskProvider
|
||||
import org.jetbrains.kotlin.gradle.KotlinMPPGradleModel.Companion.NO_KOTLIN_NATIVE_HOME
|
||||
import org.jetbrains.plugins.gradle.DefaultExternalDependencyId
|
||||
import org.jetbrains.plugins.gradle.model.*
|
||||
import org.jetbrains.plugins.gradle.tooling.ErrorMessageBuilder
|
||||
import org.jetbrains.plugins.gradle.tooling.ModelBuilderService
|
||||
@@ -170,13 +171,13 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildAndroidDeps(kotlinExt: Any, project: Project): Map<String, List<File>>? {
|
||||
private fun buildAndroidDeps(kotlinExt: Any, project: Project): Map<String, List<Any>>? {
|
||||
val includeAndroidDeps = project.properties["kotlin.include.android.dependencies"]?.toString()?.toBoolean() == true
|
||||
if (includeAndroidDeps) {
|
||||
val getAndroidSourceSetDependencies =
|
||||
kotlinExt.javaClass.getMethodOrNull("getAndroidSourceSetDependencies", Project::class.java)
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
return getAndroidSourceSetDependencies?.let { it(kotlinExt, project) } as Map<String, List<File>>?
|
||||
return getAndroidSourceSetDependencies?.let { it(kotlinExt, project) } as Map<String, List<Any>>?
|
||||
} else {
|
||||
return emptyMap()
|
||||
}
|
||||
@@ -187,7 +188,7 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
|
||||
dependencyResolver: DependencyResolver,
|
||||
project: Project,
|
||||
dependencyMapper: KotlinDependencyMapper,
|
||||
androidDeps: Map<String, List<File>>?
|
||||
androidDeps: Map<String, List<Any>>?
|
||||
): KotlinSourceSetProto? {
|
||||
val sourceSetClass = gradleSourceSet.javaClass
|
||||
val getLanguageSettings = sourceSetClass.getMethodOrNull("getLanguageSettings") ?: return null
|
||||
@@ -607,7 +608,7 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
|
||||
gradleSourceSet: Named,
|
||||
dependencyResolver: DependencyResolver,
|
||||
project: Project,
|
||||
androidDeps: Map<String, List<File>>?
|
||||
androidDeps: Map<String, List<Any>>?
|
||||
): List<KotlinDependency> {
|
||||
return ArrayList<KotlinDependency>().apply {
|
||||
val transformationBuilder = MetadataDependencyTransformationBuilder(gradleSourceSet)
|
||||
@@ -623,11 +624,33 @@ class KotlinMPPGradleModelBuilder : ModelBuilderService {
|
||||
this += buildDependencies(
|
||||
gradleSourceSet, dependencyResolver, "getRuntimeOnlyMetadataConfigurationName", "RUNTIME", project, transformationBuilder
|
||||
)
|
||||
|
||||
androidDeps?.get(gradleSourceSet.name)?.let { this += DefaultFileCollectionDependency(it) }
|
||||
this += buildAndroidSourceSetDependencies(androidDeps, gradleSourceSet)
|
||||
}
|
||||
}
|
||||
|
||||
private fun buildAndroidSourceSetDependencies(
|
||||
androidDeps: Map<String, List<Any>>?,
|
||||
gradleSourceSet: Named
|
||||
): Collection<KotlinDependency> {
|
||||
return androidDeps?.get(gradleSourceSet.name)?.map { it ->
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val collection = it["getCollection"] as Set<File>?
|
||||
if (collection == null) {
|
||||
DefaultExternalLibraryDependency().apply {
|
||||
(id as? DefaultExternalDependencyId)?.apply {
|
||||
name = it["getName"] as String?
|
||||
group = it["getGroup"] as String?
|
||||
version = it["getVersion"] as String?
|
||||
}
|
||||
file = it["getJar"] as File
|
||||
source = it["getSource"] as File?
|
||||
}
|
||||
} else {
|
||||
DefaultFileCollectionDependency(collection)
|
||||
}
|
||||
} ?: emptyList()
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
private fun safelyGetArguments(compileKotlinTask: Task, accessor: Method?) = try {
|
||||
accessor?.invoke(compileKotlinTask) as? List<String>
|
||||
|
||||
+25
-12
@@ -19,12 +19,11 @@ import org.gradle.api.InvalidUserCodeException
|
||||
import org.gradle.api.NamedDomainObjectCollection
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.*
|
||||
import org.gradle.api.artifacts.component.ModuleComponentIdentifier
|
||||
import org.gradle.api.artifacts.component.ModuleComponentSelector
|
||||
import org.gradle.api.artifacts.result.ResolvedComponentResult
|
||||
import org.gradle.api.file.FileSystemLocation
|
||||
import org.gradle.api.internal.artifacts.dependencies.DefaultExternalModuleDependency
|
||||
import org.gradle.api.provider.Provider
|
||||
import org.gradle.internal.component.external.model.DefaultModuleComponentIdentifier
|
||||
import org.gradle.util.ConfigureUtil
|
||||
import org.jetbrains.kotlin.gradle.plugin.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
||||
@@ -73,7 +72,16 @@ open class KotlinMultiplatformExtension :
|
||||
KotlinSoftwareComponentWithCoordinatesAndPublication("kotlin", targets)
|
||||
}
|
||||
|
||||
private fun getAndroidSdkJar(project: Project): File? {
|
||||
data class AndroidDependency(
|
||||
val name: String? = null,
|
||||
val jar: File? = null,
|
||||
val source: File? = null,
|
||||
val group: String? = null,
|
||||
val version: String? = null,
|
||||
val collection: Set<File>? = null
|
||||
)
|
||||
|
||||
private fun getAndroidSdkJar(project: Project): AndroidDependency? {
|
||||
val androidExtension = project.extensions.findByName("android") as BaseExtension? ?: return null
|
||||
val sdkLocation = getClassOrNull("com.android.build.gradle.internal.SdkLocationSourceSet")?.let { sdkLocationSourceSetClass ->
|
||||
val sdkLocationSourceSet = sdkLocationSourceSetClass.kotlin.constructors.firstOrNull()?.let { callable ->
|
||||
@@ -90,7 +98,11 @@ open class KotlinMultiplatformExtension :
|
||||
val sdkHandler = AndroidSdkHandler.getInstance(sdkLocation)
|
||||
val logger = LoggerProgressIndicatorWrapper(LoggerWrapper(project.logger))
|
||||
val androidTarget = sdkHandler.getAndroidTargetManager(logger).getTargetFromHashString(androidExtension.compileSdkVersion, logger)
|
||||
return File(androidTarget.getPath(IAndroidTarget.ANDROID_JAR))
|
||||
return AndroidDependency(
|
||||
androidTarget.fullName,
|
||||
File(androidTarget.getPath(IAndroidTarget.ANDROID_JAR)),
|
||||
File(androidTarget.getPath(IAndroidTarget.SOURCES))
|
||||
)
|
||||
}
|
||||
|
||||
private fun getClassOrNull(s: String) =
|
||||
@@ -118,7 +130,7 @@ open class KotlinMultiplatformExtension :
|
||||
return Version.parseVersion(version)?.isOrGreaterThan(3, 6) ?: false
|
||||
}
|
||||
|
||||
fun getAndroidSourceSetDependencies(project: Project): Map<String, List<File>?> {
|
||||
fun getAndroidSourceSetDependencies(project: Project): Map<String, List<AndroidDependency>?> {
|
||||
if (!isAndroidPluginCompatible()) return emptyMap()
|
||||
|
||||
data class SourceSetConfigs(val implConfig: Configuration, val compileConfig: Configuration)
|
||||
@@ -139,8 +151,8 @@ open class KotlinMultiplatformExtension :
|
||||
return sourceSet2Impl.mapValues { entry ->
|
||||
val dependencies = findDependencies(allImplConfigs, entry.value.implConfig)
|
||||
|
||||
val selfResolved = dependencies.filterIsInstance<SelfResolvingDependency>().flatMap { it.resolve() }
|
||||
val resolvedExternal = dependencies.filterIsInstance<DefaultExternalModuleDependency>()
|
||||
val selfResolved = dependencies.filterIsInstance<SelfResolvingDependency>().map { AndroidDependency(collection = it.resolve()) }
|
||||
val resolvedExternal = dependencies.filterIsInstance<ExternalModuleDependency>()
|
||||
.flatMap { collectDependencies(it.module, entry.value.compileConfig) }
|
||||
|
||||
val result = (selfResolved + resolvedExternal + androidSdkJar).toMutableList()
|
||||
@@ -152,7 +164,7 @@ open class KotlinMultiplatformExtension :
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val rClassOutputJar =
|
||||
linkAppClass.getMethodOrNull("getRClassOutputJar")?.invoke(task) as Provider<FileSystemLocation>?
|
||||
rClassOutputJar?.orNull?.asFile?.let { result += it }
|
||||
rClassOutputJar?.orNull?.asFile?.let { result += AndroidDependency("R.jar", it) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,15 +176,16 @@ open class KotlinMultiplatformExtension :
|
||||
private fun collectDependencies(
|
||||
module: ModuleIdentifier,
|
||||
compileClasspathConf: Configuration
|
||||
): List<File> {
|
||||
): List<AndroidDependency> {
|
||||
val viewConfig: (ArtifactView.ViewConfiguration) -> Unit = { config ->
|
||||
config.attributes { it.attribute(ARTIFACT_TYPE, AndroidArtifacts.ArtifactType.JAR.type) }
|
||||
config.isLenient = true
|
||||
}
|
||||
|
||||
val resolvedArtifacts = compileClasspathConf.incoming.artifactView(viewConfig).artifacts.mapNotNull {
|
||||
val id = (it.id.componentIdentifier as? DefaultModuleComponentIdentifier)?.moduleIdentifier ?: return@mapNotNull null
|
||||
id to it
|
||||
val componentIdentifier = it.id.componentIdentifier as? ModuleComponentIdentifier ?: return@mapNotNull null
|
||||
val id = componentIdentifier.moduleIdentifier ?: return@mapNotNull null
|
||||
id to AndroidDependency(id.name, it.file, null, id.group, componentIdentifier.version)
|
||||
}.toMap()
|
||||
|
||||
val resolutionResults = compileClasspathConf.incoming.resolutionResult.allComponents.mapNotNull {
|
||||
@@ -181,7 +194,7 @@ open class KotlinMultiplatformExtension :
|
||||
}.toMap()
|
||||
|
||||
val deps = HashSet<ModuleIdentifier>().also { doCollectDependencies(listOf(module), resolutionResults, it) }
|
||||
return deps.mapNotNull { resolvedArtifacts[it] }.map { it.file }
|
||||
return deps.mapNotNull { resolvedArtifacts[it] }
|
||||
}
|
||||
|
||||
@Suppress("UnstableApiUsage")
|
||||
|
||||
Reference in New Issue
Block a user