blob: 9791b445bf5d2239fe1372f075b79d44a8231dbb [file] [log] [blame]
Vsevolod Tolstopyatove50a0fa2019-01-28 11:34:24 +03001/*
Vsevolod Tolstopyatov41a2e302021-02-04 07:16:48 -08002 * Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
Vsevolod Tolstopyatove50a0fa2019-01-28 11:34:24 +03003 */
4
Victor Turanskyfe2fedc2020-08-27 15:47:50 +03005apply plugin: 'org.jetbrains.kotlin.multiplatform'
Vsevolod Tolstopyatovbcbcd162021-07-06 14:29:27 +03006apply plugin: 'org.jetbrains.dokka'
Vsevolod Tolstopyatove50a0fa2019-01-28 11:34:24 +03007apply from: rootProject.file("gradle/compile-jvm-multiplatform.gradle")
8apply from: rootProject.file("gradle/compile-common.gradle")
Alexander Likhachev179f1422020-11-18 17:54:33 +03009
10if (rootProject.ext.native_targets_enabled) {
11 apply from: rootProject.file("gradle/compile-native-multiplatform.gradle")
12}
13
Vsevolod Tolstopyatove50a0fa2019-01-28 11:34:24 +030014apply from: rootProject.file("gradle/compile-js-multiplatform.gradle")
Vsevolod Tolstopyatove50a0fa2019-01-28 11:34:24 +030015apply from: rootProject.file('gradle/publish-npm-js.gradle')
16
Steve Elliottca095be2022-07-25 14:26:10 +000017apply from: rootProject.file('gradle/dokka.gradle.kts')
18apply from: rootProject.file('gradle/publish.gradle')
Roman Elizarov738f5a22020-10-12 19:03:46 +030019/* ==========================================================================
20 Configure source sets structure for kotlinx-coroutines-core:
21
22 TARGETS SOURCE SETS
23 ------- ----------------------------------------------
24
25 js -----------------------------------------------------+
26 |
27 V
28 jvm -------------------------------> concurrent ---> common
29 ^
30 ios \ |
31 macos | ---> nativeDarwin ---> native --+
32 tvos | ^
33 watchos / |
34 |
35 linux \ ---> nativeOther -------+
36 mingw /
37
38 ========================================================================== */
39
40project.ext.sourceSetSuffixes = ["Main", "Test"]
41
42void defineSourceSet(newName, dependsOn, includedInPred) {
43 for (suffix in project.ext.sourceSetSuffixes) {
44 def newSS = kotlin.sourceSets.maybeCreate(newName + suffix)
45 for (dep in dependsOn) {
46 newSS.dependsOn(kotlin.sourceSets[dep + suffix])
47 }
48 for (curSS in kotlin.sourceSets) {
49 def curName = curSS.name
50 if (curName.endsWith(suffix)) {
51 def prefix = curName.substring(0, curName.length() - suffix.length())
52 if (includedInPred(prefix)) curSS.dependsOn(newSS)
53 }
54 }
55 }
56}
57
58static boolean isNativeDarwin(String name) { return ["ios", "macos", "tvos", "watchos"].any { name.startsWith(it) } }
59static boolean isNativeOther(String name) { return ["linux", "mingw"].any { name.startsWith(it) } }
60
61defineSourceSet("concurrent", ["common"]) { it in ["jvm", "native"] }
Alexander Likhachev179f1422020-11-18 17:54:33 +030062
63if (rootProject.ext.native_targets_enabled) {
64 defineSourceSet("nativeDarwin", ["native"]) { isNativeDarwin(it) }
65 defineSourceSet("nativeOther", ["native"]) { isNativeOther(it) }
66}
Roman Elizarov738f5a22020-10-12 19:03:46 +030067
68/* ========================================================================== */
69
Vsevolod Tolstopyatove50a0fa2019-01-28 11:34:24 +030070/*
71 * All platform plugins and configuration magic happens here instead of build.gradle
72 * because JMV-only projects depend on core, thus core should always be initialized before configuration.
73 */
74kotlin {
Steve Elliottca095be2022-07-25 14:26:10 +000075 sourceSets.forEach {
76 SourceSetsKt.configureMultiplatform(it)
77 }
78
79 /*
80 * Configure four test runs:
81 * 1) Old memory model, Main thread
82 * 2) New memory model, Main thread
83 * 3) Old memory model, BG thread
84 * 4) New memory model, BG thread (required for Dispatchers.Main tests on Darwin)
85 *
86 * All new MM targets are build with optimize = true to have stress tests properly run.
87 */
88 targets.withType(org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTargetWithTests.class).configureEach {
89 binaries {
90 // Test for memory leaks using a special entry point that does not exit but returns from main
91 binaries.getTest("DEBUG").freeCompilerArgs += ["-e", "kotlinx.coroutines.mainNoExit"]
Vsevolod Tolstopyatov8273a752019-03-15 19:24:41 +030092 }
Steve Elliottca095be2022-07-25 14:26:10 +000093
94 binaries.test("newMM", [DEBUG]) {
95 def thisTest = it
96 freeCompilerArgs += ["-e", "kotlinx.coroutines.mainNoExit"]
97 optimized = true
98 binaryOptions["memoryModel"] = "experimental"
99 testRuns.create("newMM") {
100 setExecutionSourceFrom(thisTest)
101 // A hack to get different suffixes in the aggregated report.
102 executionTask.configure { targetName = "$targetName new MM" }
103 }
104 }
105
106 binaries.test("worker", [DEBUG]) {
107 def thisTest = it
108 freeCompilerArgs += ["-e", "kotlinx.coroutines.mainBackground"]
109 testRuns.create("worker") {
110 setExecutionSourceFrom(thisTest)
111 executionTask.configure { targetName = "$targetName worker" }
112 }
113 }
114
115 binaries.test("workerWithNewMM", [DEBUG]) {
116 def thisTest = it
117 optimized = true
118 freeCompilerArgs += ["-e", "kotlinx.coroutines.mainBackground"]
119 binaryOptions["memoryModel"] = "experimental"
120 testRuns.create("workerWithNewMM") {
121 setExecutionSourceFrom(thisTest)
122 executionTask.configure { targetName = "$targetName worker with new MM" }
123 }
Vsevolod Tolstopyatove50a0fa2019-01-28 11:34:24 +0300124 }
125 }
126
Steve Elliottca095be2022-07-25 14:26:10 +0000127 jvm {
128 // For animal sniffer
129 withJava()
Vsevolod Tolstopyatove50a0fa2019-01-28 11:34:24 +0300130 }
131}
132
Steve Elliottca095be2022-07-25 14:26:10 +0000133
Roman Elizarovd2f4b2b2019-09-02 17:22:39 +0300134configurations {
135 configureKotlinJvmPlatform(kotlinCompilerPluginClasspath)
136}
137
Roman Elizarov90a9faf2020-02-12 16:38:26 +0300138// Update module name for metadata artifact to avoid conflicts
139// see https://github.com/Kotlin/kotlinx.coroutines/issues/1797
140compileKotlinMetadata {
141 kotlinOptions {
142 freeCompilerArgs += ["-module-name", "kotlinx-coroutines-core-common"]
143 }
144}
145
Roman Elizarov738f5a22020-10-12 19:03:46 +0300146// :KLUDGE: Idea.active: This is needed to workaround resolve problems after importing this project to IDEA
147def configureNativeSourceSetPreset(name, preset) {
148 def hostMainCompilation = project.kotlin.targetFromPreset(preset).compilations.main
149 // Look for platform libraries in "implementation" for default source set
150 def implementationConfiguration = configurations[hostMainCompilation.defaultSourceSet.implementationMetadataConfigurationName]
151 // Now find the libraries: Finds platform libs & stdlib, but platform declarations are still not resolved due to IDE bugs
152 def hostNativePlatformLibs = files(
153 provider {
154 implementationConfiguration.findAll {
155 it.path.endsWith(".klib") || it.absolutePath.contains("klib${File.separator}platform") || it.absolutePath.contains("stdlib")
156 }
157 }
158 )
159 // Add all those dependencies
160 for (suffix in sourceSetSuffixes) {
161 configure(kotlin.sourceSets[name + suffix]) {
162 dependencies.add(implementationMetadataConfigurationName, hostNativePlatformLibs)
163 }
164 }
165}
166
167// :KLUDGE: Idea.active: Configure platform libraries for native source sets when working in IDEA
Alexander Likhachev179f1422020-11-18 17:54:33 +0300168if (Idea.active && rootProject.ext.native_targets_enabled) {
Roman Elizarov738f5a22020-10-12 19:03:46 +0300169 def manager = project.ext.hostManager
170 def linuxPreset = kotlin.presets.linuxX64
171 def macosPreset = kotlin.presets.macosX64
172 // linux should be always available (cross-compilation capable) -- use it as default
173 assert manager.isEnabled(linuxPreset.konanTarget)
174 // use macOS libs for nativeDarwin if available
175 def macosAvailable = manager.isEnabled(macosPreset.konanTarget)
176 // configure source sets
177 configureNativeSourceSetPreset("native", linuxPreset)
178 configureNativeSourceSetPreset("nativeOther", linuxPreset)
179 configureNativeSourceSetPreset("nativeDarwin", macosAvailable ? macosPreset : linuxPreset)
180}
181
Vsevolod Tolstopyatove50a0fa2019-01-28 11:34:24 +0300182kotlin.sourceSets {
Roman Elizarov0bf172b2020-06-02 10:20:57 +0300183 jvmMain.dependencies {
Vsevolod Tolstopyatov559023d2020-05-14 16:24:18 +0300184 compileOnly "com.google.android:annotations:4.1.1.4"
185 }
186
Vsevolod Tolstopyatove50a0fa2019-01-28 11:34:24 +0300187 jvmTest.dependencies {
Roman Elizarov738f5a22020-10-12 19:03:46 +0300188 api "org.jetbrains.kotlinx:lincheck:$lincheck_version"
Roman Elizarov660c2d72020-02-14 13:18:37 +0300189 api "org.jetbrains.kotlinx:kotlinx-knit-test:$knit_version"
Roman Elizarov738f5a22020-10-12 19:03:46 +0300190 implementation project(":android-unit-tests")
Vsevolod Tolstopyatove50a0fa2019-01-28 11:34:24 +0300191 }
192}
193
Vsevolod Tolstopyatove50a0fa2019-01-28 11:34:24 +0300194jvmTest {
195 minHeapSize = '1g'
196 maxHeapSize = '1g'
197 enableAssertions = true
Nikita Kovalb13018d2020-11-28 15:02:58 +0300198 if (!Idea.active) {
199 // We should not set this security manager when `jvmTest`
200 // is invoked by IntelliJ IDEA since we need to pass
201 // system properties for Lincheck and stress tests.
202 // TODO Remove once IDEA is smart enough to select between `jvmTest`/`jvmStressTest`/`jvmLincheckTest` #KTIJ-599
203 systemProperty 'java.security.manager', 'kotlinx.coroutines.TestSecurityManager'
204 }
Vsevolod Tolstopyatova64e4da2019-10-10 13:03:06 +0300205 // 'stress' is required to be able to run all subpackage tests like ":jvmTests --tests "*channels*" -Pstress=true"
Roman Elizarov738f5a22020-10-12 19:03:46 +0300206 if (!Idea.active && rootProject.properties['stress'] == null) {
Nikita Kovalb13018d2020-11-28 15:02:58 +0300207 exclude '**/*LincheckTest.*'
Vsevolod Tolstopyatova64e4da2019-10-10 13:03:06 +0300208 exclude '**/*StressTest.*'
209 }
Nikita Kovalb13018d2020-11-28 15:02:58 +0300210 if (Idea.active) {
211 // Configure the IDEA runner for Lincheck
212 configureJvmForLincheck(jvmTest)
213 }
Vsevolod Tolstopyatove50a0fa2019-01-28 11:34:24 +0300214}
215
Vsevolod Tolstopyatovb400b022021-04-21 17:42:23 +0300216// Setup manifest for kotlinx-coroutines-core-jvm.jar
217jvmJar { setupManifest(it) }
218
219/*
220 * Setup manifest for kotlinx-coroutines-core.jar
221 * This is convenient for users that pass -javaagent arg manually and also is a workaround #2619 and KTIJ-5659.
222 * This manifest contains reference to AgentPremain that belongs to
223 * kotlinx-coroutines-core-jvm, but our resolving machinery guarantees that
224 * any JVM project that depends on -core artifact also depends on -core-jvm one.
225 */
226metadataJar { setupManifest(it) }
227
228static def setupManifest(Jar jar) {
229 jar.manifest {
Vsevolod Tolstopyatov70a74872020-04-24 14:59:28 +0300230 attributes "Premain-Class": "kotlinx.coroutines.debug.AgentPremain"
231 attributes "Can-Retransform-Classes": "true"
232 }
233}
234
Roman Elizarov216828a2019-09-28 00:42:51 +0300235task jvmStressTest(type: Test, dependsOn: compileTestKotlinJvm) {
Vsevolod Tolstopyatove50a0fa2019-01-28 11:34:24 +0300236 classpath = files { jvmTest.classpath }
237 testClassesDirs = files { jvmTest.testClassesDirs }
Roman Elizarovfd27d552019-09-25 23:49:34 +0300238 minHeapSize = '1g'
239 maxHeapSize = '1g'
240 include '**/*StressTest.*'
Roman Elizarov0b16abf2019-09-03 11:07:11 +0300241 enableAssertions = true
242 testLogging.showStandardStreams = true
Roman Elizarovfd27d552019-09-25 23:49:34 +0300243 systemProperty 'kotlinx.coroutines.scheduler.keep.alive.sec', '100000' // any unpark problem hangs test
Nikita Kovalac42be92020-04-23 20:01:05 +0300244 systemProperty 'kotlinx.coroutines.semaphore.segmentSize', '2'
245 systemProperty 'kotlinx.coroutines.semaphore.maxSpinCycles', '10'
Vsevolod Tolstopyatove50a0fa2019-01-28 11:34:24 +0300246}
247
Nikita Kovalb13018d2020-11-28 15:02:58 +0300248task jvmLincheckTest(type: Test, dependsOn: compileTestKotlinJvm) {
249 classpath = files { jvmTest.classpath }
250 testClassesDirs = files { jvmTest.testClassesDirs }
251 include '**/*LincheckTest.*'
252 enableAssertions = true
253 testLogging.showStandardStreams = true
254 configureJvmForLincheck(jvmLincheckTest)
255}
256
257static void configureJvmForLincheck(task) {
258 task.minHeapSize = '1g'
Steve Elliottca095be2022-07-25 14:26:10 +0000259 task.maxHeapSize = '4g' // we may need more space for building an interleaving tree in the model checking mode
Nikita Kovalb13018d2020-11-28 15:02:58 +0300260 task.jvmArgs = ['--add-opens', 'java.base/jdk.internal.misc=ALL-UNNAMED', // required for transformation
Steve Elliottca095be2022-07-25 14:26:10 +0000261 '--add-exports', 'java.base/jdk.internal.util=ALL-UNNAMED'] // in the model checking mode
Nikita Kovalb13018d2020-11-28 15:02:58 +0300262 task.systemProperty 'kotlinx.coroutines.semaphore.segmentSize', '2'
263 task.systemProperty 'kotlinx.coroutines.semaphore.maxSpinCycles', '1' // better for the model checking mode
264}
265
Steve Elliottca095be2022-07-25 14:26:10 +0000266// Always check additional test sets
267task moreTest(dependsOn: [jvmStressTest, jvmLincheckTest])
268check.dependsOn moreTest
269
270tasks.jvmLincheckTest {
271 kover {
272 enabled = false // Always disabled, lincheck doesn't really support coverage
273 }
Vsevolod Tolstopyatove50a0fa2019-01-28 11:34:24 +0300274}
275
Steve Elliottca095be2022-07-25 14:26:10 +0000276def commonKoverExcludes =
277 ["kotlinx.coroutines.debug.*", // Tested by debug module
278 "kotlinx.coroutines.channels.ChannelsKt__DeprecatedKt.*", // Deprecated
279 "kotlinx.coroutines.scheduling.LimitingDispatcher", // Deprecated
280 "kotlinx.coroutines.scheduling.ExperimentalCoroutineDispatcher" // Deprecated
281 ]
Vsevolod Tolstopyatove50a0fa2019-01-28 11:34:24 +0300282
Steve Elliottca095be2022-07-25 14:26:10 +0000283tasks.koverHtmlReport {
284 excludes = commonKoverExcludes
285}
286
287tasks.koverVerify {
288 excludes = commonKoverExcludes
289}
Vsevolod Tolstopyatove50a0fa2019-01-28 11:34:24 +0300290
291task testsJar(type: Jar, dependsOn: jvmTestClasses) {
292 classifier = 'tests'
293 from compileTestKotlinJvm.destinationDir
294}
295
296artifacts {
297 archives testsJar
298}