Restructure source JARs logic, move it to components management

Move the logic of attaching a source JAR to a publication to the
components management part, as building a source JAR will be done
differently for Android.
This commit is contained in:
Sergey Igushkin
2018-12-26 17:37:46 +03:00
parent d211bd53c9
commit 9a2dce7ea5
4 changed files with 65 additions and 31 deletions
@@ -11,6 +11,7 @@ import org.gradle.api.Project
import org.gradle.api.attributes.Attribute
import org.gradle.api.attributes.AttributeContainer
import org.gradle.api.internal.FeaturePreviews
import org.gradle.api.internal.component.SoftwareComponentInternal
import org.gradle.api.internal.file.FileResolver
import org.gradle.api.internal.plugins.DslObject
import org.gradle.api.plugins.JavaBasePlugin
@@ -29,6 +30,7 @@ import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultLanguageSettingsBuilder
import org.jetbrains.kotlin.gradle.utils.SingleWarningPerBuild
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
import org.jetbrains.kotlin.konan.target.HostManager
import org.jetbrains.kotlin.konan.target.presetName
@@ -87,8 +89,6 @@ class KotlinMultiplatformPlugin(
KotlinMetadataTargetPreset(project, instantiator, fileResolver, kotlinPluginVersion),
METADATA_TARGET_NAME
)
configureSourceJars(project)
configurePublishingWithMavenPublish(project)
// propagate compiler plugin options to the source set language settings
@@ -190,8 +190,9 @@ class KotlinMultiplatformPlugin(
// do this in whenEvaluated since older Gradle versions seem to check the files in the variant eagerly:
project.whenEvaluated {
from(variant)
(project.tasks.findByName(sourcesJarTaskName) as Jar?)?.let { sourcesJar ->
artifact(sourcesJar)
if (variant is SoftwareComponentInternal) {
variant.usages.filterIsInstance<KotlinUsageContext>().map { it.sourcesArtifact }.distinct()
.forEach { artifact(it) }
}
}
(this as MavenPublicationInternal).publishWithOriginalFileName()
@@ -200,31 +201,7 @@ class KotlinMultiplatformPlugin(
(variant as? KotlinTargetComponentWithPublication)?.publicationDelegate = variantPublication
publicationConfigureActions.all { it.execute(variantPublication) }
}
}
private val KotlinTarget.sourcesJarTaskName get() = disambiguateName("sourcesJar")
private fun configureSourceJars(project: Project) = with(project.kotlinExtension as KotlinMultiplatformExtension) {
targets.all { target ->
val mainCompilation = target.compilations.findByName(KotlinCompilation.MAIN_COMPILATION_NAME)
// If a target has no `main` compilation (e.g. Android), don't create the source JAR
?: return@all
val sourcesJar = project.tasks.create(target.sourcesJarTaskName, Jar::class.java) { sourcesJar ->
sourcesJar.appendix = target.targetName.toLowerCase()
sourcesJar.classifier = "sources"
}
project.afterEvaluate { _ ->
val compiledSourceSets = mainCompilation.allKotlinSourceSets
compiledSourceSets.forEach { sourceSet ->
sourcesJar.from(sourceSet.kotlin) { copySpec ->
copySpec.into(sourceSet.name)
}
}
}
}
}
private fun configureSourceSets(project: Project) = with(project.kotlinExtension as KotlinMultiplatformExtension) {
@@ -293,6 +270,28 @@ class KotlinMultiplatformPlugin(
}
}
internal fun sourcesJarTask(compilation: KotlinCompilation<*>, componentName: String?, artifactNameAppendix: String): Jar {
val project = compilation.target.project
val taskName = lowerCamelCaseName(componentName, "sourcesJar")
(project.tasks.findByName(taskName) as? Jar)?.let { return it }
val result = project.tasks.create(taskName, Jar::class.java) { sourcesJar ->
sourcesJar.appendix = artifactNameAppendix
sourcesJar.classifier = "sources"
}
project.whenEvaluated {
compilation.allKotlinSourceSets.forEach { sourceSet ->
result.from(sourceSet.kotlin) { copySpec ->
copySpec.into(sourceSet.name)
}
}
}
return result
}
internal fun compilationsBySourceSet(project: Project): Map<KotlinSourceSet, Set<KotlinCompilation<*>>> =
HashMap<KotlinSourceSet, MutableSet<KotlinCompilation<*>>>().also { result ->
for (target in project.multiplatformExtension!!.targets) {
@@ -38,6 +38,7 @@ object NativeUsage {
interface KotlinUsageContext : UsageContext {
val compilation: KotlinCompilation<*>
val dependencyConfigurationName: String
val sourcesArtifact: PublishArtifact?
}
class DefaultKotlinUsageContext(
@@ -45,6 +46,7 @@ class DefaultKotlinUsageContext(
private val usage: Usage,
override val dependencyConfigurationName: String,
private val publishWithGradleMetadata: Boolean,
override val sourcesArtifact: PublishArtifact? = null,
private val overrideConfigurationArtifacts: Set<PublishArtifact>? = null
) : KotlinUsageContext {
@@ -73,7 +75,7 @@ class DefaultKotlinUsageContext(
override fun getArtifacts(): Set<PublishArtifact> =
overrideConfigurationArtifacts ?:
// TODO Gradle Java plugin does that in a different way; check whether we can improve this
// TODO Gradle Java plugin does that in a different way; check whether we can improve this
configuration.artifacts
override fun getAttributes(): AttributeContainer =
@@ -55,6 +55,9 @@ abstract class KotlinOnlyTargetPreset<T : KotlinCompilation<*>>(
result.compilations.all { compilation ->
buildCompilationProcessor(compilation).run()
if (compilation.name == KotlinCompilation.MAIN_COMPILATION_NAME) {
sourcesJarTask(compilation, result.targetName, result.targetName.toLowerCase())
}
}
return result
@@ -9,7 +9,9 @@ import org.gradle.api.Action
import org.gradle.api.DomainObjectSet
import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.Project
import org.gradle.api.artifacts.ConfigurablePublishArtifact
import org.gradle.api.artifacts.Dependency
import org.gradle.api.artifacts.PublishArtifact
import org.gradle.api.attributes.Attribute
import org.gradle.api.attributes.AttributeContainer
import org.gradle.api.attributes.Usage.JAVA_API
@@ -25,6 +27,7 @@ import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
import org.jetbrains.kotlin.gradle.utils.lowerSpinalCaseName
import org.jetbrains.kotlin.konan.target.KonanTarget
abstract class AbstractKotlinTarget(
@@ -98,6 +101,8 @@ abstract class AbstractKotlinTarget(
val publishWithKotlinMetadata = (project.kotlinExtension as? KotlinMultiplatformExtension)?.isGradleMetadataAvailable
?: true // In non-MPP project, these usage contexts do not get published anyway
val sourcesJarArtifact = sourcesJarArtifact(producingCompilation, componentName, artifactNameAppendix)
// Here, `JAVA_API` and `JAVA_RUNTIME_JARS` are used intentionally as Gradle needs this for
// ordering of the usage contexts (prioritizing the dependencies) when merging them into the POM;
// These Java usages should not be replaced with the custom Kotlin usages.
@@ -109,11 +114,36 @@ abstract class AbstractKotlinTarget(
producingCompilation,
project.usageByName(usageName),
dependenciesConfigurationName,
publishWithKotlinMetadata
)
publishWithKotlinMetadata,
sourcesJarArtifact
)
}
}
protected fun sourcesJarArtifact(
producingCompilation: KotlinCompilation<*>,
componentName: String,
artifactNameAppendix: String,
classifierPrefix: String? = null
): PublishArtifact {
val sourcesJarTask = sourcesJarTask(producingCompilation, componentName, artifactNameAppendix)
val sourceArtifactConfigurationName = producingCompilation.disambiguateName("sourceArtifacts")
val sourcesJarArtifact = producingCompilation.target.project.run {
(configurations.findByName(sourceArtifactConfigurationName) ?: run {
val configuration = configurations.create(sourceArtifactConfigurationName) {
it.isCanBeResolved = false
it.isCanBeConsumed = false
}
artifacts.add(sourceArtifactConfigurationName, sourcesJarTask)
configuration
}).artifacts.single().apply {
this as ConfigurablePublishArtifact
classifier = lowerSpinalCaseName(classifierPrefix, "sources")
}
}
return sourcesJarArtifact
}
@Suppress("UNCHECKED_CAST")
internal val publicationConfigureActions =
WrapUtil.toDomainObjectSet(Action::class.java) as DomainObjectSet<Action<MavenPublication>>