1008 lines
37 KiB
Kotlin
1008 lines
37 KiB
Kotlin
@file:Suppress("UNUSED_VARIABLE", "NAME_SHADOWING")
|
|
import org.gradle.api.internal.component.SoftwareComponentInternal
|
|
import org.gradle.api.internal.component.UsageContext
|
|
import org.gradle.jvm.tasks.Jar
|
|
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
|
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages
|
|
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsTargetDsl
|
|
import org.jetbrains.kotlin.gradle.targets.js.d8.D8RootPlugin
|
|
import org.jetbrains.kotlin.gradle.targets.js.dsl.ExperimentalWasmDsl
|
|
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinTargetWithNodeJsDsl
|
|
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinWasmTargetDsl
|
|
import org.jetbrains.kotlin.gradle.targets.js.ir.KotlinJsIrLink
|
|
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile
|
|
import org.jetbrains.kotlin.gradle.tasks.UsesKotlinJavaToolchain
|
|
import plugins.configureDefaultPublishing
|
|
import plugins.configureKotlinPomAttributes
|
|
import kotlin.io.path.copyTo
|
|
|
|
plugins {
|
|
id("kotlin-multiplatform")
|
|
`maven-publish`
|
|
signing
|
|
}
|
|
|
|
description = "Kotlin Standard Library"
|
|
|
|
configureJvmToolchain(JdkMajorVersion.JDK_1_8)
|
|
|
|
fun resolvingConfiguration(name: String, configure: Action<Configuration> = Action {}) =
|
|
configurations.create(name) {
|
|
isCanBeResolved = true
|
|
isCanBeConsumed = false
|
|
configure(this)
|
|
}
|
|
fun outgoingConfiguration(name: String, configure: Action<Configuration> = Action {}) =
|
|
configurations.create(name) {
|
|
isCanBeResolved = false
|
|
isCanBeConsumed = true
|
|
configure(this)
|
|
}
|
|
|
|
val configurationBuiltins = resolvingConfiguration("builtins") {
|
|
attributes.attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, project.objects.named(LibraryElements.JAR))
|
|
}
|
|
dependencies {
|
|
configurationBuiltins(project(":core:builtins"))
|
|
}
|
|
|
|
val builtinsDir = "${rootDir}/core/builtins"
|
|
val builtinsSrcDir = "${buildDir}/src/builtin-sources"
|
|
|
|
val jsDir = "${projectDir}/js"
|
|
|
|
// for js-ir
|
|
val jsIrMainSources = "${buildDir}/src/jsMainSources"
|
|
lateinit var jsIrTarget: KotlinJsTargetDsl
|
|
|
|
val commonOptIns = listOf(
|
|
"kotlin.ExperimentalMultiplatform",
|
|
"kotlin.contracts.ExperimentalContracts",
|
|
)
|
|
val commonTestOptIns = listOf(
|
|
"kotlin.ExperimentalUnsignedTypes",
|
|
"kotlin.ExperimentalStdlibApi",
|
|
"kotlin.io.encoding.ExperimentalEncodingApi",
|
|
)
|
|
|
|
kotlin {
|
|
val renderDiagnosticNames by extra(project.kotlinBuildProperties.renderDiagnosticNames)
|
|
val diagnosticNamesArg = if (renderDiagnosticNames) "-Xrender-internal-diagnostic-names" else null
|
|
|
|
metadata {
|
|
compilations {
|
|
all {
|
|
compileTaskProvider.configure {
|
|
kotlinOptions {
|
|
freeCompilerArgs = listOfNotNull(
|
|
"-Xallow-kotlin-package",
|
|
"-module-name", "kotlin-stdlib-common",
|
|
"-Xexpect-actual-classes",
|
|
diagnosticNamesArg,
|
|
)
|
|
}
|
|
// workaround for compiling legacy MPP metadata, remove when this compilation is not needed anymore
|
|
// restate the list of opt-ins
|
|
compilerOptions.optIn.addAll(commonOptIns)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
jvm {
|
|
withJava()
|
|
compilations {
|
|
val compileOnlyDeclarations by creating {
|
|
compileTaskProvider.configure {
|
|
kotlinOptions {
|
|
freeCompilerArgs = listOfNotNull("-Xallow-kotlin-package", diagnosticNamesArg)
|
|
}
|
|
}
|
|
}
|
|
|
|
val main by getting {
|
|
compileTaskProvider.configure {
|
|
this as UsesKotlinJavaToolchain
|
|
kotlinJavaToolchain.toolchain.use(getToolchainLauncherFor(JdkMajorVersion.JDK_1_6))
|
|
kotlinOptions {
|
|
moduleName = "kotlin-stdlib"
|
|
jvmTarget = "1.8"
|
|
// providing exhaustive list of args here
|
|
freeCompilerArgs = listOfNotNull(
|
|
"-Xallow-kotlin-package",
|
|
"-Xexpect-actual-classes",
|
|
"-Xmultifile-parts-inherit",
|
|
"-Xuse-14-inline-classes-mangling-scheme",
|
|
"-Xbuiltins-from-sources",
|
|
"-Xno-new-java-annotation-targets",
|
|
diagnosticNamesArg,
|
|
)
|
|
}
|
|
}
|
|
defaultSourceSet {
|
|
dependencies {
|
|
compileOnly(compileOnlyDeclarations.output.allOutputs)
|
|
}
|
|
}
|
|
}
|
|
val mainJdk7 by creating {
|
|
associateWith(main)
|
|
compileTaskProvider.configure {
|
|
this as UsesKotlinJavaToolchain
|
|
kotlinJavaToolchain.toolchain.use(getToolchainLauncherFor(JdkMajorVersion.JDK_1_7))
|
|
kotlinOptions {
|
|
moduleName = "kotlin-stdlib-jdk7"
|
|
jvmTarget = "1.8"
|
|
freeCompilerArgs = listOfNotNull(
|
|
"-Xallow-kotlin-package",
|
|
"-Xmultifile-parts-inherit",
|
|
"-Xno-new-java-annotation-targets",
|
|
diagnosticNamesArg,
|
|
)
|
|
}
|
|
}
|
|
}
|
|
val mainJdk8 by creating {
|
|
associateWith(main)
|
|
associateWith(mainJdk7)
|
|
compileTaskProvider.configure {
|
|
kotlinOptions {
|
|
moduleName = "kotlin-stdlib-jdk8"
|
|
freeCompilerArgs = listOfNotNull(
|
|
"-Xallow-kotlin-package",
|
|
"-Xmultifile-parts-inherit",
|
|
"-Xno-new-java-annotation-targets",
|
|
diagnosticNamesArg,
|
|
)
|
|
}
|
|
}
|
|
}
|
|
project.sourceSets.create("java9") {
|
|
java.srcDir("jvm/java9")
|
|
}
|
|
configureJava9Compilation("kotlin.stdlib", listOf(
|
|
main.output.allOutputs,
|
|
mainJdk7.output.allOutputs,
|
|
mainJdk8.output.allOutputs,
|
|
), main.configurations.compileDependencyConfiguration)
|
|
val test by getting {
|
|
associateWith(mainJdk7)
|
|
associateWith(mainJdk8)
|
|
compileTaskProvider.configure {
|
|
kotlinOptions {
|
|
freeCompilerArgs += listOf(
|
|
"-Xallow-kotlin-package", // TODO: maybe rename test packages
|
|
"-Xexpect-actual-classes",
|
|
)
|
|
if (kotlinBuildProperties.useFir) {
|
|
freeCompilerArgs += "-Xuse-k2"
|
|
}
|
|
// This is needed for JavaTypeTest; typeOf for non-reified type parameters doesn't work otherwise, for implementation reasons.
|
|
freeCompilerArgs -= "-Xno-optimized-callable-references"
|
|
}
|
|
}
|
|
}
|
|
val longRunningTest by creating {
|
|
associateWith(main)
|
|
associateWith(mainJdk7)
|
|
associateWith(mainJdk8)
|
|
}
|
|
}
|
|
}
|
|
jsIrTarget = js(IR) {
|
|
if (!kotlinBuildProperties.isTeamcityBuild) {
|
|
browser {}
|
|
}
|
|
nodejs {
|
|
testTask {
|
|
useMocha {
|
|
timeout = "10s"
|
|
}
|
|
}
|
|
}
|
|
compilations {
|
|
all {
|
|
kotlinOptions {
|
|
freeCompilerArgs += "-Xallow-kotlin-package"
|
|
}
|
|
}
|
|
val main by getting
|
|
main.apply {
|
|
kotlinOptions {
|
|
freeCompilerArgs += listOf(
|
|
"-Xir-module-name=kotlin",
|
|
"-Xexpect-actual-classes",
|
|
)
|
|
|
|
if (!kotlinBuildProperties.disableWerror) {
|
|
allWarningsAsErrors = true
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
D8RootPlugin.apply(rootProject).version = v8Version
|
|
|
|
fun KotlinWasmTargetDsl.commonWasmTargetConfiguration() {
|
|
(this as KotlinTargetWithNodeJsDsl).nodejs()
|
|
compilations {
|
|
all {
|
|
kotlinOptions.freeCompilerArgs += listOf("-Xallow-kotlin-package", "-Xexpect-actual-classes")
|
|
}
|
|
val main by getting
|
|
main.apply {
|
|
kotlinOptions.freeCompilerArgs += "-Xir-module-name=kotlin"
|
|
kotlinOptions.allWarningsAsErrors = true
|
|
}
|
|
}
|
|
}
|
|
@OptIn(ExperimentalWasmDsl::class)
|
|
wasmJs {
|
|
commonWasmTargetConfiguration()
|
|
}
|
|
@OptIn(ExperimentalWasmDsl::class)
|
|
wasmWasi {
|
|
commonWasmTargetConfiguration()
|
|
}
|
|
|
|
sourceSets {
|
|
all {
|
|
kotlin.setSrcDirs(emptyList<File>())
|
|
}
|
|
commonMain {
|
|
val prepareCommonSources by tasks.registering {
|
|
dependsOn(":prepare:build.version:writeStdlibVersion")
|
|
}
|
|
kotlin {
|
|
srcDir("common/src")
|
|
srcDir(files("src").builtBy(prepareCommonSources))
|
|
srcDir("unsigned/src")
|
|
if (!kotlinBuildProperties.isInIdeaSync) {
|
|
srcDir("$builtinsDir/src/kotlin/internal")
|
|
}
|
|
if (kotlinBuildProperties.isInIdeaSync) {
|
|
// required for correct resolution of builtin classes in common code in K2 IDE
|
|
srcDir("$builtinsDir/src")
|
|
}
|
|
}
|
|
}
|
|
commonTest {
|
|
dependencies {
|
|
// TODO: use project dependency when kotlin-test is migrated
|
|
compileOnly("org.jetbrains.kotlin:kotlin-test-common:$bootstrapKotlinVersion")
|
|
compileOnly("org.jetbrains.kotlin:kotlin-test-annotations-common:$bootstrapKotlinVersion")
|
|
// compileOnly(project(":kotlin-test:kotlin-test-common"))
|
|
// compileOnly(project(":kotlin-test:kotlin-test-annotations-common"))
|
|
}
|
|
kotlin {
|
|
srcDir("common/test")
|
|
srcDir("test")
|
|
}
|
|
}
|
|
val jvmCompileOnlyDeclarations by getting {
|
|
kotlin.srcDir("jvm/compileOnly")
|
|
}
|
|
val jvmMain by getting {
|
|
project.configurations.getByName("jvmMainCompileOnly").extendsFrom(configurationBuiltins)
|
|
dependencies {
|
|
api("org.jetbrains:annotations:13.0")
|
|
}
|
|
val jvmSrcDirs = listOfNotNull(
|
|
"jvm/src",
|
|
"jvm/runtime",
|
|
"$builtinsDir/src".takeUnless { kotlinBuildProperties.isInIdeaSync }
|
|
)
|
|
project.sourceSets["main"].java.srcDirs(*jvmSrcDirs.toTypedArray())
|
|
kotlin.setSrcDirs(jvmSrcDirs)
|
|
}
|
|
|
|
val jvmMainJdk7 by getting {
|
|
kotlin.srcDir("jdk7/src")
|
|
}
|
|
val jvmMainJdk8 by getting {
|
|
kotlin.srcDir("jdk8/src")
|
|
}
|
|
|
|
val jvmTest by getting {
|
|
languageSettings {
|
|
optIn("kotlin.io.path.ExperimentalPathApi")
|
|
}
|
|
dependencies {
|
|
api(project(":kotlin-test:kotlin-test-junit"))
|
|
}
|
|
kotlin.srcDir("jvm/test")
|
|
kotlin.srcDir("jdk7/test")
|
|
kotlin.srcDir("jdk8/test")
|
|
}
|
|
|
|
val jvmLongRunningTest by getting {
|
|
dependencies {
|
|
api(project(":kotlin-test:kotlin-test-junit"))
|
|
}
|
|
kotlin.srcDir("jvm/testLongRunning")
|
|
}
|
|
|
|
val jsMain by getting {
|
|
val prepareJsIrMainSources by tasks.registering(Sync::class)
|
|
kotlin {
|
|
srcDir(prepareJsIrMainSources)
|
|
srcDir("$jsDir/builtins")
|
|
srcDir("$jsDir/runtime")
|
|
srcDir("$jsDir/src").apply {
|
|
exclude("kotlin/browser")
|
|
exclude("kotlin/dom")
|
|
exclude("kotlinx")
|
|
exclude("org.w3c")
|
|
}
|
|
}
|
|
|
|
prepareJsIrMainSources.configure {
|
|
val unimplementedNativeBuiltIns =
|
|
(file("$builtinsDir/native/kotlin/").list()!!.toSortedSet() - file("$jsDir/builtins/").list()!!)
|
|
.map { "core/builtins/native/kotlin/$it" }
|
|
|
|
// TODO: try to reuse absolute paths defined in the beginning
|
|
val sources = listOf(
|
|
"core/builtins/src/kotlin/",
|
|
) + unimplementedNativeBuiltIns
|
|
|
|
val excluded = listOf(
|
|
// JS-specific optimized version of emptyArray() already defined
|
|
"core/builtins/src/kotlin/ArrayIntrinsics.kt",
|
|
// included in common
|
|
"core/builtins/src/kotlin/internal/**",
|
|
)
|
|
|
|
sources.forEach { path ->
|
|
from("$rootDir/$path") {
|
|
into(path.dropLastWhile { it != '/' })
|
|
excluded.filter { it.startsWith(path) }.forEach {
|
|
exclude(it.substring(path.length))
|
|
}
|
|
}
|
|
}
|
|
|
|
into(jsIrMainSources)
|
|
|
|
// Required to compile native builtins with the rest of runtime
|
|
val builtInsHeader = """@file:Suppress(
|
|
"NON_ABSTRACT_FUNCTION_WITH_NO_BODY",
|
|
"MUST_BE_INITIALIZED_OR_BE_ABSTRACT",
|
|
"EXTERNAL_TYPE_EXTENDS_NON_EXTERNAL_TYPE",
|
|
"PRIMARY_CONSTRUCTOR_DELEGATION_CALL_EXPECTED",
|
|
"WRONG_MODIFIER_TARGET",
|
|
"UNUSED_PARAMETER"
|
|
)
|
|
"""
|
|
doLast {
|
|
unimplementedNativeBuiltIns.forEach { path ->
|
|
val file = File("$destinationDir/$path")
|
|
val sourceCode = builtInsHeader + file.readText()
|
|
file.writeText(sourceCode)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
val jsTest by getting {
|
|
dependencies {
|
|
api(project(":kotlin-test:kotlin-test-js-ir"))
|
|
}
|
|
kotlin.srcDir("${jsDir}/test")
|
|
}
|
|
|
|
val nativeWasmMain by creating {
|
|
dependsOn(commonMain.get())
|
|
kotlin.srcDir("native-wasm/src")
|
|
}
|
|
|
|
val nativeWasmTest by creating {
|
|
dependsOn(commonTest.get())
|
|
kotlin.srcDir("native-wasm/test")
|
|
}
|
|
|
|
val wasmCommonMain by creating {
|
|
dependsOn(nativeWasmMain)
|
|
val prepareWasmBuiltinSources by tasks.registering(Sync::class)
|
|
kotlin {
|
|
srcDir(prepareWasmBuiltinSources)
|
|
srcDir("wasm/builtins")
|
|
srcDir("wasm/internal")
|
|
srcDir("wasm/runtime")
|
|
srcDir("wasm/src")
|
|
srcDir("wasm/stubs")
|
|
}
|
|
prepareWasmBuiltinSources.configure {
|
|
val unimplementedNativeBuiltIns =
|
|
(file("$rootDir/core/builtins/native/kotlin/").list().toSortedSet() - file("wasm/builtins/kotlin/").list())
|
|
.map { "core/builtins/native/kotlin/$it" }
|
|
|
|
val sources = listOf(
|
|
"core/builtins/src/kotlin/"
|
|
) + unimplementedNativeBuiltIns
|
|
|
|
|
|
|
|
val excluded = listOf(
|
|
// included in commonMain
|
|
"internal/InternalAnnotations.kt",
|
|
// JS-specific optimized version of emptyArray() already defined
|
|
"ArrayIntrinsics.kt",
|
|
// Included with K/N collections
|
|
"Collections.kt", "Iterator.kt", "Iterators.kt"
|
|
)
|
|
|
|
sources.forEach { path ->
|
|
from("$rootDir/$path") {
|
|
into(path.dropLastWhile { it != '/' })
|
|
excluded.forEach {
|
|
exclude(it)
|
|
}
|
|
}
|
|
}
|
|
|
|
into("$buildDir/src/wasm-builtin-sources")
|
|
}
|
|
|
|
}
|
|
val wasmCommonTest by creating {
|
|
dependsOn(nativeWasmTest)
|
|
kotlin {
|
|
srcDir("wasm/test")
|
|
}
|
|
}
|
|
|
|
val wasmJsMain by getting {
|
|
dependsOn(wasmCommonMain)
|
|
kotlin {
|
|
srcDir("wasm/js/builtins")
|
|
srcDir("wasm/js/internal")
|
|
srcDir("wasm/js/src")
|
|
}
|
|
}
|
|
val wasmJsTest by getting {
|
|
dependsOn(wasmCommonTest)
|
|
dependencies {
|
|
api(project(":kotlin-test:kotlin-test-wasm-js"))
|
|
}
|
|
kotlin {
|
|
srcDir("wasm/js/test")
|
|
}
|
|
}
|
|
val wasmWasiMain by getting {
|
|
dependsOn(wasmCommonMain)
|
|
kotlin {
|
|
srcDir("wasm/wasi/builtins")
|
|
srcDir("wasm/wasi/src")
|
|
}
|
|
languageSettings {
|
|
optIn("kotlin.wasm.unsafe.UnsafeWasmMemoryApi")
|
|
}
|
|
}
|
|
val wasmWasiTest by getting {
|
|
dependsOn(wasmCommonTest)
|
|
dependencies {
|
|
api(project(":kotlin-test:kotlin-test-wasm-wasi"))
|
|
}
|
|
kotlin {
|
|
srcDir("wasm/wasi/test")
|
|
}
|
|
}
|
|
|
|
all sourceSet@ {
|
|
languageSettings {
|
|
// TODO: progressiveMode = use build property 'test.progressive.mode'
|
|
if (this@sourceSet == jvmCompileOnlyDeclarations) {
|
|
return@languageSettings
|
|
}
|
|
commonOptIns.forEach { optIn(it) }
|
|
if (this@sourceSet.name.endsWith("Test")) {
|
|
commonTestOptIns.forEach { optIn(it) }
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
dependencies {
|
|
val jvmMainApi by configurations.getting
|
|
val commonMainMetadataElementsWithClassifier by configurations.creating
|
|
val metadataApiElements by configurations.getting
|
|
val nativeApiElements by configurations.creating
|
|
constraints {
|
|
// there is no dependency anymore from kotlin-stdlib to kotlin-stdlib-common,
|
|
// but use this constraint to align it if another library brings it transitively
|
|
jvmMainApi(project(":kotlin-stdlib-common"))
|
|
commonMainMetadataElementsWithClassifier(project(":kotlin-stdlib-common"))
|
|
metadataApiElements(project(":kotlin-stdlib-common"))
|
|
nativeApiElements(project(":kotlin-stdlib-common"))
|
|
// to avoid split package and duplicate classes on classpath after moving them from these artifacts in 1.8.0
|
|
jvmMainApi("org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.8.0")
|
|
jvmMainApi("org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.8.0")
|
|
}
|
|
}
|
|
|
|
tasks {
|
|
val metadataJar by existing(Jar::class) {
|
|
archiveAppendix.set("metadata")
|
|
}
|
|
val sourcesJar by existing(Jar::class) {
|
|
archiveAppendix.set("metadata")
|
|
}
|
|
val jvmJar by existing(Jar::class) {
|
|
dependsOn(configurationBuiltins)
|
|
duplicatesStrategy = DuplicatesStrategy.FAIL
|
|
archiveAppendix.set(null as String?)
|
|
manifestAttributes(manifest, "Main", multiRelease = true)
|
|
manifest.attributes(mapOf("Implementation-Title" to "kotlin-stdlib"))
|
|
from { zipTree(configurationBuiltins.singleFile) }
|
|
from(kotlin.jvm().compilations["mainJdk7"].output.allOutputs)
|
|
from(kotlin.jvm().compilations["mainJdk8"].output.allOutputs)
|
|
from(project.sourceSets["java9"].output)
|
|
}
|
|
|
|
val jvmSourcesJar by existing(Jar::class) {
|
|
duplicatesStrategy = DuplicatesStrategy.FAIL
|
|
archiveAppendix.set(null as String?)
|
|
into("jvmMain") {
|
|
from("${rootDir}/core/builtins/native")
|
|
from(kotlin.sourceSets["jvmMainJdk7"].kotlin) {
|
|
into("jdk7")
|
|
}
|
|
from(kotlin.sourceSets["jvmMainJdk8"].kotlin) {
|
|
into("jdk8")
|
|
}
|
|
}
|
|
}
|
|
|
|
dexMethodCount {
|
|
from(jvmJar)
|
|
ownPackages.set(listOf("kotlin"))
|
|
}
|
|
|
|
val jsJar by existing(Jar::class) {
|
|
manifestAttributes(manifest, "Main")
|
|
manifest.attributes(mapOf("Implementation-Title" to "kotlin-stdlib-js"))
|
|
}
|
|
|
|
val jsJarForTests by registering(Copy::class) {
|
|
from(jsJar)
|
|
rename { _ -> "full-runtime.klib" }
|
|
// some tests expect stdlib-js klib in this location
|
|
into(rootProject.buildDir.resolve("js-ir-runtime"))
|
|
}
|
|
|
|
val jsRearrangedSourcesJar by registering(Jar::class) {
|
|
archiveClassifier.set("js-sources")
|
|
archiveVersion.set("")
|
|
destinationDirectory.set(file("$buildDir/lib"))
|
|
|
|
includeEmptyDirs = false
|
|
duplicatesStrategy = DuplicatesStrategy.FAIL
|
|
|
|
into("commonMain") {
|
|
from(kotlin.sourceSets.commonMain.get().kotlin)
|
|
}
|
|
into("jsMain") {
|
|
from(kotlin.sourceSets["jsMain"].kotlin) {
|
|
// just to depend on source-generating tasks
|
|
exclude("**")
|
|
}
|
|
from("${rootDir}/core/builtins/native/kotlin") {
|
|
into("kotlin")
|
|
include("Comparable.kt")
|
|
include("Enum.kt")
|
|
}
|
|
from("$jsIrMainSources/core/builtins/native") {
|
|
exclude("kotlin/Comparable.kt")
|
|
}
|
|
from("$jsIrMainSources/core/builtins/src")
|
|
from("$jsIrMainSources/libraries/stdlib/js/src")
|
|
from("$jsDir/builtins") {
|
|
into("kotlin")
|
|
exclude("Enum.kt")
|
|
}
|
|
from("$jsDir/runtime") {
|
|
into("runtime")
|
|
}
|
|
from("$jsDir/src") {
|
|
include("**/*.kt")
|
|
}
|
|
}
|
|
}
|
|
|
|
val jsSourcesJar by existing(Jar::class) {
|
|
val jsSourcesJarFile = jsRearrangedSourcesJar.get().archiveFile
|
|
inputs.file(jsSourcesJarFile)
|
|
doLast {
|
|
jsSourcesJarFile.get().asFile.toPath().copyTo(archiveFile.get().asFile.toPath(), overwrite = true)
|
|
}
|
|
}
|
|
|
|
val wasmJsJar by existing(Jar::class) {
|
|
manifestAttributes(manifest, "Main")
|
|
}
|
|
val wasmWasiJar by existing(Jar::class) {
|
|
manifestAttributes(manifest, "Main")
|
|
}
|
|
|
|
artifacts {
|
|
val distJsJar = configurations.create("distJsJar")
|
|
val distJsSourcesJar = configurations.create("distJsSourcesJar")
|
|
val distJsKlib = configurations.create("distJsKlib")
|
|
|
|
add(distJsSourcesJar.name, jsSourcesJar)
|
|
add(distJsKlib.name, jsJar)
|
|
}
|
|
|
|
|
|
val jvmTest by existing(Test::class)
|
|
|
|
listOf(JdkMajorVersion.JDK_9_0, JdkMajorVersion.JDK_10_0, JdkMajorVersion.JDK_11_0).forEach { jvmVersion ->
|
|
val jvmVersionTest = register("jvm${jvmVersion.majorVersion}Test", Test::class) {
|
|
group = "verification"
|
|
javaLauncher.set(getToolchainLauncherFor(jvmVersion))
|
|
// additional test tasks are not configured automatically same as the main test task
|
|
// after KMP plugin stopped applying java plugin
|
|
classpath = jvmTest.get().classpath
|
|
testClassesDirs = jvmTest.get().testClassesDirs
|
|
|
|
}
|
|
check.configure { dependsOn(jvmVersionTest) }
|
|
}
|
|
|
|
val jvmLongRunningTest by registering(Test::class) {
|
|
val compilation = kotlin.jvm().compilations["longRunningTest"]
|
|
classpath = compilation.compileDependencyFiles + compilation.runtimeDependencyFiles + compilation.output.allOutputs
|
|
testClassesDirs = compilation.output.classesDirs
|
|
}
|
|
|
|
if (project.hasProperty("kotlin.stdlib.test.long.running")) {
|
|
check.configure { dependsOn(jvmLongRunningTest) }
|
|
}
|
|
|
|
listOf("Js", "Wasi").forEach { wasmTarget ->
|
|
named("compileTestKotlinWasm$wasmTarget", AbstractKotlinCompile::class) {
|
|
// TODO: fix all warnings, enable -Werror
|
|
compilerOptions.suppressWarnings = true
|
|
// exclusions due to KT-51647
|
|
exclude("generated/minmax/*")
|
|
exclude("collections/MapTest.kt")
|
|
}
|
|
named("compileTestDevelopmentExecutableKotlinWasm$wasmTarget", KotlinJsIrLink::class) {
|
|
kotlinOptions.freeCompilerArgs += listOf("-Xwasm-enable-array-range-checks")
|
|
}
|
|
}
|
|
|
|
/*
|
|
We are using a custom 'kotlin-project-structure-metadata' to ensure 'nativeApiElements' lists 'commonMain' as source set
|
|
*/
|
|
val generateProjectStructureMetadata by existing {
|
|
val outputFile = file("build/kotlinProjectStructureMetadata/kotlin-project-structure-metadata.json")
|
|
val outputTestFile = file("kotlin-project-structure-metadata.beforePatch.json")
|
|
val patchedFile = file("kotlin-project-structure-metadata.json")
|
|
|
|
inputs.file(patchedFile)
|
|
inputs.file(outputTestFile)
|
|
|
|
doLast {
|
|
/*
|
|
Check that the generated 'outputFile' by default matches our expectations stored in the .beforePatch file
|
|
This will fail if the kotlin-project-structure-metadata.json file would change unnoticed (w/o updating our patched file)
|
|
*/
|
|
run {
|
|
val outputFileText = outputFile.readText().trim()
|
|
val expectedFileContent = outputTestFile.readText().trim()
|
|
if (outputFileText != expectedFileContent)
|
|
error(
|
|
"${outputFile.path} file content does not match expected content\n\n" +
|
|
"expected:\n\n$expectedFileContent\n\nactual:\n\n$outputFileText"
|
|
)
|
|
}
|
|
|
|
patchedFile.copyTo(outputFile, overwrite = true)
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
|
|
// region ==== Publishing ====
|
|
|
|
configureDefaultPublishing()
|
|
|
|
open class ComponentsFactoryAccess
|
|
@javax.inject.Inject
|
|
constructor(val factory: SoftwareComponentFactory)
|
|
|
|
val componentFactory = objects.newInstance<ComponentsFactoryAccess>().factory
|
|
|
|
val emptyJavadocJar by tasks.creating(org.gradle.api.tasks.bundling.Jar::class) {
|
|
archiveClassifier.set("javadoc")
|
|
}
|
|
|
|
publishing {
|
|
val artifactBaseName = base.archivesName.get()
|
|
configureMultiModuleMavenPublishing {
|
|
val rootModule = module("rootModule") {
|
|
mavenPublication {
|
|
artifactId = artifactBaseName
|
|
configureKotlinPomAttributes(project, "Kotlin Standard Library")
|
|
artifact(emptyJavadocJar)
|
|
}
|
|
|
|
// creates a variant from existing configuration or creates new one
|
|
variant("jvmApiElements")
|
|
variant("jvmRuntimeElements")
|
|
variant("jvmSourcesElements")
|
|
|
|
variant("metadataApiElements")
|
|
variant("commonMainMetadataElementsWithClassifier") {
|
|
name = "commonMainMetadataElements"
|
|
configuration {
|
|
isCanBeConsumed = false
|
|
}
|
|
attributes {
|
|
copyAttributes(from = project.configurations["commonMainMetadataElements"].attributes, to = this)
|
|
}
|
|
artifact(tasks["metadataJar"]) {
|
|
classifier = "common"
|
|
}
|
|
}
|
|
variant("metadataSourcesElementsFromJvm") {
|
|
name = "metadataSourcesElements"
|
|
configuration {
|
|
// to avoid clash in Gradle 8+ with metadataSourcesElements configuration with the same attributes
|
|
isCanBeConsumed = false
|
|
}
|
|
attributes {
|
|
copyAttributes(from = project.configurations["metadataSourcesElements"].attributes, to = this)
|
|
}
|
|
artifact(tasks["sourcesJar"]) {
|
|
classifier = "common-sources"
|
|
}
|
|
}
|
|
variant("nativeApiElements") {
|
|
attributes {
|
|
attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category.LIBRARY))
|
|
attribute(TargetJvmEnvironment.TARGET_JVM_ENVIRONMENT_ATTRIBUTE, objects.named("non-jvm"))
|
|
attribute(Usage.USAGE_ATTRIBUTE, objects.named(KotlinUsages.KOTLIN_API))
|
|
attribute(KotlinPlatformType.attribute, KotlinPlatformType.native)
|
|
}
|
|
}
|
|
}
|
|
|
|
// we cannot publish legacy common artifact with metadata in kotlin-stdlib-common
|
|
// because it will cause problems in explicitly configured stdlib dependencies in project
|
|
// val common = module("commonModule") {
|
|
// mavenPublication {
|
|
// artifactId = "$artifactBaseName-common"
|
|
// configureKotlinPomAttributes(project, "Kotlin Common Standard Library (for compatibility with legacy multiplatform)")
|
|
// artifact(tasks["sourcesJar"]) // publish sources.jar just for maven, without including it in Gradle metadata
|
|
// }
|
|
// variant("commonMainMetadataElements")
|
|
// }
|
|
val js = module("jsModule") {
|
|
mavenPublication {
|
|
artifactId = "$artifactBaseName-js"
|
|
configureKotlinPomAttributes(project, "Kotlin Standard Library for JS", packaging = "klib")
|
|
}
|
|
variant("jsApiElements")
|
|
variant("jsRuntimeElements")
|
|
variant("jsSourcesElements")
|
|
}
|
|
|
|
val wasmJs = module("wasmJsModule") {
|
|
mavenPublication {
|
|
artifactId = "$artifactBaseName-wasm-js"
|
|
configureKotlinPomAttributes(project, "Kotlin Standard Library for experimental WebAssembly JS platform", packaging = "klib")
|
|
}
|
|
variant("wasmJsApiElements")
|
|
variant("wasmJsRuntimeElements")
|
|
variant("wasmJsSourcesElements")
|
|
}
|
|
val wasmWasi = module("wasmWasiModule") {
|
|
mavenPublication {
|
|
artifactId = "$artifactBaseName-wasm-wasi"
|
|
configureKotlinPomAttributes(project, "Kotlin Standard Library for experimental WebAssembly WASI platform", packaging = "klib")
|
|
}
|
|
variant("wasmWasiApiElements")
|
|
variant("wasmWasiRuntimeElements")
|
|
variant("wasmWasiSourcesElements")
|
|
}
|
|
|
|
// Makes all variants from accompanying artifacts visible through `available-at`
|
|
rootModule.include(js, wasmJs, wasmWasi)
|
|
}
|
|
|
|
publications {
|
|
val rootModule by existing(MavenPublication::class)
|
|
val jsModule by existing(MavenPublication::class)
|
|
configureSbom("Main", "kotlin-stdlib", setOf("jvmRuntimeClasspath"), rootModule)
|
|
configureSbom("Js", "kotlin-stdlib-js", setOf("jsRuntimeClasspath"), jsModule)
|
|
|
|
val wasmJsModule by existing(MavenPublication::class)
|
|
val wasmWasiModule by existing(MavenPublication::class)
|
|
configureSbom("Wasm-Js", "kotlin-stdlib-wasm-js", setOf("wasmJsRuntimeClasspath"), wasmJsModule)
|
|
configureSbom("Wasm-Wasi", "kotlin-stdlib-wasm-wasi", setOf("wasmWasiRuntimeClasspath"), wasmWasiModule)
|
|
}
|
|
}
|
|
|
|
fun copyAttributes(from: AttributeContainer, to: AttributeContainer,) {
|
|
// capture type argument T
|
|
fun <T : Any> copyOneAttribute(from: AttributeContainer, to: AttributeContainer, key: Attribute<T>) {
|
|
val value = checkNotNull(from.getAttribute(key))
|
|
to.attribute(key, value)
|
|
}
|
|
for (key in from.keySet()) {
|
|
copyOneAttribute(from, to, key)
|
|
}
|
|
}
|
|
|
|
class MultiModuleMavenPublishingConfiguration() {
|
|
val modules = mutableMapOf<String, Module>()
|
|
|
|
class Module(val name: String) {
|
|
val variants = mutableMapOf<String, Variant>()
|
|
val includes = mutableSetOf<Module>()
|
|
|
|
class Variant(
|
|
val configurationName: String
|
|
) {
|
|
var name: String = configurationName
|
|
val attributesConfigurations = mutableListOf<AttributeContainer.() -> Unit>()
|
|
fun attributes(code: AttributeContainer.() -> Unit) {
|
|
attributesConfigurations += code
|
|
}
|
|
|
|
val artifactsWithConfigurations = mutableListOf<Pair<Any, ConfigurablePublishArtifact.() -> Unit>>()
|
|
fun artifact(file: Any, code: ConfigurablePublishArtifact.() -> Unit = {}) {
|
|
artifactsWithConfigurations += file to code
|
|
}
|
|
|
|
val configurationConfigurations = mutableListOf<Configuration.() -> Unit>()
|
|
fun configuration(code: Configuration.() -> Unit) {
|
|
configurationConfigurations += code
|
|
}
|
|
|
|
val variantDetailsConfigurations = mutableListOf<ConfigurationVariantDetails.() -> Unit>()
|
|
fun configureVariantDetails(code: ConfigurationVariantDetails.() -> Unit) {
|
|
variantDetailsConfigurations += code
|
|
}
|
|
}
|
|
|
|
val mavenPublicationConfigurations = mutableListOf<MavenPublication.() -> Unit>()
|
|
fun mavenPublication(code: MavenPublication.() -> Unit) {
|
|
mavenPublicationConfigurations += code
|
|
}
|
|
|
|
fun variant(fromConfigurationName: String, code: Variant.() -> Unit = {}): Variant {
|
|
val variant = variants.getOrPut(fromConfigurationName) { Variant(fromConfigurationName) }
|
|
variant.code()
|
|
return variant
|
|
}
|
|
|
|
fun include(vararg modules: Module) {
|
|
includes.addAll(modules)
|
|
}
|
|
}
|
|
|
|
fun module(name: String, code: Module.() -> Unit): Module {
|
|
val module = modules.getOrPut(name) { Module(name) }
|
|
module.code()
|
|
return module
|
|
}
|
|
}
|
|
|
|
fun configureMultiModuleMavenPublishing(code: MultiModuleMavenPublishingConfiguration.() -> Unit) {
|
|
val publishingConfiguration = MultiModuleMavenPublishingConfiguration()
|
|
publishingConfiguration.code()
|
|
|
|
val components = publishingConfiguration
|
|
.modules
|
|
.mapValues { (_, module) -> project.createModulePublication(module) }
|
|
|
|
val componentsWithExternals = publishingConfiguration
|
|
.modules
|
|
.filter { (_, module) -> module.includes.isNotEmpty() }
|
|
.mapValues { (moduleName, module) ->
|
|
val mainComponent = components[moduleName] ?: error("Component with name $moduleName wasn't created")
|
|
val externalComponents = module.includes
|
|
.map { components[it.name] ?: error("Component with name ${it.name} wasn't created") }
|
|
.toSet()
|
|
ComponentWithExternalVariants(mainComponent, externalComponents)
|
|
}
|
|
|
|
// override some components wih items from componentsWithExternals
|
|
val mergedComponents = components + componentsWithExternals
|
|
|
|
val publicationsContainer = publishing.publications
|
|
for ((componentName, component) in mergedComponents) {
|
|
publicationsContainer.create<MavenPublication>(componentName) {
|
|
from(component)
|
|
val module = publishingConfiguration.modules[componentName]!!
|
|
module.mavenPublicationConfigurations.forEach { configure -> configure() }
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
fun Project.createModulePublication(module: MultiModuleMavenPublishingConfiguration.Module): SoftwareComponent {
|
|
val component = componentFactory.adhoc(module.name)
|
|
module.variants.values.forEach { addVariant(component, it) }
|
|
|
|
val newNames = module.variants.map { it.key to it.value.name }.filter { it.first != it.second }.toMap()
|
|
return if (newNames.isNotEmpty()) {
|
|
ComponentWithRenamedVariants(newNames, component as SoftwareComponentInternal)
|
|
} else {
|
|
component
|
|
}
|
|
}
|
|
|
|
fun Project.addVariant(component: AdhocComponentWithVariants, variant: MultiModuleMavenPublishingConfiguration.Module.Variant) {
|
|
val configuration = configurations.getOrCreate(variant.configurationName)
|
|
configuration.apply {
|
|
isCanBeResolved = false
|
|
isCanBeConsumed = true
|
|
|
|
variant.attributesConfigurations.forEach { configure -> attributes.configure() }
|
|
}
|
|
|
|
for ((artifactNotation, configure) in variant.artifactsWithConfigurations) {
|
|
artifacts.add(configuration.name, artifactNotation) {
|
|
configure()
|
|
}
|
|
}
|
|
|
|
for (configure in variant.configurationConfigurations) {
|
|
configuration.apply(configure)
|
|
}
|
|
|
|
component.addVariantsFromConfiguration(configuration) {
|
|
variant.variantDetailsConfigurations.forEach { configure -> configure() }
|
|
}
|
|
}
|
|
|
|
private class RenamedVariant(val newName: String, context: UsageContext) : UsageContext by context {
|
|
override fun getName(): String = newName
|
|
}
|
|
|
|
private class ComponentWithRenamedVariants(
|
|
val newNames: Map<String, String>,
|
|
private val base: SoftwareComponentInternal
|
|
): SoftwareComponentInternal by base {
|
|
|
|
override fun getName(): String = base.name
|
|
override fun getUsages(): Set<UsageContext> {
|
|
return base.usages.map {
|
|
val newName = newNames[it.name]
|
|
if (newName != null) {
|
|
RenamedVariant(newName, it)
|
|
} else {
|
|
it
|
|
}
|
|
}.toSet()
|
|
}
|
|
}
|
|
|
|
private class ComponentWithExternalVariants(
|
|
private val mainComponent: SoftwareComponent,
|
|
private val externalComponents: Set<SoftwareComponent>
|
|
) : ComponentWithVariants, SoftwareComponentInternal {
|
|
override fun getName(): String = mainComponent.name
|
|
|
|
override fun getUsages(): Set<UsageContext> = (mainComponent as SoftwareComponentInternal).usages
|
|
|
|
override fun getVariants(): Set<SoftwareComponent> = externalComponents
|
|
}
|
|
|
|
// endregion
|
|
|
|
// for legacy intra-project dependencies
|
|
for (name in listOf("sources", "distSources")) {
|
|
val sourcesConfiguration = configurations.getOrCreate(name).apply {
|
|
isCanBeResolved = false
|
|
isCanBeConsumed = true
|
|
}
|
|
artifacts.add(sourcesConfiguration.name, tasks["jvmSourcesJar"])
|
|
}
|