Skip to content

Commit c1b3d70

Browse files
committed
Refactor mpp/native build, introduce "concurrent" source set, test launcher
* "concurrent" source set is shared between "jvm" and "native" * "native" source set is subdivided into "nativeDarwin" (Apple) and "nativeOther" (Linux, etc) * Native tests are launched in two variants: - A default "test" task runs tests with memory leak checker from "mainNoExit" entry point. - A special "backgroundTest" task runs tests in a background worker from "mainBackground" entry point.
1 parent 0bf172b commit c1b3d70

File tree

11 files changed

+198
-65
lines changed

11 files changed

+198
-65
lines changed

gradle.properties

+5-3
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,12 @@ kotlin.js.compiler=both
3636
gradle_node_version=1.2.0
3737
node_version=8.9.3
3838
npm_version=5.7.1
39-
mocha_version=4.1.0
39+
mocha_version=6.2.2
4040
mocha_headless_chrome_version=1.8.2
41-
mocha_teamcity_reporter_version=2.2.2
42-
source_map_support_version=0.5.3
41+
mocha_teamcity_reporter_version=3.0.0
42+
source_map_support_version=0.5.16
43+
jsdom_version=15.2.1
44+
jsdom_global_version=3.0.2
4345

4446
# Settings
4547
kotlin.incremental.multiplatform=true

gradle/compile-native-multiplatform.gradle

+14-26
Original file line numberDiff line numberDiff line change
@@ -13,36 +13,24 @@ kotlin {
1313
}
1414

1515
targets {
16-
if (project.ext.ideaActive) {
17-
fromPreset(project.ext.ideaPreset, 'native')
18-
} else {
19-
addTarget(presets.linuxX64)
20-
addTarget(presets.iosArm64)
21-
addTarget(presets.iosArm32)
22-
addTarget(presets.iosX64)
23-
addTarget(presets.macosX64)
24-
addTarget(presets.mingwX64)
25-
addTarget(presets.tvosArm64)
26-
addTarget(presets.tvosX64)
27-
addTarget(presets.watchosArm32)
28-
addTarget(presets.watchosArm64)
29-
addTarget(presets.watchosX86)
30-
}
16+
addTarget(presets.linuxX64)
17+
addTarget(presets.iosArm64)
18+
addTarget(presets.iosArm32)
19+
addTarget(presets.iosX64)
20+
addTarget(presets.macosX64)
21+
addTarget(presets.mingwX64)
22+
addTarget(presets.tvosArm64)
23+
addTarget(presets.tvosX64)
24+
addTarget(presets.watchosArm32)
25+
addTarget(presets.watchosArm64)
26+
addTarget(presets.watchosX86)
3127
}
3228

3329
sourceSets {
3430
nativeMain { dependsOn commonMain }
35-
// Empty source set is required in order to have native tests task
36-
nativeTest {}
31+
nativeTest { dependsOn commonTest }
3732

38-
if (!project.ext.ideaActive) {
39-
configure(nativeMainSets) {
40-
dependsOn nativeMain
41-
}
42-
43-
configure(nativeTestSets) {
44-
dependsOn nativeTest
45-
}
46-
}
33+
configure(nativeMainSets) { dependsOn nativeMain }
34+
configure(nativeTestSets) { dependsOn nativeTest }
4735
}
4836
}

gradle/targets.gradle

-28
This file was deleted.

gradle/test-mocha-js.gradle

+2-2
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@ task testMochaChrome(type: NodeTask, dependsOn: prepareMochaChrome) {
8686
task installDependenciesMochaJsdom(type: NpmTask, dependsOn: [npmInstall]) {
8787
args = ['install',
8888
"mocha@$mocha_version",
89-
'jsdom@15.2.1',
90-
'jsdom-global@3.0.2',
89+
"jsdom@$jsdom_version",
90+
"jsdom-global@$jsdom_global_version",
9191
"source-map-support@$source_map_support_version",
9292
'--no-save']
9393
if (project.hasProperty("teamcity")) args += ["mocha-teamcity-reporter@$mocha_teamcity_reporter_version"]

kotlinx-coroutines-core/build.gradle

+99-2
Original file line numberDiff line numberDiff line change
@@ -3,22 +3,72 @@
33
*/
44

55
apply plugin: 'kotlin-multiplatform'
6-
apply from: rootProject.file("gradle/targets.gradle")
76
apply from: rootProject.file("gradle/compile-jvm-multiplatform.gradle")
87
apply from: rootProject.file("gradle/compile-common.gradle")
98
apply from: rootProject.file("gradle/compile-js-multiplatform.gradle")
109
apply from: rootProject.file("gradle/compile-native-multiplatform.gradle")
1110
apply from: rootProject.file('gradle/publish-npm-js.gradle')
1211

12+
project.ext.ideaActive = System.getProperty('idea.active') == 'true'
13+
project.ext.sourceSetSuffixes = ["Main", "Test"]
14+
15+
void defineSourceSet(newName, dependsOn, includedInPred) {
16+
for (suffix in project.ext.sourceSetSuffixes) {
17+
def newSS = kotlin.sourceSets.maybeCreate(newName + suffix)
18+
for (dep in dependsOn) {
19+
newSS.dependsOn(kotlin.sourceSets[dep + suffix])
20+
}
21+
for (curSS in kotlin.sourceSets) {
22+
def curName = curSS.name
23+
if (curName.endsWith(suffix)) {
24+
def prefix = curName.substring(0, curName.length() - suffix.length())
25+
if (includedInPred(prefix)) curSS.dependsOn(newSS)
26+
}
27+
}
28+
}
29+
}
30+
31+
boolean isNativeDarwin(String name) { return ["ios", "macos", "tvos", "watchos"].any { name.startsWith(it) } }
32+
boolean isNativeOther(String name) { return ["linux", "mingw"].any { name.startsWith(it) } }
33+
34+
/* TARGETS:
35+
js -----------------------------------------------------+
36+
|
37+
V
38+
jvm -------------------------------> concurrent ---> common
39+
^
40+
ios \ |
41+
macos | ---> nativeDarwin ---> native --+
42+
tvos | ^
43+
watchos / |
44+
|
45+
linux \ ---> nativeOther -------+
46+
mingw /
47+
*/
48+
49+
defineSourceSet("concurrent", ["common"]) { it in ["jvm", "native"] }
50+
defineSourceSet("nativeDarwin", ["native"]) { isNativeDarwin(it) }
51+
defineSourceSet("nativeOther", ["native"]) { isNativeOther(it) }
52+
1353
/*
1454
* All platform plugins and configuration magic happens here instead of build.gradle
1555
* because JMV-only projects depend on core, thus core should always be initialized before configuration.
1656
*/
1757
kotlin {
58+
sourceSets {
59+
commonMain {
60+
dependencies {
61+
// todo: we should not need it
62+
// todo: it must be compileOnly or JVM is spoiled !!!
63+
implementation "org.jetbrains.kotlinx:atomicfu-common:$atomicfu_version"
64+
}
65+
}
66+
}
67+
1868
configure(sourceSets) {
1969
def srcDir = name.endsWith('Main') ? 'src' : 'test'
2070
def platform = name[0..-5]
21-
kotlin.srcDir "$platform/$srcDir"
71+
kotlin.srcDirs = ["$platform/$srcDir"]
2272
if (name == "jvmMain") {
2373
resources.srcDirs = ["$platform/resources"]
2474
} else if (name == "jvmTest") {
@@ -30,6 +80,23 @@ kotlin {
3080
}
3181
}
3282

83+
configure(targets) {
84+
// "Main" native targets -- one for each OS
85+
if (["macos", "linux", "mingw"].any { name.startsWith(it) }) {
86+
binaries {
87+
// Test for memory leaks using a special entry point that does not exit but returns from main
88+
binaries.getTest("DEBUG").freeCompilerArgs += ["-e", "kotlinx.coroutines.mainNoExit"]
89+
// Configure a separate test where code runs in background
90+
test("background", [org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType.DEBUG]) {
91+
freeCompilerArgs += ["-e", "kotlinx.coroutines.mainBackground"]
92+
}
93+
}
94+
testRuns {
95+
background { setExecutionSourceFrom(binaries.backgroundDebugTest) }
96+
}
97+
}
98+
}
99+
33100
configure(targets) {
34101
def targetName = it.name
35102
compilations.all { compilation ->
@@ -54,6 +121,36 @@ compileKotlinMetadata {
54121
}
55122
}
56123

124+
def configureNativeSourceSetPreset(name, preset) {
125+
def hostMainCompilation = project.kotlin.targetFromPreset(preset).compilations.main
126+
def compileConfiguration = configurations[hostMainCompilation.compileDependencyConfigurationName]
127+
def hostNativePlatformLibs = files(provider {
128+
compileConfiguration.findAll {
129+
it.path.endsWith(".klib") || it.absolutePath.contains("klib${File.separator}platform")
130+
}
131+
})
132+
for (suffix in project.ext.sourceSetSuffixes) {
133+
configure(kotlin.sourceSets[name + suffix]) {
134+
dependencies.add(implementationMetadataConfigurationName, hostNativePlatformLibs)
135+
}
136+
}
137+
}
138+
139+
// Configure platform libraries for native source sets when working in IDEA
140+
if (project.ext.ideaActive) {
141+
def manager = project.ext.hostManager
142+
def linuxPreset = kotlin.presets.linuxX64
143+
def macosPreset = kotlin.presets.macosX64
144+
// linux should be always available (cross-compilation capable) -- use it as default
145+
assert manager.isEnabled(linuxPreset.konanTarget)
146+
// use macOS libs for nativeDarwin if available
147+
def macosAvailable = manager.isEnabled(macosPreset.konanTarget)
148+
// configure source sets
149+
configureNativeSourceSetPreset("native", linuxPreset)
150+
configureNativeSourceSetPreset("nativeOther", linuxPreset)
151+
configureNativeSourceSetPreset("nativeDarwin", macosAvailable ? macosPreset : linuxPreset)
152+
}
153+
57154
kotlin.sourceSets {
58155
jvmMain.dependencies {
59156
compileOnly "com.google.android:annotations:4.1.1.4"
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/*
2+
* Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package kotlinx.coroutines
6+
7+
internal expect inline fun workerMain(block: () -> Unit)
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/*
2+
* Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package kotlinx.coroutines
6+
7+
import kotlinx.cinterop.*
8+
9+
internal actual inline fun workerMain(block: () -> Unit) {
10+
autoreleasepool {
11+
block()
12+
}
13+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/*
2+
* Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package kotlinx.coroutines
6+
7+
import platform.CoreFoundation.*
8+
import kotlin.native.concurrent.*
9+
import kotlin.native.internal.test.*
10+
import kotlin.system.*
11+
12+
// This is a separate entry point for tests in background
13+
fun mainBackground(args: Array<String>) {
14+
val worker = Worker.start(name = "main-background")
15+
worker.execute(TransferMode.SAFE, { args.freeze() }) {
16+
val result = testLauncherEntryPoint(it)
17+
exitProcess(result)
18+
}
19+
CFRunLoopRun()
20+
error("CFRunLoopRun should never return")
21+
}
22+
23+
// This is a separate entry point for tests with leak checker
24+
fun mainNoExit(args: Array<String>) {
25+
workerMain { // autoreleasepool to make sure interop objects are properly freed
26+
testLauncherEntryPoint(args)
27+
}
28+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
/*
2+
* Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package kotlinx.coroutines
6+
7+
internal actual inline fun workerMain(block: () -> Unit) = block()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
/*
2+
* Copyright 2016-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
3+
*/
4+
5+
package kotlinx.coroutines
6+
7+
import kotlin.native.concurrent.*
8+
import kotlin.native.internal.test.*
9+
import kotlin.system.*
10+
11+
// This is a separate entry point for tests in background
12+
fun mainBackground(args: Array<String>) {
13+
val worker = Worker.start(name = "main-background")
14+
worker.execute(TransferMode.SAFE, { args.freeze() }) {
15+
val result = testLauncherEntryPoint(it)
16+
exitProcess(result)
17+
}.result // block main thread
18+
}
19+
20+
// This is a separate entry point for tests with leak checker
21+
fun mainNoExit(args: Array<String>) {
22+
testLauncherEntryPoint(args)
23+
}

ui/kotlinx-coroutines-android/build.gradle.kts

-4
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,6 @@ import org.jetbrains.dokka.DokkaConfiguration.ExternalDocumentationLink
66
import org.jetbrains.dokka.gradle.DokkaTask
77
import java.net.URL
88

9-
repositories {
10-
google()
11-
}
12-
139
configurations {
1410
create("r8")
1511
}

0 commit comments

Comments
 (0)