blob: e4b12ff3adfc6a7ff6f9d321e7fa9c0a6024b2e8 [file] [log] [blame]
/*
* Copyright 2016-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license.
*/
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
import org.jetbrains.kotlin.konan.target.HostManager
import org.gradle.util.VersionNumber
import org.jetbrains.dokka.gradle.DokkaTaskPartial
import org.jetbrains.dokka.gradle.DokkaMultiModuleTask
apply plugin: 'jdk-convention'
apply from: rootProject.file("gradle/opt-in.gradle")
def coreModule = "kotlinx-coroutines-core"
// Not applicable for Kotlin plugin
def sourceless = ['kotlinx.coroutines', 'kotlinx-coroutines-bom', 'integration-testing']
def internal = ['kotlinx.coroutines', 'benchmarks', 'integration-testing']
// Not published
def unpublished = internal + ['example-frontend-js', 'android-unit-tests']
buildscript {
/*
* These property group is used to build kotlinx.coroutines against Kotlin compiler snapshot.
* How does it work:
* When build_snapshot_train is set to true, kotlin_version property is overridden with kotlin_snapshot_version,
* atomicfu_version is overwritten by TeamCity environment (AFU is built with snapshot and published to mavenLocal
* as previous step or the snapshot build).
* Additionally, mavenLocal and Sonatype snapshots are added to repository list and stress tests are disabled.
* DO NOT change the name of these properties without adapting kotlinx.train build chain.
*/
def prop = rootProject.properties['build_snapshot_train']
ext.build_snapshot_train = prop != null && prop != ""
if (build_snapshot_train) {
ext.kotlin_version = rootProject.properties['kotlin_snapshot_version']
if (kotlin_version == null) {
throw new IllegalArgumentException("'kotlin_snapshot_version' should be defined when building with snapshot compiler")
}
}
ext.native_targets_enabled = rootProject.properties['disable_native_targets'] == null
// Determine if any project dependency is using a snapshot version
ext.using_snapshot_version = build_snapshot_train
rootProject.properties.each { key, value ->
if (key.endsWith("_version") && value instanceof String && value.endsWith("-SNAPSHOT")) {
println("NOTE: USING SNAPSHOT VERSION: $key=$value")
ext.using_snapshot_version = true
}
}
if (using_snapshot_version) {
repositories {
mavenLocal()
}
}
repositories {
mavenCentral()
maven { url "https://plugins.gradle.org/m2/" }
maven { url "https://maven.pkg.jetbrains.space/kotlin/p/kotlin/dev" }
mavenLocal()
}
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.dokka:dokka-gradle-plugin:$dokka_version"
classpath "org.jetbrains.kotlinx:atomicfu-gradle-plugin:$atomicfu_version"
classpath "org.jetbrains.kotlinx:kotlinx-knit:$knit_version"
classpath "com.moowork.gradle:gradle-node-plugin:$gradle_node_version"
classpath "org.jetbrains.kotlinx:binary-compatibility-validator:$binary_compatibility_validator_version"
// JMH plugins
classpath "com.github.jengelman.gradle.plugins:shadow:5.1.0"
}
CacheRedirector.configureBuildScript(buildscript, rootProject)
}
// todo:KLUDGE: Hierarchical project structures are not fully supported in IDEA, enable only for a regular built
if (!Idea.active) {
ext.set("kotlin.mpp.enableGranularSourceSetsMetadata", "true")
}
// todo:KLUDGE: This is needed to workaround dependency resolution between Java and MPP modules
def configureKotlinJvmPlatform(configuration) {
configuration.attributes.attribute(KotlinPlatformType.attribute, KotlinPlatformType.jvm)
}
allprojects {
// the only place where HostManager could be instantiated
project.ext.hostManager = new HostManager()
def deployVersion = properties['DeployVersion']
if (deployVersion != null) version = deployVersion
if (build_snapshot_train) {
ext.kotlin_version = rootProject.properties['kotlin_snapshot_version']
println "Using Kotlin $kotlin_version for project $it"
def skipSnapshotChecks = rootProject.properties['skip_snapshot_checks'] != null
if (!skipSnapshotChecks && version != atomicfu_version) {
throw new IllegalStateException("Current deploy version is $version, but atomicfu version is not overridden ($atomicfu_version) for $it")
}
kotlin_version = rootProject.properties['kotlin_snapshot_version']
}
if (using_snapshot_version) {
repositories {
mavenLocal()
maven { url "https://oss.sonatype.org/content/repositories/snapshots" }
}
}
ext.unpublished = unpublished
// This project property is set during nightly stress test
def stressTest = project.properties['stressTest']
// Copy it to all test tasks
tasks.withType(Test) {
systemProperty 'stressTest', stressTest
}
}
apply plugin: "binary-compatibility-validator"
apiValidation {
ignoredProjects += unpublished + ["kotlinx-coroutines-bom"]
if (build_snapshot_train) {
ignoredProjects.remove("example-frontend-js")
ignoredProjects.add("kotlinx-coroutines-core")
}
ignoredPackages += "kotlinx.coroutines.internal"
}
// Configure repositories
allprojects {
repositories {
/*
* google should be first in the repository list because some of the play services
* transitive dependencies was removed from jcenter, thus breaking gradle dependency resolution
*/
google()
mavenCentral()
}
}
// Add dependency to core source sets. Core is configured in kx-core/build.gradle
configure(subprojects.findAll { !sourceless.contains(it.name) && it.name != coreModule }) {
evaluationDependsOn(":$coreModule")
def platform = PlatformKt.platformOf(it)
apply plugin: "kotlin-${platform}-conventions"
dependencies {
// See comment below for rationale, it will be replaced with "project" dependency
api project(":$coreModule")
// the only way IDEA can resolve test classes
testImplementation project(":$coreModule").kotlin.targets.jvm.compilations.test.output.allOutputs
}
}
// Configure subprojects with Kotlin sources
configure(subprojects.findAll { !sourceless.contains(it.name) }) {
// Use atomicfu plugin, it also adds all the necessary dependencies
apply plugin: 'kotlinx-atomicfu'
// Configure options for all Kotlin compilation tasks
tasks.withType(org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile).all {
kotlinOptions.freeCompilerArgs += optInAnnotations.collect { "-Xopt-in=" + it }
kotlinOptions.freeCompilerArgs += "-progressive"
// Disable KT-36770 for RxJava2 integration
kotlinOptions.freeCompilerArgs += "-XXLanguage:-ProhibitUsingNullableTypeParameterAgainstNotNullAnnotated"
// Remove null assertions to get smaller bytecode on Android
kotlinOptions.freeCompilerArgs += ["-Xno-param-assertions", "-Xno-receiver-assertions", "-Xno-call-assertions"]
}
}
if (build_snapshot_train) {
println "Hacking test tasks, removing stress and flaky tests"
allprojects {
tasks.withType(Test).all {
exclude '**/*LinearizabilityTest*'
exclude '**/*LFTest*'
exclude '**/*StressTest*'
exclude '**/*scheduling*'
exclude '**/*Timeout*'
exclude '**/*definitely/not/kotlinx*'
// Disable because of KT-11567 in 1.4
exclude '**/*CasesPublicAPITest*'
// Kotlin
exclude '**/*PrecompiledDebugProbesTest*'
}
}
println "Manifest of kotlin-compiler-embeddable.jar for coroutines"
configure(subprojects.findAll { it.name == "kotlinx-coroutines-core" }) {
configurations.matching { it.name == "kotlinCompilerClasspath" }.all {
resolvedConfiguration.getFiles().findAll { it.name.contains("kotlin-compiler-embeddable") }.each {
def manifest = zipTree(it).matching {
include 'META-INF/MANIFEST.MF'
}.getFiles().first()
manifest.readLines().each {
println it
}
}
}
}
}
// Redefine source sets because we are not using 'kotlin/main/fqn' folder convention
configure(subprojects.findAll {
!sourceless.contains(it.name) &&
it.name != "benchmarks" &&
it.name != coreModule &&
it.name != "example-frontend-js"
}) {
// Pure JS and pure MPP doesn't have this notion and are configured separately
// TODO detect it via platformOf and migrate benchmarks to the same scheme
sourceSets {
main.kotlin.srcDirs = ['src']
test.kotlin.srcDirs = ['test']
main.resources.srcDirs = ['resources']
test.resources.srcDirs = ['test-resources']
}
}
def core_docs_url = "https://kotlin.github.io/kotlinx.coroutines/$coreModule/"
def core_docs_file = "$projectDir/kotlinx-coroutines-core/build/dokka/htmlPartial/package-list"
apply plugin: "org.jetbrains.dokka"
configure(subprojects.findAll { !unpublished.contains(it.name) }) {
if (it.name != 'kotlinx-coroutines-bom') {
apply from: rootProject.file('gradle/dokka.gradle.kts')
}
apply from: rootProject.file('gradle/publish.gradle')
}
configure(subprojects.findAll { !unpublished.contains(it.name) }) {
if (it.name != "kotlinx-coroutines-bom") {
if (it.name != coreModule) {
tasks.withType(DokkaTaskPartial.class) {
dokkaSourceSets.configureEach {
externalDocumentationLink {
url.set(new URL(core_docs_url))
packageListUrl.set(new File(core_docs_file).toURI().toURL())
}
}
}
}
}
}
// Report Kotlin compiler version when building project
println("Using Kotlin compiler version: $org.jetbrains.kotlin.config.KotlinCompilerVersion.VERSION")
// --------------- Cache redirector ---------------
allprojects {
CacheRedirector.configure(project)
}
// --------------- Configure sub-projects that are published ---------------
def publishTasks = getTasksByName("publish", true) + getTasksByName("publishNpm", true)
task deploy(dependsOn: publishTasks)
apply plugin: 'base'
clean.dependsOn gradle.includedBuilds.collect { it.task(':clean') }
// --------------- Knit configuration ---------------
apply plugin: 'kotlinx-knit'
knit {
siteRoot = "https://kotlin.github.io/kotlinx.coroutines"
moduleRoots = [".", "integration", "reactive", "ui"]
moduleDocs = "build/dokka/htmlPartial"
dokkaMultiModuleRoot = "build/dokka/htmlMultiModule/"
}
knitPrepare.dependsOn getTasksByName("dokkaHtmlMultiModule", true)
dependencies {
dokkaHtmlMultiModulePlugin("org.jetbrains.kotlinx:dokka-pathsaver-plugin:$knit_version")
}
// Opt-in for build scan in order to troubleshoot Gradle on TC
if (hasProperty('buildScan')) {
buildScan {
termsOfServiceUrl = 'https://gradle.com/terms-of-service'
termsOfServiceAgree = 'yes'
}
}
/*
* kotlinx-coroutines-core dependency leaks into test runtime classpath via kotlin-compiler-embeddable
* and conflicts with our own test/runtime incompatibilities (e.g. when class is moved from a main to test),
* so we do substitution here
*/
allprojects { subProject ->
subProject
.configurations
.matching {
// Excluding substituted project itself because of circular dependencies, but still do it
// for "*Test*" configurations
subProject.name != "kotlinx-coroutines-core" || it.name.contains("Test")
}
.configureEach { conf ->
conf.resolutionStrategy.dependencySubstitution {
substitute(module("org.jetbrains.kotlinx:kotlinx-coroutines-core"))
.using(project(":kotlinx-coroutines-core"))
.because("Because Kotlin compiler embeddable leaks coroutines into the runtime classpath, " +
"triggering all sort of incompatible class changes errors")
}
}
}