Import sources for Android SDK, include proper identifiers for Gradle dependencies

This commit is contained in:
Vyacheslav Karpukhin
2020-01-24 17:19:20 +01:00
parent 663c8e5a46
commit 9788525ec7
2 changed files with 54 additions and 18 deletions
@@ -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>
@@ -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")