| /* |
| * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license. |
| */ |
| |
| apply plugin: 'org.jetbrains.kotlin.multiplatform' |
| apply plugin: 'org.jetbrains.dokka' |
| apply from: rootProject.file("gradle/compile-jvm-multiplatform.gradle") |
| apply from: rootProject.file("gradle/compile-common.gradle") |
| |
| if (rootProject.ext.native_targets_enabled) { |
| apply from: rootProject.file("gradle/compile-native-multiplatform.gradle") |
| } |
| |
| apply from: rootProject.file("gradle/compile-js-multiplatform.gradle") |
| apply from: rootProject.file('gradle/publish-npm-js.gradle') |
| |
| apply from: rootProject.file('gradle/dokka.gradle.kts') |
| apply from: rootProject.file('gradle/publish.gradle') |
| /* ========================================================================== |
| Configure source sets structure for kotlinx-coroutines-core: |
| |
| TARGETS SOURCE SETS |
| ------- ---------------------------------------------- |
| |
| js -----------------------------------------------------+ |
| | |
| V |
| jvm -------------------------------> concurrent ---> common |
| ^ |
| ios \ | |
| macos | ---> nativeDarwin ---> native --+ |
| tvos | ^ |
| watchos / | |
| | |
| linux \ ---> nativeOther -------+ |
| mingw / |
| |
| ========================================================================== */ |
| |
| project.ext.sourceSetSuffixes = ["Main", "Test"] |
| |
| void defineSourceSet(newName, dependsOn, includedInPred) { |
| for (suffix in project.ext.sourceSetSuffixes) { |
| def newSS = kotlin.sourceSets.maybeCreate(newName + suffix) |
| for (dep in dependsOn) { |
| newSS.dependsOn(kotlin.sourceSets[dep + suffix]) |
| } |
| for (curSS in kotlin.sourceSets) { |
| def curName = curSS.name |
| if (curName.endsWith(suffix)) { |
| def prefix = curName.substring(0, curName.length() - suffix.length()) |
| if (includedInPred(prefix)) curSS.dependsOn(newSS) |
| } |
| } |
| } |
| } |
| |
| static boolean isNativeDarwin(String name) { return ["ios", "macos", "tvos", "watchos"].any { name.startsWith(it) } } |
| static boolean isNativeOther(String name) { return ["linux", "mingw"].any { name.startsWith(it) } } |
| |
| defineSourceSet("concurrent", ["common"]) { it in ["jvm", "native"] } |
| |
| if (rootProject.ext.native_targets_enabled) { |
| defineSourceSet("nativeDarwin", ["native"]) { isNativeDarwin(it) } |
| defineSourceSet("nativeOther", ["native"]) { isNativeOther(it) } |
| } |
| |
| /* ========================================================================== */ |
| |
| /* |
| * All platform plugins and configuration magic happens here instead of build.gradle |
| * because JMV-only projects depend on core, thus core should always be initialized before configuration. |
| */ |
| kotlin { |
| sourceSets.forEach { |
| SourceSetsKt.configureMultiplatform(it) |
| } |
| |
| /* |
| * Configure four test runs: |
| * 1) Old memory model, Main thread |
| * 2) New memory model, Main thread |
| * 3) Old memory model, BG thread |
| * 4) New memory model, BG thread (required for Dispatchers.Main tests on Darwin) |
| * |
| * All new MM targets are build with optimize = true to have stress tests properly run. |
| */ |
| targets.withType(org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTargetWithTests.class).configureEach { |
| binaries { |
| // Test for memory leaks using a special entry point that does not exit but returns from main |
| binaries.getTest("DEBUG").freeCompilerArgs += ["-e", "kotlinx.coroutines.mainNoExit"] |
| } |
| |
| binaries.test("newMM", [DEBUG]) { |
| def thisTest = it |
| freeCompilerArgs += ["-e", "kotlinx.coroutines.mainNoExit"] |
| optimized = true |
| binaryOptions["memoryModel"] = "experimental" |
| testRuns.create("newMM") { |
| setExecutionSourceFrom(thisTest) |
| // A hack to get different suffixes in the aggregated report. |
| executionTask.configure { targetName = "$targetName new MM" } |
| } |
| } |
| |
| binaries.test("worker", [DEBUG]) { |
| def thisTest = it |
| freeCompilerArgs += ["-e", "kotlinx.coroutines.mainBackground"] |
| testRuns.create("worker") { |
| setExecutionSourceFrom(thisTest) |
| executionTask.configure { targetName = "$targetName worker" } |
| } |
| } |
| |
| binaries.test("workerWithNewMM", [DEBUG]) { |
| def thisTest = it |
| optimized = true |
| freeCompilerArgs += ["-e", "kotlinx.coroutines.mainBackground"] |
| binaryOptions["memoryModel"] = "experimental" |
| testRuns.create("workerWithNewMM") { |
| setExecutionSourceFrom(thisTest) |
| executionTask.configure { targetName = "$targetName worker with new MM" } |
| } |
| } |
| } |
| |
| jvm { |
| // For animal sniffer |
| withJava() |
| } |
| } |
| |
| |
| configurations { |
| configureKotlinJvmPlatform(kotlinCompilerPluginClasspath) |
| } |
| |
| // Update module name for metadata artifact to avoid conflicts |
| // see https://github.com/Kotlin/kotlinx.coroutines/issues/1797 |
| compileKotlinMetadata { |
| kotlinOptions { |
| freeCompilerArgs += ["-module-name", "kotlinx-coroutines-core-common"] |
| } |
| } |
| |
| // :KLUDGE: Idea.active: This is needed to workaround resolve problems after importing this project to IDEA |
| def configureNativeSourceSetPreset(name, preset) { |
| def hostMainCompilation = project.kotlin.targetFromPreset(preset).compilations.main |
| // Look for platform libraries in "implementation" for default source set |
| def implementationConfiguration = configurations[hostMainCompilation.defaultSourceSet.implementationMetadataConfigurationName] |
| // Now find the libraries: Finds platform libs & stdlib, but platform declarations are still not resolved due to IDE bugs |
| def hostNativePlatformLibs = files( |
| provider { |
| implementationConfiguration.findAll { |
| it.path.endsWith(".klib") || it.absolutePath.contains("klib${File.separator}platform") || it.absolutePath.contains("stdlib") |
| } |
| } |
| ) |
| // Add all those dependencies |
| for (suffix in sourceSetSuffixes) { |
| configure(kotlin.sourceSets[name + suffix]) { |
| dependencies.add(implementationMetadataConfigurationName, hostNativePlatformLibs) |
| } |
| } |
| } |
| |
| // :KLUDGE: Idea.active: Configure platform libraries for native source sets when working in IDEA |
| if (Idea.active && rootProject.ext.native_targets_enabled) { |
| def manager = project.ext.hostManager |
| def linuxPreset = kotlin.presets.linuxX64 |
| def macosPreset = kotlin.presets.macosX64 |
| // linux should be always available (cross-compilation capable) -- use it as default |
| assert manager.isEnabled(linuxPreset.konanTarget) |
| // use macOS libs for nativeDarwin if available |
| def macosAvailable = manager.isEnabled(macosPreset.konanTarget) |
| // configure source sets |
| configureNativeSourceSetPreset("native", linuxPreset) |
| configureNativeSourceSetPreset("nativeOther", linuxPreset) |
| configureNativeSourceSetPreset("nativeDarwin", macosAvailable ? macosPreset : linuxPreset) |
| } |
| |
| kotlin.sourceSets { |
| jvmMain.dependencies { |
| compileOnly "com.google.android:annotations:4.1.1.4" |
| } |
| |
| jvmTest.dependencies { |
| api "org.jetbrains.kotlinx:lincheck:$lincheck_version" |
| api "org.jetbrains.kotlinx:kotlinx-knit-test:$knit_version" |
| implementation project(":android-unit-tests") |
| } |
| } |
| |
| jvmTest { |
| minHeapSize = '1g' |
| maxHeapSize = '1g' |
| enableAssertions = true |
| if (!Idea.active) { |
| // We should not set this security manager when `jvmTest` |
| // is invoked by IntelliJ IDEA since we need to pass |
| // system properties for Lincheck and stress tests. |
| // TODO Remove once IDEA is smart enough to select between `jvmTest`/`jvmStressTest`/`jvmLincheckTest` #KTIJ-599 |
| systemProperty 'java.security.manager', 'kotlinx.coroutines.TestSecurityManager' |
| } |
| // 'stress' is required to be able to run all subpackage tests like ":jvmTests --tests "*channels*" -Pstress=true" |
| if (!Idea.active && rootProject.properties['stress'] == null) { |
| exclude '**/*LincheckTest.*' |
| exclude '**/*StressTest.*' |
| } |
| if (Idea.active) { |
| // Configure the IDEA runner for Lincheck |
| configureJvmForLincheck(jvmTest) |
| } |
| } |
| |
| // Setup manifest for kotlinx-coroutines-core-jvm.jar |
| jvmJar { setupManifest(it) } |
| |
| /* |
| * Setup manifest for kotlinx-coroutines-core.jar |
| * This is convenient for users that pass -javaagent arg manually and also is a workaround #2619 and KTIJ-5659. |
| * This manifest contains reference to AgentPremain that belongs to |
| * kotlinx-coroutines-core-jvm, but our resolving machinery guarantees that |
| * any JVM project that depends on -core artifact also depends on -core-jvm one. |
| */ |
| metadataJar { setupManifest(it) } |
| |
| static def setupManifest(Jar jar) { |
| jar.manifest { |
| attributes "Premain-Class": "kotlinx.coroutines.debug.AgentPremain" |
| attributes "Can-Retransform-Classes": "true" |
| } |
| } |
| |
| task jvmStressTest(type: Test, dependsOn: compileTestKotlinJvm) { |
| classpath = files { jvmTest.classpath } |
| testClassesDirs = files { jvmTest.testClassesDirs } |
| minHeapSize = '1g' |
| maxHeapSize = '1g' |
| include '**/*StressTest.*' |
| enableAssertions = true |
| testLogging.showStandardStreams = true |
| systemProperty 'kotlinx.coroutines.scheduler.keep.alive.sec', '100000' // any unpark problem hangs test |
| systemProperty 'kotlinx.coroutines.semaphore.segmentSize', '2' |
| systemProperty 'kotlinx.coroutines.semaphore.maxSpinCycles', '10' |
| } |
| |
| task jvmLincheckTest(type: Test, dependsOn: compileTestKotlinJvm) { |
| classpath = files { jvmTest.classpath } |
| testClassesDirs = files { jvmTest.testClassesDirs } |
| include '**/*LincheckTest.*' |
| enableAssertions = true |
| testLogging.showStandardStreams = true |
| configureJvmForLincheck(jvmLincheckTest) |
| } |
| |
| static void configureJvmForLincheck(task) { |
| task.minHeapSize = '1g' |
| task.maxHeapSize = '4g' // we may need more space for building an interleaving tree in the model checking mode |
| task.jvmArgs = ['--add-opens', 'java.base/jdk.internal.misc=ALL-UNNAMED', // required for transformation |
| '--add-exports', 'java.base/jdk.internal.util=ALL-UNNAMED'] // in the model checking mode |
| task.systemProperty 'kotlinx.coroutines.semaphore.segmentSize', '2' |
| task.systemProperty 'kotlinx.coroutines.semaphore.maxSpinCycles', '1' // better for the model checking mode |
| } |
| |
| // Always check additional test sets |
| task moreTest(dependsOn: [jvmStressTest, jvmLincheckTest]) |
| check.dependsOn moreTest |
| |
| tasks.jvmLincheckTest { |
| kover { |
| enabled = false // Always disabled, lincheck doesn't really support coverage |
| } |
| } |
| |
| def commonKoverExcludes = |
| ["kotlinx.coroutines.debug.*", // Tested by debug module |
| "kotlinx.coroutines.channels.ChannelsKt__DeprecatedKt.*", // Deprecated |
| "kotlinx.coroutines.scheduling.LimitingDispatcher", // Deprecated |
| "kotlinx.coroutines.scheduling.ExperimentalCoroutineDispatcher" // Deprecated |
| ] |
| |
| tasks.koverHtmlReport { |
| excludes = commonKoverExcludes |
| } |
| |
| tasks.koverVerify { |
| excludes = commonKoverExcludes |
| } |
| |
| task testsJar(type: Jar, dependsOn: jvmTestClasses) { |
| classifier = 'tests' |
| from compileTestKotlinJvm.destinationDir |
| } |
| |
| artifacts { |
| archives testsJar |
| } |