[repo] Move buildSrc into repo/gradle-build-conventions/buildsrc-compat project
Include new project as build logic included build. Such change will allow us to start migration into build convention plugins by splitting buildSrc logic into subprojects.
This commit is contained in:
committed by
Space Team
parent
4a598afc36
commit
5b5dae9249
@@ -26,7 +26,6 @@ class CodeConformanceTest : TestCase() {
|
||||
".idea",
|
||||
"build/js",
|
||||
"build/tmp",
|
||||
"buildSrc",
|
||||
"compiler/build",
|
||||
"compiler/fir/lightTree/testData",
|
||||
"compiler/testData/psi/kdoc",
|
||||
@@ -80,8 +79,6 @@ class CodeConformanceTest : TestCase() {
|
||||
File("."),
|
||||
listOf(
|
||||
"build",
|
||||
"buildSrc/build/generated-sources",
|
||||
"buildSrc/prepare-deps/build",
|
||||
"compiler/ir/serialization.js/build/fullRuntime",
|
||||
"compiler/ir/serialization.js/build/reducedRuntime/src/libraries/stdlib/js-ir/runtime/longjs.kt",
|
||||
"dependencies",
|
||||
@@ -108,6 +105,7 @@ class CodeConformanceTest : TestCase() {
|
||||
"libraries/stdlib/js-v1/.gradle",
|
||||
"libraries/stdlib/js-v1/build",
|
||||
"libraries/stdlib/js-v1/node_modules",
|
||||
"libraries/stdlib/jvm/build",
|
||||
"libraries/stdlib/jvm-minimal-for-test/build",
|
||||
"libraries/stdlib/wasm/build",
|
||||
"libraries/tools/atomicfu/build",
|
||||
@@ -142,6 +140,7 @@ class CodeConformanceTest : TestCase() {
|
||||
"repo/gradle-settings-conventions/jvm-toolchain-provisioning/build/generated-sources",
|
||||
"repo/gradle-settings-conventions/gradle-enterprise/build/generated-sources",
|
||||
"repo/gradle-settings-conventions/kotlin-daemon-config/build/generated-sources",
|
||||
"repo/gradle-build-conventions/buildsrc-compat/build/generated-sources",
|
||||
".gradle/expanded",
|
||||
)
|
||||
)
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
## Description
|
||||
|
||||
Provides common build convention plugins for the repo.
|
||||
|
||||
### List of plugins
|
||||
|
||||
- "buildsrc-compat" — migrated 'buildSrc' project. Will exist until it will be separated into different convention plugins.
|
||||
@@ -0,0 +1,149 @@
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
buildscript {
|
||||
// workaround for KGP build metrics reports: https://github.com/gradle/gradle/issues/20001
|
||||
project.extensions.extraProperties["kotlin.build.report.output"] = null
|
||||
|
||||
val versionPropertiesFile = project.rootProject.projectDir.parentFile.resolve("../gradle/versions.properties")
|
||||
val versionProperties = java.util.Properties()
|
||||
versionPropertiesFile.inputStream().use { propInput ->
|
||||
versionProperties.load(propInput)
|
||||
}
|
||||
configurations.all {
|
||||
resolutionStrategy.eachDependency {
|
||||
if (requested.group == "com.google.code.gson" && requested.name == "gson") {
|
||||
useVersion(versionProperties["versions.gson"] as String)
|
||||
because("Force using same gson version because of https://github.com/google/gson/pull/1991")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.info("buildSrcKotlinVersion: " + extra["bootstrapKotlinVersion"])
|
||||
logger.info("buildSrc kotlin compiler version: " + org.jetbrains.kotlin.config.KotlinCompilerVersion.VERSION)
|
||||
logger.info("buildSrc stdlib version: " + KotlinVersion.CURRENT)
|
||||
|
||||
apply {
|
||||
from("../../../gradle/checkCacheability.gradle.kts")
|
||||
}
|
||||
|
||||
plugins {
|
||||
`kotlin-dsl`
|
||||
`java-gradle-plugin`
|
||||
id("org.jetbrains.kotlin.jvm")
|
||||
}
|
||||
|
||||
gradlePlugin {
|
||||
plugins {
|
||||
register("jps-compatible") {
|
||||
id = "jps-compatible"
|
||||
implementationClass = "org.jetbrains.kotlin.pill.JpsCompatiblePlugin"
|
||||
}
|
||||
register("kotlin-build-publishing") {
|
||||
id = "kotlin-build-publishing"
|
||||
implementationClass = "plugins.KotlinBuildPublishingPlugin"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.getBooleanProperty(name: String): Boolean? = this.findProperty(name)?.let {
|
||||
val v = it.toString()
|
||||
if (v.isBlank()) true
|
||||
else v.toBoolean()
|
||||
}
|
||||
|
||||
project.apply {
|
||||
from(rootProject.file("../../gradle/versions.gradle.kts"))
|
||||
}
|
||||
|
||||
val isTeamcityBuild = kotlinBuildProperties.isTeamcityBuild
|
||||
val intellijSeparateSdks by extra(project.getBooleanProperty("intellijSeparateSdks") ?: false)
|
||||
|
||||
extra["intellijReleaseType"] = when {
|
||||
extra["versions.intellijSdk"]?.toString()?.contains("-EAP-") == true -> "snapshots"
|
||||
extra["versions.intellijSdk"]?.toString()?.endsWith("SNAPSHOT") == true -> "nightly"
|
||||
else -> "releases"
|
||||
}
|
||||
|
||||
extra["versions.androidDxSources"] = "5.0.0_r2"
|
||||
extra["customDepsOrg"] = "kotlin.build"
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
google()
|
||||
maven("https://packages.jetbrains.team/maven/p/ij/intellij-dependencies")
|
||||
maven("https://maven.pkg.jetbrains.space/kotlin/p/kotlin/kotlin-dependencies")
|
||||
gradlePluginPortal()
|
||||
|
||||
extra["bootstrapKotlinRepo"]?.let {
|
||||
maven(url = it)
|
||||
}
|
||||
}
|
||||
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion.set(JavaLanguageVersion.of(8))
|
||||
}
|
||||
}
|
||||
|
||||
tasks.validatePlugins.configure {
|
||||
enabled = false
|
||||
}
|
||||
|
||||
java {
|
||||
disableAutoTargetJvm()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation(kotlin("stdlib", embeddedKotlinVersion))
|
||||
implementation("org.jetbrains.kotlin:kotlin-build-gradle-plugin:${kotlinBuildProperties.buildGradlePluginVersion}")
|
||||
implementation("com.gradle.publish:plugin-publish-plugin:1.0.0")
|
||||
implementation("org.jetbrains.dokka:dokka-gradle-plugin:1.8.20")
|
||||
|
||||
implementation("org.spdx:spdx-gradle-plugin:0.1.0-dev-8")
|
||||
|
||||
implementation("com.jakewharton.dex:dex-member-list:4.1.1")
|
||||
|
||||
implementation("gradle.plugin.com.github.johnrengelman:shadow:${project.extra["versions.shadow"]}") {
|
||||
// https://github.com/johnrengelman/shadow/issues/807
|
||||
exclude("org.ow2.asm")
|
||||
}
|
||||
implementation("net.sf.proguard:proguard-gradle:6.2.2")
|
||||
|
||||
// Version should be in sync with <root>/build.gradle.kts
|
||||
implementation("gradle.plugin.org.jetbrains.gradle.plugin.idea-ext:gradle-idea-ext:1.0.1")
|
||||
|
||||
implementation("io.ktor:ktor-client-core:${project.extra["versions.ktor-client-core"]}")
|
||||
implementation("io.ktor:ktor-client-cio:${project.extra["versions.ktor-client-cio"]}")
|
||||
|
||||
compileOnly("com.gradle:gradle-enterprise-gradle-plugin:3.12.4")
|
||||
|
||||
compileOnly(gradleApi())
|
||||
|
||||
// See https://github.com/gradle/gradle/issues/22510
|
||||
implementation("org.gradle.kotlin:gradle-kotlin-dsl-plugins:2.4.1")
|
||||
implementation("org.jetbrains.kotlin:kotlin-gradle-plugin:${project.bootstrapKotlinVersion}")
|
||||
implementation("org.jetbrains.kotlin:kotlin-stdlib:${project.bootstrapKotlinVersion}")
|
||||
implementation("org.jetbrains.kotlin:kotlin-reflect:${project.bootstrapKotlinVersion}")
|
||||
implementation("com.google.code.gson:gson:2.8.9") // Workaround for Gradle dependency resolution error
|
||||
implementation("org.jetbrains.kotlinx:kotlinx-metadata-jvm:0.6.2")
|
||||
}
|
||||
|
||||
samWithReceiver {
|
||||
annotation("org.gradle.api.HasImplicitReceiver")
|
||||
}
|
||||
|
||||
fun Project.samWithReceiver(configure: org.jetbrains.kotlin.samWithReceiver.gradle.SamWithReceiverExtension.() -> Unit): Unit =
|
||||
extensions.configure("samWithReceiver", configure)
|
||||
|
||||
tasks.withType<KotlinCompile>().configureEach {
|
||||
compilerOptions {
|
||||
allWarningsAsErrors.set(true)
|
||||
optIn.add("kotlin.ExperimentalStdlibApi")
|
||||
freeCompilerArgs.add("-Xsuppress-version-warnings")
|
||||
}
|
||||
}
|
||||
|
||||
allprojects {
|
||||
tasks.register("checkBuild")
|
||||
}
|
||||
@@ -0,0 +1,462 @@
|
||||
@file:Suppress("PropertyName", "HasPlatformType", "UnstableApiUsage")
|
||||
|
||||
import org.gradle.internal.os.OperatingSystem
|
||||
import org.jetbrains.kotlin.gradle.tasks.internal.CleanableStore
|
||||
import java.io.Closeable
|
||||
import java.io.OutputStreamWriter
|
||||
import java.net.URI
|
||||
import java.text.SimpleDateFormat
|
||||
import java.time.Duration
|
||||
import java.time.Instant
|
||||
import java.util.*
|
||||
import javax.xml.stream.XMLOutputFactory
|
||||
|
||||
plugins {
|
||||
base
|
||||
}
|
||||
|
||||
val intellijReleaseType: String by rootProject.extra
|
||||
val intellijVersion = rootProject.extra["versions.intellijSdk"] as String
|
||||
val intellijVersionForIde = rootProject.intellijSdkVersionForIde()
|
||||
val asmVersion = rootProject.findProperty("versions.jar.asm-all") as String?
|
||||
val androidStudioRelease = rootProject.findProperty("versions.androidStudioRelease") as String?
|
||||
val androidStudioBuild = rootProject.findProperty("versions.androidStudioBuild") as String?
|
||||
val intellijSeparateSdks: Boolean by rootProject.extra
|
||||
|
||||
fun checkIntellijVersion(intellijVersion: String) {
|
||||
val intellijVersionDelimiterIndex = intellijVersion.indexOfAny(charArrayOf('.', '-'))
|
||||
if (intellijVersionDelimiterIndex == -1) {
|
||||
error("Invalid IDEA version $intellijVersion")
|
||||
}
|
||||
}
|
||||
checkIntellijVersion(intellijVersion)
|
||||
intellijVersionForIde?.let { checkIntellijVersion(it) }
|
||||
|
||||
logger.info("intellijVersion: $intellijVersion")
|
||||
logger.info("intellijVersionForIde: $intellijVersionForIde")
|
||||
logger.info("androidStudioRelease: $androidStudioRelease")
|
||||
logger.info("androidStudioBuild: $androidStudioBuild")
|
||||
logger.info("intellijSeparateSdks: $intellijSeparateSdks")
|
||||
|
||||
val androidStudioOs by lazy {
|
||||
when {
|
||||
OperatingSystem.current().isWindows -> "windows"
|
||||
OperatingSystem.current().isMacOsX -> "mac"
|
||||
OperatingSystem.current().isLinux -> "linux"
|
||||
else -> {
|
||||
logger.error("Unknown operating system for android tools: ${OperatingSystem.current().name}")
|
||||
""
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
if (androidStudioRelease != null) {
|
||||
ivy {
|
||||
url = URI("https://dl.google.com/dl/android/studio/ide-zips/$androidStudioRelease")
|
||||
|
||||
patternLayout {
|
||||
artifact("[artifact]-[revision]-$androidStudioOs.[ext]")
|
||||
}
|
||||
|
||||
metadataSources {
|
||||
artifact()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
maven("https://www.jetbrains.com/intellij-repository/$intellijReleaseType")
|
||||
maven("https://plugins.jetbrains.com/maven")
|
||||
maven("https://packages.jetbrains.team/maven/p/ij/intellij-dependencies")
|
||||
}
|
||||
|
||||
val intellij by configurations.creating
|
||||
val intellijForIde by configurations.creating
|
||||
val androidStudio by configurations.creating
|
||||
val sources by configurations.creating
|
||||
val sourcesForIde by configurations.creating
|
||||
val jpsStandalone by configurations.creating
|
||||
val jpsStandaloneForIde by configurations.creating
|
||||
val intellijCore by configurations.creating
|
||||
val intellijCoreForIde by configurations.creating
|
||||
|
||||
/**
|
||||
* Special repository for annotations.jar required for idea runtime only.
|
||||
*
|
||||
* See IntellijDependenciesKt.intellijRuntimeAnnotations for more details.
|
||||
*/
|
||||
val intellijRuntimeAnnotations = "intellij-runtime-annotations"
|
||||
|
||||
val dependenciesDir = (findProperty("kotlin.build.dependencies.dir") as String?)?.let(::File)
|
||||
?: rootProject.gradle.gradleUserHomeDir.resolve("kotlin-build-dependencies")
|
||||
|
||||
val customDepsRepoDir = dependenciesDir.resolve("repo")
|
||||
|
||||
val customDepsOrg: String by rootProject.extra
|
||||
val repoDir = File(customDepsRepoDir, customDepsOrg)
|
||||
|
||||
dependencies {
|
||||
if (androidStudioRelease != null) {
|
||||
val extension = if (androidStudioOs == "linux")
|
||||
"tar.gz"
|
||||
else
|
||||
"zip"
|
||||
|
||||
androidStudio("google:android-studio-ide:$androidStudioBuild@$extension")
|
||||
} else {
|
||||
intellij("com.jetbrains.intellij.idea:ideaIC:$intellijVersion")
|
||||
intellijVersionForIde?.let { intellijForIde("com.jetbrains.intellij.idea:ideaIC:$it") }
|
||||
}
|
||||
|
||||
if (asmVersion != null) {
|
||||
sources("org.jetbrains.intellij.deps:asm-all:$asmVersion:sources@jar")
|
||||
}
|
||||
|
||||
sources("com.jetbrains.intellij.idea:ideaIC:$intellijVersion:sources@jar")
|
||||
intellijVersionForIde?.let { sourcesForIde("com.jetbrains.intellij.idea:ideaIC:$it:sources@jar") }
|
||||
jpsStandalone("com.jetbrains.intellij.idea:jps-standalone:$intellijVersion")
|
||||
intellijVersionForIde?.let { jpsStandaloneForIde("com.jetbrains.intellij.idea:jps-standalone:$it") }
|
||||
intellijCore("com.jetbrains.intellij.idea:intellij-core:$intellijVersion")
|
||||
intellijVersionForIde?.let { intellijCoreForIde("com.jetbrains.intellij.idea:intellij-core:$it") }
|
||||
}
|
||||
|
||||
fun prepareDeps(
|
||||
intellij: Configuration,
|
||||
intellijCore: Configuration,
|
||||
sources: Configuration,
|
||||
jpsStandalone: Configuration,
|
||||
intellijVersion: String
|
||||
) {
|
||||
val makeIntellijCore = buildIvyRepositoryTask(intellijCore, customDepsOrg, customDepsRepoDir)
|
||||
|
||||
val makeIntellijAnnotations = tasks.register("makeIntellijAnnotations${intellij.name.replaceFirstChar(Char::uppercase)}", Copy::class) {
|
||||
dependsOn(makeIntellijCore)
|
||||
|
||||
val intellijCoreRepo = CleanableStore[repoDir.resolve("intellij-core").absolutePath][intellijVersion].use()
|
||||
from(intellijCoreRepo.resolve("artifacts/annotations.jar"))
|
||||
|
||||
val annotationsStore = CleanableStore[repoDir.resolve(intellijRuntimeAnnotations).absolutePath]
|
||||
val targetDir = annotationsStore[intellijVersion].use()
|
||||
into(targetDir)
|
||||
|
||||
val ivyFile = File(targetDir, "$intellijRuntimeAnnotations.ivy.xml")
|
||||
outputs.files(ivyFile)
|
||||
|
||||
doFirst {
|
||||
annotationsStore.cleanStore()
|
||||
}
|
||||
|
||||
doLast {
|
||||
writeIvyXml(
|
||||
customDepsOrg,
|
||||
intellijRuntimeAnnotations,
|
||||
intellijVersion,
|
||||
intellijRuntimeAnnotations,
|
||||
targetDir,
|
||||
targetDir,
|
||||
targetDir,
|
||||
allowAnnotations = true
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val mergeSources = tasks.create("mergeSources${intellij.name.replaceFirstChar(Char::uppercase)}", Jar::class.java) {
|
||||
dependsOn(sources)
|
||||
isPreserveFileTimestamps = false
|
||||
isReproducibleFileOrder = true
|
||||
isZip64 = true
|
||||
if (!kotlinBuildProperties.isTeamcityBuild) {
|
||||
from(provider { sources.map(::zipTree) })
|
||||
}
|
||||
destinationDirectory.set(File(repoDir, sources.name))
|
||||
archiveBaseName.set("intellij")
|
||||
archiveClassifier.set("sources")
|
||||
archiveVersion.set(intellijVersion)
|
||||
}
|
||||
|
||||
val sourcesFile = mergeSources.outputs.files.singleFile
|
||||
|
||||
val makeIde = if (androidStudioBuild != null) {
|
||||
buildIvyRepositoryTask(
|
||||
androidStudio,
|
||||
customDepsOrg,
|
||||
customDepsRepoDir,
|
||||
if (androidStudioOs == "mac")
|
||||
::skipContentsDirectory
|
||||
else
|
||||
::skipToplevelDirectory
|
||||
)
|
||||
} else {
|
||||
val task = buildIvyRepositoryTask(intellij, customDepsOrg, customDepsRepoDir, null, sourcesFile)
|
||||
|
||||
task.configure {
|
||||
dependsOn(mergeSources)
|
||||
}
|
||||
|
||||
task
|
||||
}
|
||||
|
||||
val buildJpsStandalone = buildIvyRepositoryTask(jpsStandalone, customDepsOrg, customDepsRepoDir, null, sourcesFile)
|
||||
|
||||
tasks.named("build") {
|
||||
dependsOn(
|
||||
makeIntellijCore,
|
||||
makeIde,
|
||||
buildJpsStandalone,
|
||||
makeIntellijAnnotations
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
when(kotlinBuildProperties.getOrNull("attachedIntellijVersion")) {
|
||||
null -> {}
|
||||
"master" -> {} // for intellij/kt-master, intellij maven artifacts are used instead of manual unpacked dependencies
|
||||
else -> {
|
||||
val intellijVersionForIde = intellijVersionForIde
|
||||
?: error("intellijVersionForIde should not be null as attachedIntellijVersion is present")
|
||||
prepareDeps(intellijForIde, intellijCoreForIde, sourcesForIde, jpsStandaloneForIde, intellijVersionForIde)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
tasks.named<Delete>("clean") {
|
||||
delete(customDepsRepoDir)
|
||||
}
|
||||
|
||||
fun buildIvyRepositoryTask(
|
||||
configuration: Configuration,
|
||||
organization: String,
|
||||
repoDirectory: File,
|
||||
pathRemap: ((String) -> String)? = null,
|
||||
sources: File? = null
|
||||
): TaskProvider<Task> {
|
||||
fun ResolvedArtifact.storeDirectory(): CleanableStore =
|
||||
CleanableStore[repoDirectory.resolve("$organization/${moduleVersion.id.name}").absolutePath]
|
||||
|
||||
fun ResolvedArtifact.moduleDirectory(): File =
|
||||
storeDirectory()[moduleVersion.id.version].use()
|
||||
|
||||
return tasks.register("buildIvyRepositoryFor${configuration.name.replaceFirstChar(Char::uppercase)}") {
|
||||
dependsOn(configuration)
|
||||
inputs.files(configuration)
|
||||
|
||||
outputs.upToDateWhen {
|
||||
val repoMarker = configuration.resolvedConfiguration.resolvedArtifacts.single().moduleDirectory().resolve(".marker")
|
||||
repoMarker.exists()
|
||||
}
|
||||
|
||||
doFirst {
|
||||
val artifact = configuration.resolvedConfiguration.resolvedArtifacts.single()
|
||||
val moduleDirectory = artifact.moduleDirectory()
|
||||
|
||||
artifact.storeDirectory().cleanStore()
|
||||
|
||||
val repoMarker = File(moduleDirectory, ".marker")
|
||||
if (repoMarker.exists()) {
|
||||
logger.info("Path ${repoMarker.absolutePath} already exists, skipping unpacking.")
|
||||
return@doFirst
|
||||
}
|
||||
|
||||
with(artifact) {
|
||||
val artifactsDirectory = File(moduleDirectory, "artifacts")
|
||||
logger.info("Unpacking ${file.name} into ${artifactsDirectory.absolutePath}")
|
||||
copy {
|
||||
val fileTree = when (extension) {
|
||||
"tar.gz" -> tarTree(file)
|
||||
"zip" -> zipTree(file)
|
||||
else -> error("Unsupported artifact extension: $extension")
|
||||
}
|
||||
|
||||
from(
|
||||
fileTree.matching {
|
||||
exclude("**/plugins/Kotlin/**")
|
||||
}
|
||||
)
|
||||
|
||||
into(artifactsDirectory)
|
||||
|
||||
if (pathRemap != null) {
|
||||
eachFile {
|
||||
path = pathRemap(path)
|
||||
}
|
||||
}
|
||||
|
||||
includeEmptyDirs = false
|
||||
}
|
||||
|
||||
writeIvyXml(
|
||||
organization,
|
||||
moduleVersion.id.name,
|
||||
moduleVersion.id.version,
|
||||
moduleVersion.id.name,
|
||||
File(artifactsDirectory, "lib"),
|
||||
File(artifactsDirectory, "lib"),
|
||||
File(moduleDirectory, "ivy"),
|
||||
*listOfNotNull(sources).toTypedArray()
|
||||
)
|
||||
|
||||
val pluginsDirectory = File(artifactsDirectory, "plugins")
|
||||
if (pluginsDirectory.exists()) {
|
||||
file(File(artifactsDirectory, "plugins"))
|
||||
.listFiles { file: File -> file.isDirectory }
|
||||
.forEach {
|
||||
writeIvyXml(
|
||||
organization,
|
||||
it.name,
|
||||
moduleVersion.id.version,
|
||||
it.name,
|
||||
File(it, "lib"),
|
||||
File(it, "lib"),
|
||||
File(moduleDirectory, "ivy"),
|
||||
*listOfNotNull(sources).toTypedArray()
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
repoMarker.createNewFile()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun CleanableStore.cleanStore() = cleanDir(Instant.now().minus(Duration.ofDays(30)))
|
||||
|
||||
fun writeIvyXml(
|
||||
organization: String,
|
||||
moduleName: String,
|
||||
version: String,
|
||||
fileName: String,
|
||||
baseDir: File,
|
||||
artifactDir: File,
|
||||
targetDir: File,
|
||||
vararg sourcesJar: File,
|
||||
allowAnnotations: Boolean = false
|
||||
) {
|
||||
fun shouldIncludeIntellijJar(jar: File) =
|
||||
jar.isFile
|
||||
&& jar.extension == "jar"
|
||||
&& !jar.name.startsWith("kotlin-")
|
||||
&& (allowAnnotations || jar.name != "annotations.jar") // see comments for [intellijAnnotations] above
|
||||
|
||||
val ivyFile = targetDir.resolve("$fileName.ivy.xml")
|
||||
ivyFile.parentFile.mkdirs()
|
||||
with(XMLWriter(ivyFile.writer())) {
|
||||
document("UTF-8", "1.0") {
|
||||
element("ivy-module") {
|
||||
attribute("version", "2.0")
|
||||
attribute("xmlns:m", "http://ant.apache.org/ivy/maven")
|
||||
|
||||
emptyElement("info") {
|
||||
attributes(
|
||||
"organisation" to organization,
|
||||
"module" to moduleName,
|
||||
"revision" to version,
|
||||
"publication" to SimpleDateFormat("yyyyMMddHHmmss").format(Date())
|
||||
)
|
||||
}
|
||||
|
||||
element("configurations") {
|
||||
listOf("default", "sources").forEach { configurationName ->
|
||||
emptyElement("conf") {
|
||||
attributes("name" to configurationName, "visibility" to "public")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
element("publications") {
|
||||
artifactDir.listFiles()
|
||||
?.filter(::shouldIncludeIntellijJar)
|
||||
?.sortedBy { it.name.lowercase() }
|
||||
?.forEach { jarFile ->
|
||||
val relativeName = jarFile.toRelativeString(baseDir).removeSuffix(".jar")
|
||||
emptyElement("artifact") {
|
||||
attributes(
|
||||
"name" to relativeName,
|
||||
"type" to "jar",
|
||||
"ext" to "jar",
|
||||
"conf" to "default"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
sourcesJar.forEach { jarFile ->
|
||||
emptyElement("artifact") {
|
||||
val sourcesArtifactName = jarFile.name.substringBefore("-$version")
|
||||
attributes(
|
||||
"name" to sourcesArtifactName,
|
||||
"type" to "jar",
|
||||
"ext" to "jar",
|
||||
"conf" to "sources",
|
||||
"m:classifier" to "sources"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
close()
|
||||
}
|
||||
}
|
||||
|
||||
fun skipToplevelDirectory(path: String) = path.substringAfter('/')
|
||||
|
||||
fun skipContentsDirectory(path: String) = path.substringAfter("Contents/")
|
||||
|
||||
fun Project.intellijSdkVersionForIde(): String? {
|
||||
val majorVersion = kotlinBuildProperties.getOrNull("attachedIntellijVersion") as? String ?: return null
|
||||
return rootProject.findProperty("versions.intellijSdk.forIde.$majorVersion") as? String
|
||||
}
|
||||
|
||||
class XMLWriter(private val outputStreamWriter: OutputStreamWriter) : Closeable {
|
||||
|
||||
private val xmlStreamWriter = XMLOutputFactory.newInstance().createXMLStreamWriter(outputStreamWriter)
|
||||
|
||||
private var depth = 0
|
||||
private val indent = " "
|
||||
|
||||
fun document(encoding: String, version: String, init: XMLWriter.() -> Unit) = apply {
|
||||
xmlStreamWriter.writeStartDocument(encoding, version)
|
||||
|
||||
init()
|
||||
|
||||
xmlStreamWriter.writeEndDocument()
|
||||
}
|
||||
|
||||
fun element(name: String, init: XMLWriter.() -> Unit) = apply {
|
||||
writeIndent()
|
||||
xmlStreamWriter.writeStartElement(name)
|
||||
depth += 1
|
||||
|
||||
init()
|
||||
|
||||
depth -= 1
|
||||
writeIndent()
|
||||
xmlStreamWriter.writeEndElement()
|
||||
}
|
||||
|
||||
fun emptyElement(name: String, init: XMLWriter.() -> Unit) = apply {
|
||||
writeIndent()
|
||||
xmlStreamWriter.writeEmptyElement(name)
|
||||
init()
|
||||
}
|
||||
|
||||
fun attribute(name: String, value: String): Unit = xmlStreamWriter.writeAttribute(name, value)
|
||||
|
||||
fun attributes(vararg attributes: Pair<String, String>) {
|
||||
attributes.forEach { attribute(it.first, it.second) }
|
||||
}
|
||||
|
||||
private fun writeIndent() {
|
||||
xmlStreamWriter.writeCharacters("\n")
|
||||
repeat(depth) {
|
||||
xmlStreamWriter.writeCharacters(indent)
|
||||
}
|
||||
}
|
||||
|
||||
override fun close() {
|
||||
xmlStreamWriter.flush()
|
||||
xmlStreamWriter.close()
|
||||
outputStreamWriter.close()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.api.tasks.testing.Test
|
||||
import java.io.File
|
||||
|
||||
// You can see "How To" via link: https://jetbrains.quip.com/xQ2WAUy9bZmy/How-to-use-AggregateTest-task
|
||||
open class AggregateTest : Test() { // Inherit from Test to see test results in IDEA Test viewer
|
||||
private var patterns: MutableMap<String, MutableList<String>> = mutableMapOf()
|
||||
|
||||
@InputFile
|
||||
lateinit var testPatternFile: File
|
||||
|
||||
init {
|
||||
// Set empty FileCollection to avoid NPE when initializing a base 'Test' class
|
||||
classpath = project.objects.fileCollection()
|
||||
testClassesDirs = project.objects.fileCollection()
|
||||
|
||||
project.gradle.taskGraph.whenReady {
|
||||
if (allTasks.filterIsInstance<AggregateTest>().isNotEmpty()) {
|
||||
initPatterns()
|
||||
allTasks.filterIsInstance<Test>().forEach { testTask -> subTaskConfigure(testTask) }
|
||||
|
||||
if (!project.gradle.startParameter.taskNames.all { project.tasks.findByPath(it) is AggregateTest }) {
|
||||
logger.warn("Please, don't use AggregateTest and non-AggregateTest test tasks together. You can get incorrect results.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun initPatterns() {
|
||||
if (!testPatternFile.exists())
|
||||
throw GradleException("File with test patterns is not found")
|
||||
testPatternFile
|
||||
.readLines()
|
||||
.asSequence()
|
||||
.filter { it.isNotEmpty() }
|
||||
.forEach { line ->
|
||||
// patternType is exclude or include value
|
||||
val (pattern, patternType) = line.split(',').map { it.trim() }
|
||||
patterns.getOrPut(patternType) { mutableListOf() }.add(pattern)
|
||||
}
|
||||
}
|
||||
|
||||
private fun subTaskConfigure(testTask: Test) {
|
||||
testTask.doNotTrackState("State is tracked by AggregateTest task")
|
||||
testTask.ignoreFailures = true
|
||||
testTask.filter {
|
||||
isFailOnNoMatchingTests = false
|
||||
patterns["include"]?.let {
|
||||
it.forEach { pattern ->
|
||||
includeTestsMatching(pattern)
|
||||
}
|
||||
}
|
||||
patterns["exclude"]?.let {
|
||||
it.forEach { pattern ->
|
||||
excludeTestsMatching(pattern)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@TaskAction
|
||||
override fun executeTests() {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
val KotlinBuildProperties.includeJava9: Boolean
|
||||
get() = !isInJpsBuildIdeaSync && getBoolean("kotlin.build.java9", true)
|
||||
|
||||
val KotlinBuildProperties.useBootstrapStdlib: Boolean
|
||||
get() = isInJpsBuildIdeaSync || getBoolean("kotlin.build.useBootstrapStdlib", false)
|
||||
|
||||
val KotlinBuildProperties.postProcessing: Boolean get() = isTeamcityBuild || getBoolean("kotlin.build.postprocessing", true)
|
||||
|
||||
val KotlinBuildProperties.relocation: Boolean get() = postProcessing
|
||||
|
||||
val KotlinBuildProperties.proguard: Boolean get() = postProcessing && getBoolean("kotlin.build.proguard", isTeamcityBuild)
|
||||
|
||||
val KotlinBuildProperties.jarCompression: Boolean get() = getBoolean("kotlin.build.jar.compression", isTeamcityBuild)
|
||||
|
||||
val KotlinBuildProperties.ignoreTestFailures: Boolean get() = getBoolean("ignoreTestFailures", isTeamcityBuild)
|
||||
|
||||
val KotlinBuildProperties.disableWerror: Boolean
|
||||
get() = getBoolean("kotlin.build.disable.werror") || useFir || isInJpsBuildIdeaSync || getBoolean("test.progressive.mode")
|
||||
|
||||
val KotlinBuildProperties.generateModularizedConfigurations: Boolean
|
||||
get() = getBoolean("kotlin.fir.modularized.mt.configurations", false)
|
||||
|
||||
val KotlinBuildProperties.generateFullPipelineConfigurations: Boolean
|
||||
get() = getBoolean("kotlin.fir.modularized.fp.configurations", false)
|
||||
|
||||
val KotlinBuildProperties.pathToKotlinModularizedTestData: String?
|
||||
get() = getOrNull("kotlin.fir.modularized.testdata.kotlin") as? String
|
||||
|
||||
val KotlinBuildProperties.pathToIntellijModularizedTestData: String?
|
||||
get() = getOrNull("kotlin.fir.modularized.testdata.intellij") as? String
|
||||
|
||||
val KotlinBuildProperties.pathToYoutrackModularizedTestData: String?
|
||||
get() = getOrNull("kotlin.fir.modularized.testdata.youtrack") as? String
|
||||
|
||||
val KotlinBuildProperties.pathToSpaceModularizedTestData: String?
|
||||
get() = getOrNull("kotlin.fir.modularized.testdata.space") as? String
|
||||
|
||||
val KotlinBuildProperties.isObsoleteJdkOverrideEnabled: Boolean
|
||||
get() = getBoolean("kotlin.build.isObsoleteJdkOverrideEnabled", false)
|
||||
|
||||
val KotlinBuildProperties.isNativeRuntimeDebugInfoEnabled: Boolean
|
||||
get() = getBoolean("kotlin.native.isNativeRuntimeDebugInfoEnabled", false)
|
||||
|
||||
val KotlinBuildProperties.junit5NumberOfThreadsForParallelExecution: Int?
|
||||
get() = (getOrNull("kotlin.test.junit5.maxParallelForks") as? String)?.toInt()
|
||||
|
||||
// Enabling publishing docs jars only on CI build by default
|
||||
// Currently dokka task runs non-incrementally and takes big amount of time
|
||||
val KotlinBuildProperties.publishGradlePluginsJavadoc: Boolean
|
||||
get() = getBoolean("kotlin.build.gradle.publish.javadocs", isTeamcityBuild)
|
||||
|
||||
val KotlinBuildProperties.useFirWithLightTree: Boolean
|
||||
get() = getBoolean("kotlin.build.useFirLT")
|
||||
|
||||
val KotlinBuildProperties.useFirTightIC: Boolean
|
||||
get() = getBoolean("kotlin.build.useFirIC")
|
||||
+389
@@ -0,0 +1,389 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
import groovy.lang.Closure
|
||||
import org.gradle.api.JavaVersion
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.provider.Provider
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.jvm.toolchain.JavaLauncher
|
||||
import org.gradle.kotlin.dsl.property
|
||||
import proguard.ClassSpecification
|
||||
import java.io.File
|
||||
|
||||
@CacheableTask
|
||||
open class CacheableProguardTask : proguard.gradle.ProGuardTask() {
|
||||
|
||||
@get:Internal
|
||||
val javaLauncher: Property<JavaLauncher> = project.objects.property()
|
||||
|
||||
@get:Internal
|
||||
val jdkHomePath: Provider<File> = javaLauncher.map { it.metadata.installationPath.asFile }
|
||||
|
||||
@get:Optional
|
||||
@get:Input
|
||||
internal val jdkMajorVersion: Provider<JavaVersion> = javaLauncher.map {
|
||||
JavaVersion.toVersion(it.metadata.languageVersion.toString())
|
||||
}
|
||||
|
||||
@CompileClasspath
|
||||
override fun getLibraryJarFileCollection(): FileCollection = super.getLibraryJarFileCollection()
|
||||
.filter { libraryFile ->
|
||||
jdkHomePath.orNull?.let { !libraryFile.absoluteFile.startsWith(it.absoluteFile) } ?: true
|
||||
}
|
||||
|
||||
@InputFiles
|
||||
@PathSensitive(PathSensitivity.RELATIVE)
|
||||
override fun getConfigurationFileCollection(): FileCollection = super.getConfigurationFileCollection()
|
||||
|
||||
@InputFiles
|
||||
@Classpath
|
||||
override fun getInJarFileCollection(): FileCollection = super.getInJarFileCollection()
|
||||
|
||||
@Optional
|
||||
@OutputFiles
|
||||
override fun getOutJarFileCollection(): FileCollection = super.getOutJarFileCollection()
|
||||
|
||||
@get:Optional
|
||||
@get:OutputFile
|
||||
internal val printConfigurationFile: File?
|
||||
get() = configuration.printConfiguration?.takeIf { it.path.isNotEmpty() }
|
||||
|
||||
@Input
|
||||
override fun getOutJarFilters(): MutableList<Any?> = super.getOutJarFilters()
|
||||
|
||||
@Input
|
||||
override fun getInJarFilters(): MutableList<Any?> = super.getInJarFilters()
|
||||
|
||||
@Input
|
||||
override fun getLibraryJarFilters(): MutableList<Any?> = super.getLibraryJarFilters()
|
||||
|
||||
@Internal
|
||||
override fun getOutJarFiles(): MutableList<Any?> = super.getOutJarFiles()
|
||||
|
||||
@Internal
|
||||
override fun getInJarFiles(): MutableList<Any?> = super.getInJarFiles()
|
||||
|
||||
@Internal
|
||||
override fun getInJarCounts(): MutableList<Any?> = super.getInJarCounts()
|
||||
|
||||
@Internal
|
||||
override fun getLibraryJarFiles(): MutableList<Any?> = super.getLibraryJarFiles()
|
||||
|
||||
/*
|
||||
* Inputs properly declared these methods so we don't override them
|
||||
*
|
||||
* configuration(configurationFiles: Any?)
|
||||
* libraryjars(libraryJarFiles: Any?)
|
||||
* libraryjars(filterArgs: MutableMap<Any?, Any?>?, libraryJarFiles: Any?)
|
||||
* injars(inJarFiles: Any?)
|
||||
* injars(filterArgs: MutableMap<Any?, Any?>?, inJarFiles: Any?)
|
||||
* outjars(outJarFiles: Any?)
|
||||
* outjars(filterArgs: MutableMap<Any?, Any?>?, outJarFiles: Any?)
|
||||
* printconfiguration()
|
||||
* printconfiguration(printConfiguration: Any?)
|
||||
*/
|
||||
|
||||
override fun renamesourcefileattribute() = throw NotImplementedError()
|
||||
|
||||
override fun renamesourcefileattribute(newSourceFileAttribute: String?) = throw NotImplementedError()
|
||||
|
||||
override fun dontshrink() = throw NotImplementedError()
|
||||
|
||||
override fun assumenosideeffects(classSpecificationString: String?) = throw NotImplementedError()
|
||||
|
||||
override fun assumenosideeffects(classSpecificationArgs: MutableMap<Any?, Any?>?, classMembersClosure: Closure<*>?) = throw NotImplementedError()
|
||||
|
||||
override fun keepnames(classSpecificationString: String?) = throw NotImplementedError()
|
||||
|
||||
override fun keepnames(keepArgs: MutableMap<Any?, Any?>?, classSpecificationString: String?) = throw NotImplementedError()
|
||||
|
||||
override fun keepnames(keepClassSpecificationArgs: MutableMap<Any?, Any?>?) = throw NotImplementedError()
|
||||
|
||||
override fun keepnames(keepClassSpecificationArgs: MutableMap<Any?, Any?>?, classMembersClosure: Closure<*>?) = throw NotImplementedError()
|
||||
|
||||
override fun printmapping() = throw NotImplementedError()
|
||||
|
||||
override fun printmapping(printMapping: Any?) = throw NotImplementedError()
|
||||
|
||||
override fun keep(classSpecificationString: String?) = throw NotImplementedError()
|
||||
|
||||
override fun keep(keepArgs: MutableMap<Any?, Any?>?, classSpecificationString: String?) = throw NotImplementedError()
|
||||
|
||||
override fun keep(keepClassSpecificationArgs: MutableMap<Any?, Any?>?) = throw NotImplementedError()
|
||||
|
||||
override fun keep(keepClassSpecificationArgs: MutableMap<Any?, Any?>?, classMembersClosure: Closure<*>?) = throw NotImplementedError()
|
||||
|
||||
override fun keepdirectories() = throw NotImplementedError()
|
||||
|
||||
override fun keepdirectories(filter: String?) = throw NotImplementedError()
|
||||
|
||||
override fun dontpreverify() = throw NotImplementedError()
|
||||
|
||||
override fun dontnote() = throw NotImplementedError()
|
||||
|
||||
override fun dontnote(filter: String?) = throw NotImplementedError()
|
||||
|
||||
@Internal
|
||||
override fun getrenamesourcefileattribute(): Any? = throw NotImplementedError()
|
||||
|
||||
override fun useuniqueclassmembernames() = throw NotImplementedError()
|
||||
|
||||
override fun overloadaggressively() = throw NotImplementedError()
|
||||
|
||||
@Internal
|
||||
override fun getprintusage(): Any? = throw NotImplementedError()
|
||||
|
||||
@Internal
|
||||
override fun getforceprocessing(): Any? = throw NotImplementedError()
|
||||
|
||||
override fun whyareyoukeeping(classSpecificationString: String?) = throw NotImplementedError()
|
||||
|
||||
override fun whyareyoukeeping(classSpecificationArgs: MutableMap<Any?, Any?>?) = throw NotImplementedError()
|
||||
|
||||
override fun whyareyoukeeping(classSpecificationArgs: MutableMap<Any?, Any?>?, classMembersClosure: Closure<*>?) = throw NotImplementedError()
|
||||
|
||||
override fun obfuscationdictionary(obfuscationDictionary: Any?) = throw NotImplementedError()
|
||||
|
||||
override fun adaptclassstrings() = throw NotImplementedError()
|
||||
|
||||
override fun adaptclassstrings(filter: String?) = throw NotImplementedError()
|
||||
|
||||
override fun applymapping(applyMapping: Any?) = throw NotImplementedError()
|
||||
|
||||
override fun mergeinterfacesaggressively() = throw NotImplementedError()
|
||||
|
||||
@Internal
|
||||
override fun getdontwarn(): Any? = throw NotImplementedError()
|
||||
|
||||
override fun ignorewarnings() = throw NotImplementedError()
|
||||
|
||||
@Internal
|
||||
override fun getaddconfigurationdebugging(): Any? = throw NotImplementedError()
|
||||
|
||||
override fun field(memberSpecificationArgs: MutableMap<Any?, Any?>?) = throw NotImplementedError()
|
||||
|
||||
@Internal
|
||||
override fun getallowaccessmodification(): Any? = throw NotImplementedError()
|
||||
|
||||
override fun constructor(memberSpecificationArgs: MutableMap<Any?, Any?>?) = throw NotImplementedError()
|
||||
|
||||
override fun dontusemixedcaseclassnames() = throw NotImplementedError()
|
||||
|
||||
@Internal
|
||||
override fun getignorewarnings(): Any? = throw NotImplementedError()
|
||||
|
||||
@Internal
|
||||
override fun getkeepdirectories(): Any? = throw NotImplementedError()
|
||||
|
||||
override fun classobfuscationdictionary(classObfuscationDictionary: Any?) = throw NotImplementedError()
|
||||
|
||||
override fun verbose() = throw NotImplementedError()
|
||||
|
||||
override fun optimizations(filter: String?) = throw NotImplementedError()
|
||||
|
||||
@Internal
|
||||
override fun getuseuniqueclassmembernames(): Any? = throw NotImplementedError()
|
||||
|
||||
@Internal
|
||||
override fun getmicroedition(): Any? = throw NotImplementedError()
|
||||
|
||||
override fun assumenoescapingparameters(classSpecificationString: String?) = throw NotImplementedError()
|
||||
|
||||
override fun assumenoescapingparameters(classSpecificationArgs: MutableMap<Any?, Any?>?, classMembersClosure: Closure<*>?) = throw NotImplementedError()
|
||||
|
||||
@Internal
|
||||
override fun getandroid(): Any? = throw NotImplementedError()
|
||||
|
||||
override fun keeppackagenames() = throw NotImplementedError()
|
||||
|
||||
override fun keeppackagenames(filter: String?) = throw NotImplementedError()
|
||||
|
||||
@Internal
|
||||
override fun getoverloadaggressively(): Any? = throw NotImplementedError()
|
||||
|
||||
override fun skipnonpubliclibraryclasses() = throw NotImplementedError()
|
||||
|
||||
@Internal
|
||||
override fun getdontusemixedcaseclassnames(): Any? = throw NotImplementedError()
|
||||
|
||||
@Internal
|
||||
override fun getdontnote(): Any? = throw NotImplementedError()
|
||||
|
||||
override fun assumenoexternalreturnvalues(classSpecificationString: String?) = throw NotImplementedError()
|
||||
|
||||
override fun assumenoexternalreturnvalues(classSpecificationArgs: MutableMap<Any?, Any?>?, classMembersClosure: Closure<*>?) = throw NotImplementedError()
|
||||
|
||||
override fun target(targetClassVersion: String?) = throw NotImplementedError()
|
||||
|
||||
override fun keepattributes() = throw NotImplementedError()
|
||||
|
||||
override fun keepattributes(filter: String?) = throw NotImplementedError()
|
||||
|
||||
override fun keepclassmembernames(classSpecificationString: String?) = throw NotImplementedError()
|
||||
|
||||
override fun keepclassmembernames(keepArgs: MutableMap<Any?, Any?>?, classSpecificationString: String?) = throw NotImplementedError()
|
||||
|
||||
override fun keepclassmembernames(keepClassSpecificationArgs: MutableMap<Any?, Any?>?) = throw NotImplementedError()
|
||||
|
||||
override fun keepclassmembernames(keepClassSpecificationArgs: MutableMap<Any?, Any?>?, classMembersClosure: Closure<*>?) = throw NotImplementedError()
|
||||
|
||||
@Internal
|
||||
override fun getdontpreverify(): Any? = throw NotImplementedError()
|
||||
|
||||
@Internal
|
||||
override fun getverbose(): Any? = throw NotImplementedError()
|
||||
|
||||
@Internal
|
||||
override fun getskipnonpubliclibraryclasses(): Any? = throw NotImplementedError()
|
||||
|
||||
@Internal
|
||||
override fun getdontoptimize(): Any? = throw NotImplementedError()
|
||||
|
||||
override fun keepclasseswithmembernames(classSpecificationString: String?) = throw NotImplementedError()
|
||||
|
||||
override fun keepclasseswithmembernames(keepArgs: MutableMap<Any?, Any?>?, classSpecificationString: String?) = throw NotImplementedError()
|
||||
|
||||
override fun keepclasseswithmembernames(keepClassSpecificationArgs: MutableMap<Any?, Any?>?) = throw NotImplementedError()
|
||||
|
||||
override fun keepclasseswithmembernames(keepClassSpecificationArgs: MutableMap<Any?, Any?>?, classMembersClosure: Closure<*>?) = throw NotImplementedError()
|
||||
|
||||
override fun keepclasseswithmembers(classSpecificationString: String?) = throw NotImplementedError()
|
||||
|
||||
override fun keepclasseswithmembers(keepArgs: MutableMap<Any?, Any?>?, classSpecificationString: String?) = throw NotImplementedError()
|
||||
|
||||
override fun keepclasseswithmembers(keepClassSpecificationArgs: MutableMap<Any?, Any?>?) = throw NotImplementedError()
|
||||
|
||||
override fun keepclasseswithmembers(keepClassSpecificationArgs: MutableMap<Any?, Any?>?, classMembersClosure: Closure<*>?) = throw NotImplementedError()
|
||||
|
||||
@Internal
|
||||
override fun getdump(): Any? = throw NotImplementedError()
|
||||
|
||||
override fun printseeds() = throw NotImplementedError()
|
||||
|
||||
override fun printseeds(printSeeds: Any?) = throw NotImplementedError()
|
||||
|
||||
override fun dontoptimize() = throw NotImplementedError()
|
||||
|
||||
override fun dontobfuscate() = throw NotImplementedError()
|
||||
|
||||
override fun extendClassSpecifications(
|
||||
classSpecifications: MutableList<Any?>?,
|
||||
classSpecification: ClassSpecification?
|
||||
): MutableList<Any?> = throw NotImplementedError()
|
||||
|
||||
override fun allowaccessmodification() = throw NotImplementedError()
|
||||
|
||||
@Internal
|
||||
override fun getdontobfuscate(): Any? = throw NotImplementedError()
|
||||
|
||||
@Internal
|
||||
override fun getprintmapping(): Any? = throw NotImplementedError()
|
||||
|
||||
override fun flattenpackagehierarchy() = throw NotImplementedError()
|
||||
|
||||
override fun flattenpackagehierarchy(flattenPackageHierarchy: String?) = throw NotImplementedError()
|
||||
|
||||
override fun android() = throw NotImplementedError()
|
||||
|
||||
override fun dump() = throw NotImplementedError()
|
||||
|
||||
override fun dump(dump: Any?) = throw NotImplementedError()
|
||||
|
||||
@Internal
|
||||
override fun getdontshrink(): Any? = throw NotImplementedError()
|
||||
|
||||
@Internal
|
||||
override fun getkeepattributes(): Any? = throw NotImplementedError()
|
||||
|
||||
override fun microedition() = throw NotImplementedError()
|
||||
|
||||
override fun keepparameternames() = throw NotImplementedError()
|
||||
|
||||
override fun addconfigurationdebugging() = throw NotImplementedError()
|
||||
|
||||
override fun packageobfuscationdictionary(packageObfuscationDictionary: Any?) = throw NotImplementedError()
|
||||
|
||||
@Internal
|
||||
override fun getdontskipnonpubliclibraryclassmembers(): Any? = throw NotImplementedError()
|
||||
|
||||
override fun dontskipnonpubliclibraryclassmembers() = throw NotImplementedError()
|
||||
|
||||
@Internal
|
||||
override fun getprintconfiguration(): Any? = throw NotImplementedError()
|
||||
|
||||
override fun forceprocessing() = throw NotImplementedError()
|
||||
|
||||
override fun keepclassmembers(classSpecificationString: String?) = throw NotImplementedError()
|
||||
|
||||
override fun keepclassmembers(keepArgs: MutableMap<Any?, Any?>?, classSpecificationString: String?) = throw NotImplementedError()
|
||||
|
||||
override fun keepclassmembers(keepClassSpecificationArgs: MutableMap<Any?, Any?>?) = throw NotImplementedError()
|
||||
|
||||
override fun keepclassmembers(keepClassSpecificationArgs: MutableMap<Any?, Any?>?, classMembersClosure: Closure<*>?) = throw NotImplementedError()
|
||||
|
||||
@Internal
|
||||
override fun getmergeinterfacesaggressively(): Any? = throw NotImplementedError()
|
||||
|
||||
@Internal
|
||||
override fun getConfigurationFiles(): MutableList<Any?> = throw NotImplementedError()
|
||||
|
||||
@Internal
|
||||
override fun getkeeppackagenames(): Any? = throw NotImplementedError()
|
||||
|
||||
override fun assumevalues(classSpecificationString: String?) = throw NotImplementedError()
|
||||
|
||||
override fun assumevalues(classSpecificationArgs: MutableMap<Any?, Any?>?, classMembersClosure: Closure<*>?) = throw NotImplementedError()
|
||||
|
||||
override fun printusage() = throw NotImplementedError()
|
||||
|
||||
override fun printusage(printUsage: Any?) = throw NotImplementedError()
|
||||
|
||||
@Internal
|
||||
override fun getprintseeds(): Any? = throw NotImplementedError()
|
||||
|
||||
@Internal
|
||||
override fun getadaptresourcefilenames(): Any? = throw NotImplementedError()
|
||||
|
||||
override fun assumenoexternalsideeffects(classSpecificationString: String?) = throw NotImplementedError()
|
||||
|
||||
override fun assumenoexternalsideeffects(classSpecificationArgs: MutableMap<Any?, Any?>?, classMembersClosure: Closure<*>?) = throw NotImplementedError()
|
||||
|
||||
override fun dontwarn() = throw NotImplementedError()
|
||||
|
||||
override fun dontwarn(filter: String?) = throw NotImplementedError()
|
||||
|
||||
@Internal
|
||||
override fun getrepackageclasses(): Any? = throw NotImplementedError()
|
||||
|
||||
@Internal
|
||||
override fun getadaptresourcefilecontents(): Any? = throw NotImplementedError()
|
||||
|
||||
@Internal
|
||||
override fun getflattenpackagehierarchy(): Any? = throw NotImplementedError()
|
||||
|
||||
override fun optimizationpasses(optimizationPasses: Int) = throw NotImplementedError()
|
||||
|
||||
override fun adaptresourcefilenames() = throw NotImplementedError()
|
||||
|
||||
override fun adaptresourcefilenames(filter: String?) = throw NotImplementedError()
|
||||
|
||||
override fun method(memberSpecificationArgs: MutableMap<Any?, Any?>?) = throw NotImplementedError()
|
||||
|
||||
@Internal
|
||||
override fun getadaptclassstrings(): Any? = throw NotImplementedError()
|
||||
|
||||
override fun repackageclasses() = throw NotImplementedError()
|
||||
|
||||
override fun repackageclasses(repackageClasses: String?) = throw NotImplementedError()
|
||||
|
||||
@Internal
|
||||
override fun getkeepparameternames(): Any? = throw NotImplementedError()
|
||||
|
||||
override fun adaptresourcefilecontents() = throw NotImplementedError()
|
||||
|
||||
override fun adaptresourcefilecontents(filter: String?) = throw NotImplementedError()
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
// usages in build scripts are not tracked properly
|
||||
@file:Suppress("unused")
|
||||
|
||||
import groovy.lang.Closure
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.file.CopySourceSpec
|
||||
import org.gradle.api.file.SourceDirectorySet
|
||||
import org.gradle.api.plugins.JavaPluginExtension
|
||||
import org.gradle.api.tasks.JavaExec
|
||||
import org.gradle.api.tasks.SourceSet
|
||||
import org.gradle.api.tasks.SourceSetOutput
|
||||
import org.gradle.api.tasks.bundling.AbstractArchiveTask
|
||||
import org.gradle.kotlin.dsl.*
|
||||
import proguard.gradle.ProGuardTask
|
||||
import java.io.File
|
||||
import java.util.*
|
||||
import java.util.concurrent.Callable
|
||||
|
||||
inline fun <reified T : Task> Project.task(noinline configuration: T.() -> Unit) = tasks.registering(T::class, configuration)
|
||||
|
||||
inline fun <reified T : Task> Project.eagerTask(noinline configuration: T.() -> Unit) = tasks.creating(T::class, configuration)
|
||||
|
||||
fun Project.callGroovy(name: String, vararg args: Any?): Any? {
|
||||
return (property(name) as Closure<*>).call(*args)
|
||||
}
|
||||
|
||||
inline fun <T : Any> Project.withJavaPlugin(crossinline body: () -> T?): T? {
|
||||
var res: T? = null
|
||||
pluginManager.withPlugin("java") {
|
||||
res = body()
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
fun Project.getCompiledClasses(): SourceSetOutput? = withJavaPlugin { mainSourceSet.output }
|
||||
|
||||
fun Project.getSources(): SourceDirectorySet? = withJavaPlugin { mainSourceSet.allSource }
|
||||
|
||||
fun Project.getResourceFiles(): SourceDirectorySet? = withJavaPlugin { mainSourceSet.resources }
|
||||
|
||||
fun fileFrom(root: File, vararg children: String): File = children.fold(root) { f, c -> File(f, c) }
|
||||
|
||||
fun fileFrom(root: String, vararg children: String): File = children.fold(File(root)) { f, c -> File(f, c) }
|
||||
|
||||
var Project.jvmTarget: String?
|
||||
get() = extra.takeIf { it.has("jvmTarget") }?.get("jvmTarget") as? String
|
||||
set(v) {
|
||||
extra["jvmTarget"] = v
|
||||
}
|
||||
|
||||
var Project.javaHome: String?
|
||||
get() = extra.takeIf { it.has("javaHome") }?.get("javaHome") as? String
|
||||
set(v) {
|
||||
extra["javaHome"] = v
|
||||
}
|
||||
|
||||
fun Project.generator(fqName: String, sourceSet: SourceSet? = null, configure: JavaExec.() -> Unit = {}) = smartJavaExec {
|
||||
group = "Generate"
|
||||
classpath = (sourceSet ?: testSourceSet).runtimeClasspath
|
||||
mainClass.set(fqName)
|
||||
workingDir = rootDir
|
||||
systemProperty("line.separator", "\n")
|
||||
systemProperty("idea.ignore.disabled.plugins", "true")
|
||||
configure()
|
||||
}
|
||||
|
||||
fun Project.getBooleanProperty(name: String): Boolean? = this.findProperty(name)?.let {
|
||||
val v = it.toString()
|
||||
if (v.isBlank()) true
|
||||
else v.toBoolean()
|
||||
}
|
||||
|
||||
inline fun CopySourceSpec.from(crossinline filesProvider: () -> Any?): CopySourceSpec = from(Callable { filesProvider() })
|
||||
|
||||
fun Project.javaPluginExtension(): JavaPluginExtension = extensions.getByType()
|
||||
|
||||
fun Project.findJavaPluginExtension(): JavaPluginExtension? = extensions.findByType()
|
||||
|
||||
fun JavaExec.pathRelativeToWorkingDir(file: File): String = file.relativeTo(workingDir).invariantSeparatorsPath
|
||||
|
||||
fun Task.singleOutputFile(): File = when (this) {
|
||||
is AbstractArchiveTask -> archiveFile.get().asFile
|
||||
is ProGuardTask -> project.file(outJarFiles.single()!!)
|
||||
else -> outputs.files.singleFile
|
||||
}
|
||||
|
||||
val Project.isConfigurationCacheDisabled
|
||||
get() = (gradle.startParameter as? org.gradle.api.internal.StartParameterInternal)?.configurationCache?.get() != true
|
||||
|
||||
val Project.isIdeaActive
|
||||
get() = providers.systemProperty("idea.active").isPresent
|
||||
|
||||
val Project.intellijCommunityDir: File
|
||||
get() = rootDir.resolve("intellij/community").takeIf { it.isDirectory } ?: rootDir.resolve("intellij")
|
||||
|
||||
fun String.capitalize(): String = capitalize(Locale.ROOT)
|
||||
|
||||
fun String.capitalize(locale: Locale): String = replaceFirstChar { if (it.isLowerCase()) it.titlecase(locale) else it.toString() }
|
||||
@@ -0,0 +1,754 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
import org.gradle.api.Action
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.artifacts.ModuleDependency
|
||||
import org.gradle.api.artifacts.type.ArtifactTypeDefinition
|
||||
import org.gradle.api.attributes.*
|
||||
import org.gradle.api.attributes.java.TargetJvmEnvironment
|
||||
import org.gradle.api.attributes.java.TargetJvmVersion
|
||||
import org.gradle.api.attributes.plugin.GradlePluginApiVersion
|
||||
import org.gradle.api.component.AdhocComponentWithVariants
|
||||
import org.gradle.api.plugins.JavaLibraryPlugin
|
||||
import org.gradle.api.plugins.JavaPlugin
|
||||
import org.gradle.api.plugins.JavaPluginExtension
|
||||
import org.gradle.api.publish.PublishingExtension
|
||||
import org.gradle.api.publish.maven.MavenPublication
|
||||
import org.gradle.api.tasks.Copy
|
||||
import org.gradle.api.tasks.SourceSet
|
||||
import org.gradle.api.tasks.compile.JavaCompile
|
||||
import org.gradle.jvm.tasks.Jar
|
||||
import org.gradle.kotlin.dsl.*
|
||||
import org.gradle.plugin.devel.plugins.JavaGradlePluginPlugin
|
||||
import org.jetbrains.dokka.DokkaVersion
|
||||
import org.jetbrains.dokka.gradle.DokkaTask
|
||||
import org.jetbrains.dokka.gradle.GradleExternalDocumentationLinkBuilder
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinSingleJavaTargetExtension
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinVersion
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
import plugins.configureDefaultPublishing
|
||||
import plugins.configureKotlinPomAttributes
|
||||
import java.net.URL
|
||||
|
||||
/**
|
||||
* Gradle's plugins common variants.
|
||||
*
|
||||
* [minimalSupportedGradleVersion] - minimal Gradle version that is supported in this variant
|
||||
* [gradleApiVersion] - Gradle API dependency version. Usually should be the same as [minimalSupportedGradleVersion].
|
||||
*/
|
||||
enum class GradlePluginVariant(
|
||||
val sourceSetName: String,
|
||||
val minimalSupportedGradleVersion: String,
|
||||
val gradleApiVersion: String,
|
||||
val gradleApiJavadocUrl: String
|
||||
) {
|
||||
GRADLE_MIN("main", "6.8.3", "6.9", "https://docs.gradle.org/6.9.3/javadoc/"),
|
||||
GRADLE_70("gradle70", "7.0", "7.0", "https://docs.gradle.org/7.0.2/javadoc/"),
|
||||
GRADLE_71("gradle71", "7.1", "7.1", "https://docs.gradle.org/7.1.1/javadoc/"),
|
||||
GRADLE_74("gradle74", "7.4", "7.4", "https://docs.gradle.org/7.4.2/javadoc/"),
|
||||
GRADLE_75("gradle75", "7.5", "7.5", "https://docs.gradle.org/7.5.1/javadoc/"),
|
||||
GRADLE_76("gradle76", "7.6", "7.6", "https://docs.gradle.org/7.6.1/javadoc/"),
|
||||
GRADLE_80("gradle80", "8.0", "8.0", "https://docs.gradle.org/8.0.2/javadoc/"),
|
||||
GRADLE_81("gradle81", "8.1", "8.1", "https://docs.gradle.org/8.1.1/javadoc/"),
|
||||
}
|
||||
|
||||
val commonSourceSetName = "common"
|
||||
|
||||
/**
|
||||
* Configures common pom configuration parameters
|
||||
*/
|
||||
fun Project.configureCommonPublicationSettingsForGradle(
|
||||
signingRequired: Boolean,
|
||||
) {
|
||||
plugins.withId("maven-publish") {
|
||||
configureDefaultPublishing(signingRequired)
|
||||
|
||||
extensions.configure<PublishingExtension> {
|
||||
publications
|
||||
.withType<MavenPublication>()
|
||||
.configureEach {
|
||||
configureKotlinPomAttributes(project)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* These dependencies will be provided by Gradle, and we should prevent version conflict
|
||||
*/
|
||||
fun Configuration.excludeGradleCommonDependencies() {
|
||||
dependencies
|
||||
.withType<ModuleDependency>()
|
||||
.configureEach {
|
||||
exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib")
|
||||
exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib-jdk7")
|
||||
exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib-jdk8")
|
||||
exclude(group = "org.jetbrains.kotlin", module = "kotlin-stdlib-common")
|
||||
exclude(group = "org.jetbrains.kotlin", module = "kotlin-reflect")
|
||||
exclude(group = "org.jetbrains.kotlin", module = "kotlin-script-runtime")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Exclude Gradle runtime from given SourceSet configurations.
|
||||
*/
|
||||
fun Project.excludeGradleCommonDependencies(sourceSet: SourceSet) {
|
||||
configurations[sourceSet.implementationConfigurationName].excludeGradleCommonDependencies()
|
||||
configurations[sourceSet.apiConfigurationName].excludeGradleCommonDependencies()
|
||||
configurations[sourceSet.runtimeOnlyConfigurationName].excludeGradleCommonDependencies()
|
||||
}
|
||||
|
||||
private val testPlugins = setOf(
|
||||
"kotlin-gradle-plugin-api",
|
||||
"android-test-fixes",
|
||||
"gradle-warnings-detector",
|
||||
"kotlin-compiler-args-properties",
|
||||
"kotlin-gradle-plugin",
|
||||
)
|
||||
|
||||
/**
|
||||
* Common sources for all variants.
|
||||
* Should contain classes that are independent of Gradle API version or using minimal supported Gradle api.
|
||||
*/
|
||||
fun Project.createGradleCommonSourceSet(): SourceSet {
|
||||
val commonSourceSet = sourceSets.create(commonSourceSetName) {
|
||||
excludeGradleCommonDependencies(this)
|
||||
|
||||
// Adding Gradle API to separate configuration, so version will not leak into variants
|
||||
val commonGradleApiConfiguration = configurations.create("commonGradleApiCompileOnly") {
|
||||
isVisible = false
|
||||
isCanBeConsumed = false
|
||||
isCanBeResolved = true
|
||||
}
|
||||
configurations[compileClasspathConfigurationName].extendsFrom(commonGradleApiConfiguration)
|
||||
|
||||
dependencies {
|
||||
compileOnlyConfigurationName(kotlinStdlib())
|
||||
"commonGradleApiCompileOnly"("dev.gradleplugins:gradle-api:8.1")
|
||||
if (this@createGradleCommonSourceSet.name !in testPlugins) {
|
||||
compileOnlyConfigurationName(project(":kotlin-gradle-plugin-api")) {
|
||||
capabilities {
|
||||
requireCapability("org.jetbrains.kotlin:kotlin-gradle-plugin-api-common")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
plugins.withType<JavaLibraryPlugin>().configureEach {
|
||||
this@createGradleCommonSourceSet.extensions.configure<JavaPluginExtension> {
|
||||
registerFeature(commonSourceSet.name) {
|
||||
usingSourceSet(commonSourceSet)
|
||||
disablePublication()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Common outputs will also produce '${project.name}.kotlin_module' file, so we need to avoid
|
||||
// files clash
|
||||
tasks.named<KotlinCompile>("compile${commonSourceSet.name.replaceFirstChar { it.uppercase() }}Kotlin") {
|
||||
@Suppress("DEPRECATION")
|
||||
kotlinOptions {
|
||||
moduleName = "${this@createGradleCommonSourceSet.name}_${commonSourceSet.name}"
|
||||
}
|
||||
}
|
||||
|
||||
return commonSourceSet
|
||||
}
|
||||
|
||||
/**
|
||||
* Fixes wired SourceSet does not expose compiled common classes and common resources as secondary variant
|
||||
* which is used in the Kotlin Project compilation.
|
||||
*/
|
||||
private fun Project.fixWiredSourceSetSecondaryVariants(
|
||||
wireSourceSet: SourceSet,
|
||||
commonSourceSet: SourceSet,
|
||||
) {
|
||||
configurations
|
||||
.matching {
|
||||
it.name == wireSourceSet.apiElementsConfigurationName ||
|
||||
it.name == wireSourceSet.runtimeElementsConfigurationName
|
||||
}
|
||||
.configureEach {
|
||||
outgoing {
|
||||
variants.maybeCreate("classes").apply {
|
||||
attributes {
|
||||
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements.CLASSES))
|
||||
}
|
||||
(commonSourceSet.output.classesDirs.files + wireSourceSet.output.classesDirs.files)
|
||||
.toSet()
|
||||
.forEach {
|
||||
if (!artifacts.files.contains(it)) {
|
||||
artifact(it) {
|
||||
type = ArtifactTypeDefinition.JVM_CLASS_DIRECTORY
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
configurations
|
||||
.matching { it.name == wireSourceSet.runtimeElementsConfigurationName }
|
||||
.configureEach {
|
||||
outgoing {
|
||||
val resourcesDirectories = listOfNotNull(
|
||||
commonSourceSet.output.resourcesDir,
|
||||
wireSourceSet.output.resourcesDir
|
||||
)
|
||||
|
||||
if (resourcesDirectories.isNotEmpty()) {
|
||||
variants.maybeCreate("resources").apply {
|
||||
attributes {
|
||||
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements.RESOURCES))
|
||||
}
|
||||
resourcesDirectories.forEach {
|
||||
if (!artifacts.files.contains(it)) {
|
||||
artifact(it) {
|
||||
type = ArtifactTypeDefinition.JVM_RESOURCES_DIRECTORY
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Make [wireSourceSet] to extend [commonSourceSet].
|
||||
*/
|
||||
fun Project.wireGradleVariantToCommonGradleVariant(
|
||||
wireSourceSet: SourceSet,
|
||||
commonSourceSet: SourceSet,
|
||||
) {
|
||||
wireSourceSet.compileClasspath += commonSourceSet.output
|
||||
wireSourceSet.runtimeClasspath += commonSourceSet.output
|
||||
|
||||
// Allowing to use 'internal' classes/methods from common source code
|
||||
(extensions.getByName("kotlin") as KotlinSingleJavaTargetExtension).target.compilations.run {
|
||||
getByName(wireSourceSet.name).associateWith(getByName(commonSourceSet.name))
|
||||
}
|
||||
|
||||
configurations[wireSourceSet.apiConfigurationName].extendsFrom(
|
||||
configurations[commonSourceSet.apiConfigurationName]
|
||||
)
|
||||
configurations[wireSourceSet.implementationConfigurationName].extendsFrom(
|
||||
configurations[commonSourceSet.implementationConfigurationName]
|
||||
)
|
||||
configurations[wireSourceSet.runtimeOnlyConfigurationName].extendsFrom(
|
||||
configurations[commonSourceSet.runtimeOnlyConfigurationName]
|
||||
)
|
||||
configurations[wireSourceSet.compileOnlyConfigurationName].extendsFrom(
|
||||
configurations[commonSourceSet.compileOnlyConfigurationName]
|
||||
)
|
||||
|
||||
fixWiredSourceSetSecondaryVariants(wireSourceSet, commonSourceSet)
|
||||
|
||||
tasks.withType<Jar>().configureEach {
|
||||
if (name == wireSourceSet.jarTaskName) {
|
||||
from(wireSourceSet.output, commonSourceSet.output)
|
||||
setupPublicJar(archiveBaseName.get())
|
||||
addEmbeddedRuntime()
|
||||
addEmbeddedRuntime(wireSourceSet.embeddedConfigurationName)
|
||||
} else if (name == wireSourceSet.sourcesJarTaskName) {
|
||||
from(wireSourceSet.allSource, commonSourceSet.allSource)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private const val FIXED_CONFIGURATION_SUFFIX = "WithFixedAttribute"
|
||||
|
||||
/**
|
||||
* 'main' sources are used for minimal supported Gradle versions (6.7) up to Gradle 7.0.
|
||||
*/
|
||||
fun Project.reconfigureMainSourcesSetForGradlePlugin(
|
||||
commonSourceSet: SourceSet,
|
||||
) {
|
||||
sourceSets.named(SourceSet.MAIN_SOURCE_SET_NAME) {
|
||||
plugins.withType<JavaGradlePluginPlugin>().configureEach {
|
||||
// Removing Gradle api default dependency added by 'java-gradle-plugin'
|
||||
configurations[apiConfigurationName].dependencies.remove(dependencies.gradleApi())
|
||||
}
|
||||
|
||||
dependencies {
|
||||
"compileOnly"(kotlinStdlib())
|
||||
// Decoupling gradle-api artifact from current project Gradle version. Later would be useful for
|
||||
// gradle plugin variants
|
||||
"compileOnly"("dev.gradleplugins:gradle-api:${GradlePluginVariant.GRADLE_MIN.gradleApiVersion}")
|
||||
if (this@reconfigureMainSourcesSetForGradlePlugin.name !in testPlugins) {
|
||||
"api"(project(":kotlin-gradle-plugin-api"))
|
||||
}
|
||||
}
|
||||
|
||||
excludeGradleCommonDependencies(this)
|
||||
wireGradleVariantToCommonGradleVariant(this, commonSourceSet)
|
||||
|
||||
// https://youtrack.jetbrains.com/issue/KT-51913
|
||||
// Remove workaround after bootstrap update
|
||||
if (configurations["default"].attributes.contains(TargetJvmEnvironment.TARGET_JVM_ENVIRONMENT_ATTRIBUTE)) {
|
||||
configurations["default"].attributes.attribute(
|
||||
TargetJvmEnvironment.TARGET_JVM_ENVIRONMENT_ATTRIBUTE,
|
||||
objects.named(TargetJvmEnvironment::class, "no-op")
|
||||
)
|
||||
}
|
||||
|
||||
plugins.withType<JavaLibraryPlugin>().configureEach {
|
||||
this@reconfigureMainSourcesSetForGradlePlugin
|
||||
.extensions
|
||||
.configure<JavaPluginExtension> {
|
||||
withSourcesJar()
|
||||
if (kotlinBuildProperties.publishGradlePluginsJavadoc) {
|
||||
withJavadocJar()
|
||||
}
|
||||
}
|
||||
|
||||
configurations.create(sourceSets.getByName("main").embeddedConfigurationName) {
|
||||
isCanBeConsumed = false
|
||||
isCanBeResolved = true
|
||||
attributes {
|
||||
attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME))
|
||||
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements.JAR))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Workaround for https://youtrack.jetbrains.com/issue/KT-52987
|
||||
val javaComponent = project.components["java"] as AdhocComponentWithVariants
|
||||
listOf(
|
||||
runtimeElementsConfigurationName,
|
||||
apiElementsConfigurationName
|
||||
)
|
||||
.map { configurations[it] }
|
||||
.forEach { originalConfiguration ->
|
||||
configurations.create("${originalConfiguration.name}$FIXED_CONFIGURATION_SUFFIX") {
|
||||
isCanBeResolved = originalConfiguration.isCanBeResolved
|
||||
isCanBeConsumed = originalConfiguration.isCanBeConsumed
|
||||
isVisible = originalConfiguration.isVisible
|
||||
setExtendsFrom(originalConfiguration.extendsFrom)
|
||||
|
||||
artifacts {
|
||||
originalConfiguration.artifacts.forEach {
|
||||
add(name, it)
|
||||
}
|
||||
}
|
||||
|
||||
// Removing 'org.jetbrains.kotlin.platform.type' attribute
|
||||
// as it brings issues with Gradle variant resolve on Gradle 7.6+ versions
|
||||
attributes {
|
||||
originalConfiguration.attributes.keySet()
|
||||
.filter { it.name != KotlinPlatformType.attribute.name }
|
||||
.forEach { originalAttribute ->
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
attribute(
|
||||
originalAttribute as Attribute<Any>,
|
||||
originalConfiguration.attributes.getAttribute(originalAttribute)!!
|
||||
)
|
||||
}
|
||||
|
||||
plugins.withType<JavaPlugin> {
|
||||
tasks.named<JavaCompile>(compileJavaTaskName).get().apply {
|
||||
attribute(
|
||||
TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE,
|
||||
when (targetCompatibility) {
|
||||
"1.8" -> 8
|
||||
else -> targetCompatibility.toInt()
|
||||
}
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val expectedAttributes = setOf(
|
||||
Category.CATEGORY_ATTRIBUTE,
|
||||
Bundling.BUNDLING_ATTRIBUTE,
|
||||
Usage.USAGE_ATTRIBUTE,
|
||||
LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE,
|
||||
TargetJvmEnvironment.TARGET_JVM_ENVIRONMENT_ATTRIBUTE,
|
||||
TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE
|
||||
)
|
||||
if (attributes.keySet() != expectedAttributes) {
|
||||
error(
|
||||
"Wrong set of attributes:\n" +
|
||||
" Expected: ${expectedAttributes.joinToString(", ")}\n" +
|
||||
" Actual: ${attributes.keySet().joinToString(", ") { "${it.name}=${attributes.getAttribute(it)}" }}"
|
||||
)
|
||||
}
|
||||
|
||||
javaComponent.addVariantsFromConfiguration(this) {
|
||||
mapToMavenScope(
|
||||
when (originalConfiguration.name) {
|
||||
runtimeElementsConfigurationName -> "runtime"
|
||||
apiElementsConfigurationName -> "compile"
|
||||
else -> error("Unsupported configuration name")
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
// Make original configuration unpublishable and not visible
|
||||
originalConfiguration.isCanBeConsumed = false
|
||||
originalConfiguration.isVisible = false
|
||||
javaComponent.withVariantsFromConfiguration(originalConfiguration) {
|
||||
skip()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fix common sources visibility for tests
|
||||
sourceSets.named(SourceSet.TEST_SOURCE_SET_NAME) {
|
||||
compileClasspath += commonSourceSet.output
|
||||
runtimeClasspath += commonSourceSet.output
|
||||
}
|
||||
|
||||
// Allowing to use 'internal' classes/methods from common source code
|
||||
(extensions.getByName("kotlin") as KotlinSingleJavaTargetExtension).target.compilations.run {
|
||||
getByName(SourceSet.TEST_SOURCE_SET_NAME).associateWith(getByName(commonSourceSet.name))
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adding plugin variants: https://docs.gradle.org/current/userguide/implementing_gradle_plugins.html#plugin-with-variants
|
||||
*/
|
||||
fun Project.createGradlePluginVariant(
|
||||
variant: GradlePluginVariant,
|
||||
commonSourceSet: SourceSet,
|
||||
isGradlePlugin: Boolean = true,
|
||||
): SourceSet {
|
||||
val variantSourceSet = sourceSets.create(variant.sourceSetName) {
|
||||
excludeGradleCommonDependencies(this)
|
||||
wireGradleVariantToCommonGradleVariant(this, commonSourceSet)
|
||||
}
|
||||
|
||||
plugins.withType<JavaLibraryPlugin>().configureEach {
|
||||
extensions.configure<JavaPluginExtension> {
|
||||
registerFeature(variantSourceSet.name) {
|
||||
usingSourceSet(variantSourceSet)
|
||||
if (isGradlePlugin) {
|
||||
capability(project.group.toString(), project.name, project.version.toString())
|
||||
}
|
||||
|
||||
if (kotlinBuildProperties.publishGradlePluginsJavadoc) {
|
||||
withJavadocJar()
|
||||
}
|
||||
withSourcesJar()
|
||||
}
|
||||
|
||||
configurations.named(variantSourceSet.apiElementsConfigurationName, commonVariantAttributes())
|
||||
configurations.named(variantSourceSet.runtimeElementsConfigurationName, commonVariantAttributes())
|
||||
|
||||
configurations.create(variantSourceSet.embeddedConfigurationName) {
|
||||
isCanBeConsumed = false
|
||||
isCanBeResolved = true
|
||||
attributes {
|
||||
attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME))
|
||||
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements.JAR))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.named<Jar>(variantSourceSet.sourcesJarTaskName) {
|
||||
addEmbeddedSources()
|
||||
addEmbeddedSources(variantSourceSet.embeddedConfigurationName)
|
||||
}
|
||||
}
|
||||
|
||||
plugins.withId("java-gradle-plugin") {
|
||||
tasks.named<Copy>(variantSourceSet.processResourcesTaskName) {
|
||||
val copyPluginDescriptors = rootSpec.addChild()
|
||||
copyPluginDescriptors.into("META-INF/gradle-plugins")
|
||||
copyPluginDescriptors.from(tasks.named("pluginDescriptors"))
|
||||
}
|
||||
}
|
||||
|
||||
configurations.configureEach {
|
||||
if (this@configureEach.name.startsWith(variantSourceSet.name)) {
|
||||
attributes {
|
||||
attribute(
|
||||
GradlePluginApiVersion.GRADLE_PLUGIN_API_VERSION_ATTRIBUTE,
|
||||
objects.named(variant.minimalSupportedGradleVersion)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// KT-52138: Make module name the same for all variants, so KSP could access internal methods/properties
|
||||
tasks.named<KotlinCompile>("compile${variantSourceSet.name.replaceFirstChar { it.uppercase() }}Kotlin") {
|
||||
@Suppress("DEPRECATION")
|
||||
kotlinOptions {
|
||||
moduleName = this@createGradlePluginVariant.name
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
variantSourceSet.compileOnlyConfigurationName(kotlinStdlib())
|
||||
variantSourceSet.compileOnlyConfigurationName("dev.gradleplugins:gradle-api:${variant.gradleApiVersion}")
|
||||
if (this@createGradlePluginVariant.name !in testPlugins) {
|
||||
variantSourceSet.apiConfigurationName(project(":kotlin-gradle-plugin-api")) {
|
||||
capabilities {
|
||||
requireCapability("org.jetbrains.kotlin:kotlin-gradle-plugin-api-${variant.sourceSetName}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return variantSourceSet
|
||||
}
|
||||
|
||||
/**
|
||||
* All additional configuration attributes in plugin variant should be the same as in the 'main' variant.
|
||||
* Otherwise, Gradle <7.0 will fail to select plugin variant.
|
||||
*/
|
||||
private fun Project.commonVariantAttributes(): Action<Configuration> = Action<Configuration> {
|
||||
attributes {
|
||||
attribute(
|
||||
TargetJvmEnvironment.TARGET_JVM_ENVIRONMENT_ATTRIBUTE,
|
||||
objects.named(TargetJvmEnvironment.STANDARD_JVM)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.configureKotlinCompileTasksGradleCompatibility() {
|
||||
tasks.withType<KotlinCompile>().configureEach {
|
||||
compilerOptions {
|
||||
// check https://docs.gradle.org/current/userguide/compatibility.html#kotlin for Kotlin-Gradle versions matrix
|
||||
@Suppress("DEPRECATION") // we can't use language version greater than 1.5 as minimal supported Gradle embeds Kotlin 1.4
|
||||
languageVersion.set(KotlinVersion.KOTLIN_1_5)
|
||||
@Suppress("DEPRECATION") // we can't use api version greater than 1.4 as minimal supported Gradle version uses kotlin-stdlib 1.4
|
||||
apiVersion.set(KotlinVersion.KOTLIN_1_4)
|
||||
freeCompilerArgs.addAll(
|
||||
listOf(
|
||||
"-Xskip-prerelease-check",
|
||||
"-Xsuppress-version-warnings",
|
||||
// We have to override the default value for `-Xsam-conversions` to `class`
|
||||
// otherwise the compiler would compile lambdas using invokedynamic,
|
||||
// such lambdas are not serializable so are not compatible with Gradle configuration cache.
|
||||
// It doesn't lead to a significant difference in binaries sizes, and previously (before LV 1.5) the `class` value was set by default.
|
||||
"-Xsam-conversions=class",
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Will allow combining outputs of multiple SourceSets
|
||||
fun Project.publishShadowedJar(
|
||||
sourceSet: SourceSet,
|
||||
commonSourceSet: SourceSet,
|
||||
) {
|
||||
val jarTask = tasks.named<Jar>(sourceSet.jarTaskName)
|
||||
|
||||
val shadowJarTask = embeddableCompilerDummyForDependenciesRewriting(
|
||||
taskName = "$EMBEDDABLE_COMPILER_TASK_NAME${sourceSet.jarTaskName.replaceFirstChar { it.uppercase() }}"
|
||||
) {
|
||||
setupPublicJar(
|
||||
jarTask.flatMap { it.archiveBaseName },
|
||||
jarTask.flatMap { it.archiveClassifier }
|
||||
)
|
||||
addEmbeddedRuntime()
|
||||
addEmbeddedRuntime(sourceSet.embeddedConfigurationName)
|
||||
from(sourceSet.output)
|
||||
from(commonSourceSet.output)
|
||||
|
||||
// When Gradle traverses the inputs, reject the shaded compiler JAR,
|
||||
// which leads to the content of that JAR being excluded as well:
|
||||
exclude {
|
||||
// Docstring says `file` never returns null, but it does
|
||||
@Suppress("UNNECESSARY_SAFE_CALL", "SAFE_CALL_WILL_CHANGE_NULLABILITY")
|
||||
it.file?.name?.startsWith("kotlin-compiler-embeddable") ?: false
|
||||
}
|
||||
}
|
||||
|
||||
// Removing artifact produced by Jar task
|
||||
if (sourceSet.name == SourceSet.MAIN_SOURCE_SET_NAME) {
|
||||
configurations["${sourceSet.runtimeElementsConfigurationName}$FIXED_CONFIGURATION_SUFFIX"]
|
||||
.artifacts.removeAll { true }
|
||||
configurations["${sourceSet.apiElementsConfigurationName}$FIXED_CONFIGURATION_SUFFIX"]
|
||||
.artifacts.removeAll { true }
|
||||
} else {
|
||||
configurations[sourceSet.runtimeElementsConfigurationName]
|
||||
.artifacts.removeAll { true }
|
||||
configurations[sourceSet.apiElementsConfigurationName]
|
||||
.artifacts.removeAll { true }
|
||||
}
|
||||
|
||||
// Adding instead artifact from shadow jar task
|
||||
configurations {
|
||||
artifacts {
|
||||
if (sourceSet.name == SourceSet.MAIN_SOURCE_SET_NAME) {
|
||||
add("${sourceSet.runtimeElementsConfigurationName}$FIXED_CONFIGURATION_SUFFIX", shadowJarTask)
|
||||
add("${sourceSet.apiElementsConfigurationName}$FIXED_CONFIGURATION_SUFFIX", shadowJarTask)
|
||||
} else {
|
||||
add(sourceSet.apiElementsConfigurationName, shadowJarTask)
|
||||
add(sourceSet.runtimeElementsConfigurationName, shadowJarTask)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.addBomCheckTask() {
|
||||
val checkBomTask = tasks.register("checkGradlePluginsBom") {
|
||||
group = "Validation"
|
||||
description = "Check if project is added into Kotlin Gradle Plugins bom"
|
||||
|
||||
val bomBuildFile = project(":kotlin-gradle-plugins-bom").projectDir.resolve("build.gradle.kts")
|
||||
val exceptions = listOf(
|
||||
project(":gradle:android-test-fixes").path,
|
||||
project(":gradle:gradle-warnings-detector").path,
|
||||
project(":gradle:kotlin-compiler-args-properties").path,
|
||||
project(":kotlin-gradle-build-metrics").path,
|
||||
project(":kotlin-gradle-statistics").path,
|
||||
)
|
||||
val projectPath = this@addBomCheckTask.path
|
||||
|
||||
doLast {
|
||||
if (projectPath in exceptions) return@doLast
|
||||
|
||||
val constraintsLines = bomBuildFile.readText()
|
||||
.substringAfter("constraints {")
|
||||
.substringBefore("}")
|
||||
.split("\n")
|
||||
.map { it.trim() }
|
||||
|
||||
val isContainingThisProject = constraintsLines.contains(
|
||||
"api(project(\"$projectPath\"))"
|
||||
)
|
||||
|
||||
if (!isContainingThisProject) {
|
||||
throw GradleException(":kotlin-gradle-plugins-bom does not contain $projectPath project constraint!")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.named("check") {
|
||||
dependsOn(checkBomTask)
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.configureDokkaPublication(
|
||||
shouldLinkGradleApi: Boolean = false,
|
||||
configurePublishingToKotlinlang: Boolean = false,
|
||||
) {
|
||||
|
||||
val dokkaVersioningPluginVersion = "1.8.10"
|
||||
|
||||
dependencies {
|
||||
implicitDependencies("org.jetbrains.dokka:javadoc-plugin:${DokkaVersion.version}")
|
||||
implicitDependencies("org.jetbrains.dokka:versioning-plugin:$dokkaVersioningPluginVersion")
|
||||
}
|
||||
|
||||
if (!kotlinBuildProperties.publishGradlePluginsJavadoc) return
|
||||
|
||||
plugins.apply("org.jetbrains.dokka")
|
||||
plugins.withId("org.jetbrains.dokka") {
|
||||
val commonSourceSet = sourceSets.getByName(commonSourceSetName)
|
||||
|
||||
GradlePluginVariant.values().forEach { pluginVariant ->
|
||||
val variantSourceSet = sourceSets.getByName(pluginVariant.sourceSetName)
|
||||
val dokkaTaskName = "dokka${variantSourceSet.javadocTaskName.replaceFirstChar { it.uppercase() }}"
|
||||
|
||||
val dokkaTask = if (tasks.names.contains(dokkaTaskName)) {
|
||||
tasks.named<DokkaTask>(dokkaTaskName)
|
||||
} else {
|
||||
tasks.register<DokkaTask>(dokkaTaskName)
|
||||
}
|
||||
dokkaTask.configure {
|
||||
description = "Generates documentation in 'javadoc' format for '${variantSourceSet.javadocTaskName}' variant"
|
||||
|
||||
plugins.dependencies.add(
|
||||
project.dependencies.create("org.jetbrains.dokka:javadoc-plugin:${DokkaVersion.version}")
|
||||
)
|
||||
|
||||
dokkaSourceSets {
|
||||
named(commonSourceSet.name) {
|
||||
suppress.set(false)
|
||||
jdkVersion.set(8)
|
||||
}
|
||||
|
||||
named(variantSourceSet.name) {
|
||||
dependsOn(commonSourceSet)
|
||||
suppress.set(false)
|
||||
jdkVersion.set(8)
|
||||
|
||||
if (shouldLinkGradleApi) {
|
||||
externalDocumentationLink {
|
||||
url.set(URL(pluginVariant.gradleApiJavadocUrl))
|
||||
|
||||
addWorkaroundForElementList(pluginVariant)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.named<Jar>(variantSourceSet.javadocJarTaskName) {
|
||||
from(dokkaTask.flatMap { it.outputDirectory })
|
||||
}
|
||||
}
|
||||
|
||||
if (configurePublishingToKotlinlang) {
|
||||
val latestVariant = GradlePluginVariant.values().last()
|
||||
val olderVersionsDir = layout.buildDirectory.dir("dokka/kotlinlangDocumentationOld")
|
||||
|
||||
project.dependencies {
|
||||
// Version is required due to https://github.com/Kotlin/dokka/issues/2812
|
||||
"dokkaHtmlPlugin"("org.jetbrains.dokka:versioning-plugin:$dokkaVersioningPluginVersion")
|
||||
}
|
||||
|
||||
tasks.register<DokkaTask>("dokkaKotlinlangDocumentation") {
|
||||
description = "Generates documentation reference for Kotlinlang"
|
||||
|
||||
dokkaSourceSets {
|
||||
pluginsMapConfiguration.put(
|
||||
"org.jetbrains.dokka.base.DokkaBase",
|
||||
"{ \"templatesDir\": \"${layout.projectDirectory.dir("dokka-template")}\" }"
|
||||
)
|
||||
pluginsMapConfiguration.put(
|
||||
"org.jetbrains.dokka.versioning.VersioningPlugin",
|
||||
olderVersionsDir.map { olderVersionsDir ->
|
||||
"{ \"version\":\"$version\", \"olderVersionsDir\":\"${olderVersionsDir.asFile}\" }"
|
||||
}
|
||||
)
|
||||
|
||||
named(commonSourceSet.name) {
|
||||
suppress.set(false)
|
||||
jdkVersion.set(8)
|
||||
}
|
||||
|
||||
named(latestVariant.sourceSetName) {
|
||||
dependsOn(commonSourceSet)
|
||||
suppress.set(false)
|
||||
jdkVersion.set(8)
|
||||
|
||||
if (shouldLinkGradleApi) {
|
||||
externalDocumentationLink {
|
||||
url.set(URL(latestVariant.gradleApiJavadocUrl))
|
||||
|
||||
addWorkaroundForElementList(latestVariant)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Workaround for https://github.com/Kotlin/dokka/issues/2097
|
||||
// Gradle 7.6 javadoc does not have published 'package-list' file
|
||||
private fun GradleExternalDocumentationLinkBuilder.addWorkaroundForElementList(pluginVariant: GradlePluginVariant) {
|
||||
if (pluginVariant == GradlePluginVariant.GRADLE_76 ||
|
||||
pluginVariant == GradlePluginVariant.GRADLE_80 ||
|
||||
pluginVariant == GradlePluginVariant.GRADLE_81
|
||||
) {
|
||||
packageListUrl.set(URL("${pluginVariant.gradleApiJavadocUrl}element-list"))
|
||||
}
|
||||
}
|
||||
|
||||
private val SourceSet.embeddedConfigurationName get() = "${name}Embedded"
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
import org.gradle.api.Project
|
||||
|
||||
interface CompatibilityPredicate {
|
||||
fun matches(ide: Ide): Boolean
|
||||
|
||||
operator fun invoke(): Boolean = matches(IdeVersionConfigurator.currentIde)
|
||||
|
||||
operator fun invoke(block: () -> Unit): Unit {
|
||||
if (matches(IdeVersionConfigurator.currentIde)) {
|
||||
block()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val CompatibilityPredicate.not: CompatibilityPredicate get() = object : CompatibilityPredicate {
|
||||
override fun matches(ide: Ide) = !this@not.matches(ide)
|
||||
}
|
||||
|
||||
fun CompatibilityPredicate.or(other: CompatibilityPredicate): CompatibilityPredicate = object : CompatibilityPredicate {
|
||||
override fun matches(ide: Ide) = this@or.matches(ide) || other.matches(ide)
|
||||
}
|
||||
|
||||
enum class Platform : CompatibilityPredicate {
|
||||
P213;
|
||||
|
||||
val version: Int = name.drop(1).toInt()
|
||||
|
||||
val displayVersion: String = "20${name.drop(1).dropLast(1)}.${name.last()}"
|
||||
|
||||
override fun matches(ide: Ide) = ide.platform == this
|
||||
|
||||
companion object {
|
||||
operator fun get(version: Int): Platform {
|
||||
return Platform.values().firstOrNull { it.version == version }
|
||||
?: error("Can't find platform $version")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
enum class Ide(val platform: Platform) : CompatibilityPredicate {
|
||||
IJ213(Platform.P213);
|
||||
|
||||
val kind = Kind.values().first { it.shortName == name.take(2) }
|
||||
val version = name.dropWhile { !it.isDigit() }.toInt()
|
||||
|
||||
val displayVersion: String = when (kind) {
|
||||
Kind.IntelliJ -> "IJ${platform.displayVersion}"
|
||||
Kind.AndroidStudio -> "Studio${name.substringAfter("AS").toCharArray().joinToString(separator = ".")}"
|
||||
}
|
||||
|
||||
override fun matches(ide: Ide) = ide == this
|
||||
|
||||
enum class Kind(val shortName: String) {
|
||||
AndroidStudio("AS"), IntelliJ("IJ")
|
||||
}
|
||||
|
||||
companion object {
|
||||
val IJ: CompatibilityPredicate = IdeKindPredicate(Kind.IntelliJ)
|
||||
val AS: CompatibilityPredicate = IdeKindPredicate(Kind.AndroidStudio)
|
||||
}
|
||||
}
|
||||
|
||||
val Platform.orHigher get() = object : CompatibilityPredicate {
|
||||
override fun matches(ide: Ide) = ide.platform.version >= version
|
||||
}
|
||||
|
||||
val Platform.orLower get() = object : CompatibilityPredicate {
|
||||
override fun matches(ide: Ide) = ide.platform.version <= version
|
||||
}
|
||||
|
||||
val Ide.orHigher get() = object : CompatibilityPredicate {
|
||||
override fun matches(ide: Ide) = ide.kind == kind && ide.version >= version
|
||||
}
|
||||
|
||||
val Ide.orLower get() = object : CompatibilityPredicate {
|
||||
override fun matches(ide: Ide) = ide.kind == kind && ide.version <= version
|
||||
}
|
||||
|
||||
object IdeVersionConfigurator {
|
||||
lateinit var currentIde: Ide
|
||||
|
||||
fun setCurrentIde(project: Project) {
|
||||
val platformVersion = project.rootProject.extensions.extraProperties["versions.platform"].toString()
|
||||
val ideName = if (platformVersion.startsWith("AS")) platformVersion else "IJ$platformVersion"
|
||||
currentIde = Ide.valueOf(ideName)
|
||||
}
|
||||
}
|
||||
|
||||
private class IdeKindPredicate(val kind: Ide.Kind) : CompatibilityPredicate {
|
||||
override fun matches(ide: Ide) = ide.kind == kind
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
import org.gradle.api.Action
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.tasks.compile.JavaCompile
|
||||
import org.gradle.kotlin.dsl.provideDelegate
|
||||
import org.gradle.kotlin.dsl.withGroovyBuilder
|
||||
import java.io.File
|
||||
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
class InstrumentJava(@Transient val javaInstrumentator: Configuration) : Action<Task> {
|
||||
private val instrumentatorClasspath: String by lazy {
|
||||
javaInstrumentator.asPath
|
||||
}
|
||||
|
||||
override fun execute(task: Task) {
|
||||
require(task is JavaCompile) { "$task is not of type JavaCompile!" }
|
||||
|
||||
// There is a requirement for Javac.execute() to have an existen non-empty directory as a source dir for the compilation
|
||||
// even if compilation is disabled.
|
||||
//
|
||||
// So we create an empty dummy directory during the execution.
|
||||
//
|
||||
// See:
|
||||
// Javac.execute() - https://github.com/apache/ant/blob/9943641/src/main/org/apache/tools/ant/taskdefs/Javac.java#L1086
|
||||
// InstrumentIdeaExtensions - https://github.com/JetBrains/intellij-community/blob/9c40bdd/java/compiler/javac2/src/com/intellij/ant/InstrumentIdeaExtensions.java
|
||||
// Javac2.compile() - https://github.com/JetBrains/intellij-community/blob/9c40bdd/java/compiler/javac2/src/com/intellij/ant/Javac2.java#L237
|
||||
val dummyInstrumentSrcDir = File(task.project.buildDir, "instrument_dummy_src")
|
||||
val dummyInstrumentSrcRelativePath = dummyInstrumentSrcDir.relativeTo(task.project.projectDir).path.replace("\\", "/")
|
||||
|
||||
task.doLast {
|
||||
task.ant.withGroovyBuilder {
|
||||
"taskdef"(
|
||||
"name" to "instrumentIdeaExtensions",
|
||||
"classpath" to instrumentatorClasspath,
|
||||
"loaderref" to "java2.loader",
|
||||
"classname" to "com.intellij.ant.InstrumentIdeaExtensions"
|
||||
)
|
||||
}
|
||||
|
||||
dummyInstrumentSrcDir.mkdirs()
|
||||
|
||||
task.ant.withGroovyBuilder {
|
||||
"instrumentIdeaExtensions"(
|
||||
"srcdir" to dummyInstrumentSrcRelativePath,
|
||||
"destdir" to task.destinationDirectory.asFile.get(),
|
||||
"classpath" to task.classpath.asPath,
|
||||
"includeantruntime" to false,
|
||||
"instrumentNotNull" to true
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
@file:JvmName("JvmToolchain")
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.plugins.JavaPluginExtension
|
||||
import org.gradle.api.provider.Provider
|
||||
import org.gradle.api.tasks.compile.JavaCompile
|
||||
import org.gradle.jvm.toolchain.*
|
||||
import org.gradle.kotlin.dsl.getByType
|
||||
import org.gradle.kotlin.dsl.withType
|
||||
import org.jetbrains.kotlin.gradle.dsl.KotlinTopLevelExtension
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
|
||||
enum class JdkMajorVersion(
|
||||
val majorVersion: Int,
|
||||
val targetName: String = majorVersion.toString(),
|
||||
private val overrideMajorVersion: Int? = null,
|
||||
private val mandatory: Boolean = true
|
||||
) {
|
||||
JDK_1_6(6, targetName = "1.6", overrideMajorVersion = 8),
|
||||
JDK_1_7(7, targetName = "1.7", overrideMajorVersion = 8),
|
||||
JDK_1_8(8, targetName = "1.8"),
|
||||
JDK_9_0(9, overrideMajorVersion = 11),
|
||||
JDK_10_0(10, mandatory = false, overrideMajorVersion = 11),
|
||||
JDK_11_0(11, mandatory = false),
|
||||
JDK_16_0(16, mandatory = false),
|
||||
JDK_17_0(17, mandatory = false),
|
||||
JDK_21_0(21, mandatory = false);
|
||||
|
||||
fun isMandatory(): Boolean = mandatory
|
||||
|
||||
val overrideVersion by lazy {
|
||||
if (overrideMajorVersion != null) {
|
||||
values().firstOrNull() { it.majorVersion == overrideMajorVersion }
|
||||
?: error("Can't find the value with majorVersion=$overrideMajorVersion")
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
|
||||
val envName = name
|
||||
}
|
||||
|
||||
val DEFAULT_JVM_TOOLCHAIN = JdkMajorVersion.JDK_1_8
|
||||
|
||||
fun Project.configureJvmDefaultToolchain() {
|
||||
configureJvmToolchain(DEFAULT_JVM_TOOLCHAIN)
|
||||
}
|
||||
|
||||
fun Project.shouldOverrideObsoleteJdk(jdkVersion: JdkMajorVersion): Boolean =
|
||||
kotlinBuildProperties.isObsoleteJdkOverrideEnabled && jdkVersion.overrideVersion != null
|
||||
|
||||
fun Project.configureJvmToolchain(jdkVersion: JdkMajorVersion) {
|
||||
@Suppress("NAME_SHADOWING")
|
||||
val jdkVersion = chooseJdk_1_8ForJpsBuild(jdkVersion)
|
||||
// Ensure java only modules also set default toolchain
|
||||
configureJavaOnlyToolchain(jdkVersion)
|
||||
|
||||
plugins.withId("org.jetbrains.kotlin.jvm") {
|
||||
val kotlinExtension = extensions.getByType<KotlinTopLevelExtension>()
|
||||
|
||||
if (shouldOverrideObsoleteJdk(jdkVersion)) {
|
||||
kotlinExtension.jvmToolchain {
|
||||
setupToolchain(jdkVersion.overrideVersion ?: error("Substitution version should be defined for override mode"))
|
||||
}
|
||||
updateJvmTarget(jdkVersion.targetName)
|
||||
} else {
|
||||
kotlinExtension.jvmToolchain {
|
||||
setupToolchain(jdkVersion)
|
||||
}
|
||||
}
|
||||
|
||||
tasks
|
||||
.matching { it.name != "compileJava9Java" && it is JavaCompile }
|
||||
.configureEach {
|
||||
with(this as JavaCompile) {
|
||||
options.compilerArgs.add("-proc:none")
|
||||
options.encoding = "UTF-8"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun JavaToolchainSpec.setupToolchain(jdkVersion: JdkMajorVersion) {
|
||||
languageVersion.set(JavaLanguageVersion.of(jdkVersion.majorVersion))
|
||||
}
|
||||
|
||||
fun Project.configureJavaOnlyToolchain(
|
||||
jdkVersion: JdkMajorVersion
|
||||
) {
|
||||
@Suppress("NAME_SHADOWING")
|
||||
val jdkVersion = chooseJdk_1_8ForJpsBuild(jdkVersion)
|
||||
plugins.withId("java-base") {
|
||||
val javaExtension = extensions.getByType<JavaPluginExtension>()
|
||||
if (shouldOverrideObsoleteJdk(jdkVersion)) {
|
||||
javaExtension.toolchain {
|
||||
setupToolchain(jdkVersion.overrideVersion ?: error("Substitution version should be defined for override mode"))
|
||||
}
|
||||
tasks.withType<JavaCompile>().configureEach {
|
||||
targetCompatibility = jdkVersion.targetName
|
||||
sourceCompatibility = jdkVersion.targetName
|
||||
}
|
||||
} else {
|
||||
javaExtension.toolchain {
|
||||
setupToolchain(jdkVersion)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.chooseJdk_1_8ForJpsBuild(jdkVersion: JdkMajorVersion): JdkMajorVersion {
|
||||
return if (kotlinBuildProperties.isInJpsBuildIdeaSync) {
|
||||
maxOf(jdkVersion, JdkMajorVersion.JDK_1_8)
|
||||
} else {
|
||||
jdkVersion
|
||||
}
|
||||
}
|
||||
|
||||
fun KotlinCompile.configureTaskToolchain(
|
||||
jdkVersion: JdkMajorVersion
|
||||
) {
|
||||
if (project.shouldOverrideObsoleteJdk(jdkVersion)) {
|
||||
kotlinJavaToolchain.toolchain.use(
|
||||
project.getToolchainLauncherFor(
|
||||
jdkVersion.overrideVersion ?: error("Substitution version should be defined for override mode")
|
||||
)
|
||||
)
|
||||
@Suppress("DEPRECATION")
|
||||
kotlinOptions {
|
||||
jvmTarget = jdkVersion.targetName
|
||||
}
|
||||
} else {
|
||||
kotlinJavaToolchain.toolchain.use(
|
||||
project.getToolchainLauncherFor(jdkVersion)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun JavaCompile.configureTaskToolchain(
|
||||
jdkVersion: JdkMajorVersion
|
||||
) {
|
||||
if (project.shouldOverrideObsoleteJdk(jdkVersion)) {
|
||||
javaCompiler.set(
|
||||
project.getToolchainCompilerFor(
|
||||
jdkVersion.overrideVersion ?: error("Substitution version should be defined for override mode")
|
||||
)
|
||||
)
|
||||
targetCompatibility = jdkVersion.targetName
|
||||
sourceCompatibility = jdkVersion.targetName
|
||||
} else {
|
||||
javaCompiler.set(project.getToolchainCompilerFor(jdkVersion))
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.updateJvmTarget(
|
||||
jvmTarget: String
|
||||
) {
|
||||
@Suppress("NAME_SHADOWING")
|
||||
val jvmTarget = if (kotlinBuildProperties.isInJpsBuildIdeaSync && jvmTarget == "1.6") {
|
||||
"1.8"
|
||||
} else {
|
||||
jvmTarget
|
||||
}
|
||||
// Java 9 tasks are exceptions that are configured in configureJava9Compilation
|
||||
tasks
|
||||
.withType<KotlinCompile>()
|
||||
.matching { it.name != "compileJava9Kotlin" }
|
||||
.configureEach {
|
||||
@Suppress("DEPRECATION")
|
||||
kotlinOptions.jvmTarget = jvmTarget
|
||||
}
|
||||
|
||||
tasks
|
||||
.withType<JavaCompile>()
|
||||
.matching { it.name != "compileJava9Java" }
|
||||
.configureEach {
|
||||
sourceCompatibility = jvmTarget
|
||||
targetCompatibility = jvmTarget
|
||||
}
|
||||
}
|
||||
|
||||
private fun Project.getToolchainCompilerFor(
|
||||
jdkVersion: JdkMajorVersion
|
||||
): Provider<JavaCompiler> {
|
||||
val service = project.extensions.getByType<JavaToolchainService>()
|
||||
return service.compilerFor {
|
||||
this.languageVersion.set(JavaLanguageVersion.of(jdkVersion.majorVersion))
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.getToolchainLauncherFor(
|
||||
jdkVersion: JdkMajorVersion
|
||||
): Provider<JavaLauncher> {
|
||||
val service = project.extensions.getByType<JavaToolchainService>()
|
||||
val jdkVersionWithOverride = project.getJdkVersionWithOverride(jdkVersion)
|
||||
return service.launcherFor {
|
||||
this.languageVersion.set(JavaLanguageVersion.of(jdkVersionWithOverride.majorVersion))
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.getToolchainJdkHomeFor(jdkVersion: JdkMajorVersion): Provider<String> {
|
||||
return getToolchainLauncherFor(jdkVersion).map {
|
||||
it.metadata.installationPath.asFile.absolutePath
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun Project.getJdkVersionWithOverride(jdkVersion: JdkMajorVersion): JdkMajorVersion {
|
||||
return if (project.shouldOverrideObsoleteJdk(jdkVersion)) {
|
||||
jdkVersion.overrideVersion ?: error("Substitution version should be defined for override mode")
|
||||
} else {
|
||||
jdkVersion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:JvmName("LibrariesCommon")
|
||||
|
||||
import org.gradle.api.JavaVersion
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.java.archives.Manifest
|
||||
import org.gradle.api.plugins.BasePluginExtension
|
||||
import org.gradle.api.tasks.compile.JavaCompile
|
||||
import org.gradle.kotlin.dsl.*
|
||||
import org.gradle.process.CommandLineArgumentProvider
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||
import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile
|
||||
|
||||
@JvmOverloads
|
||||
fun Project.configureJava9Compilation(
|
||||
moduleName: String,
|
||||
moduleOutputs: Collection<FileCollection> = setOf(sourceSets["main"].output)
|
||||
) {
|
||||
configurations["java9CompileClasspath"].extendsFrom(configurations["compileClasspath"])
|
||||
|
||||
tasks.named("compileJava9Kotlin", KotlinCompile::class.java) {
|
||||
configureTaskToolchain(JdkMajorVersion.JDK_9_0)
|
||||
@Suppress("DEPRECATION")
|
||||
kotlinOptions.jvmTarget = JdkMajorVersion.JDK_9_0.targetName
|
||||
}
|
||||
|
||||
tasks.named("compileJava9Java", JavaCompile::class.java) {
|
||||
dependsOn(moduleOutputs)
|
||||
|
||||
targetCompatibility = JavaVersion.VERSION_1_9.toString()
|
||||
sourceCompatibility = JavaVersion.VERSION_1_9.toString()
|
||||
configureTaskToolchain(JdkMajorVersion.JDK_9_0)
|
||||
|
||||
// module-info.java should be in java9 source set by convention
|
||||
val java9SourceSet = sourceSets["java9"].java
|
||||
destinationDirectory.set(java9SourceSet.destinationDirectory.asFile.get().resolve("META-INF/versions/9"))
|
||||
options.sourcepath = files(java9SourceSet.srcDirs)
|
||||
val compileClasspath = configurations["java9CompileClasspath"]
|
||||
val moduleFiles = objects.fileCollection().from(moduleOutputs)
|
||||
val modulePath = compileClasspath.filter { it !in moduleFiles.files }
|
||||
classpath = objects.fileCollection().from()
|
||||
options.compilerArgumentProviders.add(
|
||||
Java9AdditionalArgumentsProvider(
|
||||
moduleName,
|
||||
moduleFiles,
|
||||
modulePath
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private class Java9AdditionalArgumentsProvider(
|
||||
private val moduleName: String,
|
||||
private val moduleFiles: FileCollection,
|
||||
private val modulePath: FileCollection
|
||||
) : CommandLineArgumentProvider {
|
||||
override fun asArguments(): Iterable<String> = listOf(
|
||||
"--module-path", modulePath.asPath,
|
||||
"--patch-module", "$moduleName=${moduleFiles.asPath}",
|
||||
"-Xlint:-requires-transitive-automatic" // suppress automatic module transitive dependencies in kotlin.test
|
||||
)
|
||||
}
|
||||
|
||||
fun Project.configureFrontendIr() = tasks.withType<KotlinJvmCompile>().configureEach {
|
||||
compilerOptions {
|
||||
if (project.kotlinBuildProperties.useFirForLibraries) {
|
||||
freeCompilerArgs.add("-Xuse-k2")
|
||||
allWarningsAsErrors.set(false)
|
||||
} else if (project.kotlinBuildProperties.useFir) {
|
||||
freeCompilerArgs.add("-Xskip-prerelease-check")
|
||||
}
|
||||
|
||||
val renderDiagnosticNames by extra(project.kotlinBuildProperties.renderDiagnosticNames)
|
||||
if (renderDiagnosticNames) {
|
||||
freeCompilerArgs.add("-Xrender-internal-diagnostic-names")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun Project.manifestAttributes(
|
||||
manifest: Manifest,
|
||||
component: String? = null,
|
||||
multiRelease: Boolean = false
|
||||
) {
|
||||
manifest.attributes(
|
||||
"Implementation-Vendor" to "JetBrains",
|
||||
"Implementation-Title" to project.extensions.getByType<BasePluginExtension>().archivesName,
|
||||
"Implementation-Version" to project.rootProject.extra["buildNumber"] as String
|
||||
)
|
||||
|
||||
if (component != null) {
|
||||
val kotlinLanguageVersion: String by rootProject.extra
|
||||
manifest.attributes(
|
||||
"Kotlin-Runtime-Component" to component,
|
||||
"Kotlin-Version" to kotlinLanguageVersion
|
||||
)
|
||||
}
|
||||
|
||||
if (multiRelease) {
|
||||
manifest.attributes(
|
||||
"Multi-Release" to "true"
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
import org.gradle.api.tasks.JavaExec
|
||||
|
||||
/**
|
||||
* Workaround for IDEA-200192:
|
||||
* IDEA makes all JavaExec tasks not up-to-date and attaches debugger making our breakpoints trigger during irrelevant task execution
|
||||
*/
|
||||
open class NoDebugJavaExec : JavaExec() {
|
||||
private fun String.isDebuggerArgument(): Boolean =
|
||||
startsWith("-agentlib:jdwp=transport=dt_socket,server=n,suspend=y,address=")
|
||||
|
||||
override fun setJvmArgs(arguments: MutableList<String>?) {
|
||||
super.setJvmArgs(arguments?.filterNot { it.isDebuggerArgument() })
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.tasks.JavaExec
|
||||
import org.gradle.jvm.tasks.Jar
|
||||
import org.gradle.kotlin.dsl.creating
|
||||
import org.gradle.kotlin.dsl.task
|
||||
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
// creating class eagerly here: using register causes problems due to quite complicated relationships between these tasks
|
||||
fun Project.smartJavaExec(configure: JavaExec.() -> Unit) = tasks.creating(JavaExec::class) {
|
||||
configure()
|
||||
passClasspathInJar()
|
||||
}
|
||||
|
||||
// Moves the classpath into a jar metadata, to shorten the command line length and to avoid hitting the limit on Windows
|
||||
fun JavaExec.passClasspathInJar() {
|
||||
val jarTask = project.task("${name}WriteClassPath", Jar::class) {
|
||||
val classpath = classpath
|
||||
val main = mainClass.get()
|
||||
dependsOn(classpath)
|
||||
inputs.files(classpath)
|
||||
inputs.property("main", main)
|
||||
|
||||
archiveFileName.set("$main.${this@passClasspathInJar.name}.classpath.container.jar")
|
||||
destinationDirectory.set(temporaryDir)
|
||||
|
||||
doFirst {
|
||||
val classPathString = classpath.joinToString(" ") {
|
||||
it.toURI().toString()
|
||||
}
|
||||
manifest {
|
||||
attributes(
|
||||
mapOf(
|
||||
"Class-Path" to classPathString,
|
||||
"Main-Class" to main
|
||||
)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependsOn(jarTask)
|
||||
|
||||
mainClass.set("-jar")
|
||||
classpath = project.files()
|
||||
args = listOf(jarTask.outputs.files.singleFile.path) + args.orEmpty()
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
import org.gradle.api.Action
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.execution.TaskExecutionGraph
|
||||
import org.gradle.api.tasks.TaskProvider
|
||||
|
||||
/* This file is solely needed to suppress implicit dependencies on npm and yarn tasks registered by Kotlin Gradle Plugin */
|
||||
|
||||
private val rootNpmRelatedTasks = setOf("kotlinNpmInstall", "kotlinStoreYarnLock")
|
||||
|
||||
private val allowImplicitDependOnNpmForTasks = setOf("kotlinUpgradeYarnLock", "compileTestKotlinJs", "compileTestKotlinWasm")
|
||||
|
||||
private fun findRootTasks(taskGraph: TaskExecutionGraph): List<Task> {
|
||||
val allDependentTasksPaths = mutableSetOf<String>()
|
||||
val allTasksPaths = mutableSetOf<String>()
|
||||
taskGraph.allTasks.forEach { task ->
|
||||
allTasksPaths.add(task.path)
|
||||
for (dependency in task.taskDependencies.getDependencies(task)) {
|
||||
allDependentTasksPaths.add(dependency.path)
|
||||
}
|
||||
}
|
||||
val rootTasksPaths = allTasksPaths - allDependentTasksPaths
|
||||
|
||||
return taskGraph.allTasks.filter { task -> task.path in rootTasksPaths }
|
||||
}
|
||||
|
||||
private fun tasksGraphString(taskGraph: TaskExecutionGraph, ident: String = "", nextIdent: (String) -> String = { "$it|-"}): String {
|
||||
return buildString {
|
||||
val alreadyPrintedTasks = mutableSetOf<String>()
|
||||
fun Task.printTree(indent: String) {
|
||||
append(indent)
|
||||
if (path in alreadyPrintedTasks) {
|
||||
appendLine("$path *")
|
||||
} else {
|
||||
alreadyPrintedTasks.add(path)
|
||||
appendLine(path)
|
||||
val nextIndent = nextIdent(indent)
|
||||
for (dependency in taskDependencies.getDependencies(this)) {
|
||||
dependency.printTree(nextIndent)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (rootTask in findRootTasks(taskGraph)) {
|
||||
rootTask.printTree(ident)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val Project.checkYarnAndNPMSuppressed: Action<TaskExecutionGraph> get() {
|
||||
return Action<TaskExecutionGraph> {
|
||||
val disableNpmYarnCheck = providers.gradleProperty("kotlin.build.disable.npmyarn.suppress.check")
|
||||
.orNull?.toBoolean() ?: false
|
||||
|
||||
if (disableNpmYarnCheck) return@Action
|
||||
|
||||
val executeTaskNames = allTasks.filter { it.enabled }.map { it.name }.toSet()
|
||||
|
||||
val npmYarnTasks = rootNpmRelatedTasks.filter { it in executeTaskNames }
|
||||
val allowedTask = allowImplicitDependOnNpmForTasks.filter { it in executeTaskNames }
|
||||
|
||||
if (npmYarnTasks.isNotEmpty()) {
|
||||
if (allowedTask.isEmpty()) {
|
||||
error("$npmYarnTasks tasks shouldn't be present in the task graph: $npmYarnTasks " +
|
||||
"as $allowImplicitDependOnNpmForTasks tasks were not activated\n" +
|
||||
"Graph:\n${tasksGraphString(this)}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
import GradlePropertyIssue.MissingProperty
|
||||
import GradlePropertyIssue.UnexpectedPropertyValue
|
||||
import org.gradle.api.Project
|
||||
|
||||
/**
|
||||
* Mechanism to warn developers when a given Gradle property does not match the developer's expectation.
|
||||
*
|
||||
* There may be some Gradle properties, that are defined in the project and will change over time (e.g. defaultSnapshotVersion).
|
||||
* Some developers (and QA) will need to be very clear about the value of this property.
|
||||
*
|
||||
* In order to get notified about the value of the property changing, it is possible to define the same property in
|
||||
* ~/.gradle/gradle.properties with a given `.kotlin_build.expected_value` suffix to ensure the value.
|
||||
*
|
||||
* e.g. if a developer set's
|
||||
*
|
||||
* `defaultSnapshotVersion.kotlin_build.expected_value=1.6.255-SNAPSHOT` and the value gets bumped to `1.9.255-SNAPSHOT` after pulling from master,
|
||||
* the developer will notice this during project configuration phase.
|
||||
*/
|
||||
fun Project.checkExpectedGradlePropertyValues() {
|
||||
val expectSuffix = ".kotlin_build.expected_value"
|
||||
val expectKeys = properties.keys.filter { it.endsWith(expectSuffix) }
|
||||
|
||||
val issues = expectKeys.mapNotNull { expectKey ->
|
||||
val actualKey = expectKey.removeSuffix(expectSuffix)
|
||||
val expectedValue = properties[expectKey]?.toString() ?: return@mapNotNull null
|
||||
|
||||
if (!properties.containsKey(actualKey))
|
||||
return@mapNotNull MissingProperty(actualKey, expectedValue)
|
||||
|
||||
val actualValue = properties[actualKey].toString()
|
||||
|
||||
if (expectedValue != actualValue)
|
||||
return@mapNotNull UnexpectedPropertyValue(actualKey, expectedValue, actualValue)
|
||||
|
||||
null
|
||||
}.toSet()
|
||||
|
||||
if (issues.isEmpty()) {
|
||||
return
|
||||
}
|
||||
|
||||
val unexpectedPropertyValues = issues.filterIsInstance<UnexpectedPropertyValue>()
|
||||
val missingProperties = issues.filterIsInstance<MissingProperty>()
|
||||
|
||||
throw IllegalArgumentException(
|
||||
buildString {
|
||||
if (unexpectedPropertyValues.isNotEmpty()) {
|
||||
appendLine("Unexpected Gradle property values found in ${project.displayName}:")
|
||||
unexpectedPropertyValues.forEach { issue ->
|
||||
appendLine("Expected ${issue.key} to be '${issue.expectedValue}', but found '${issue.actualValue}'")
|
||||
}
|
||||
}
|
||||
|
||||
if (missingProperties.isNotEmpty()) {
|
||||
if (unexpectedPropertyValues.isNotEmpty()) appendLine()
|
||||
appendLine("Missing Gradle properties found in ${project.displayName}:")
|
||||
missingProperties.forEach { issue ->
|
||||
appendLine("Expected ${issue.key} to be '${issue.expectedValue}', but the property is missing")
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private sealed class GradlePropertyIssue {
|
||||
data class UnexpectedPropertyValue(
|
||||
val key: String, val expectedValue: String, val actualValue: String
|
||||
) : GradlePropertyIssue()
|
||||
|
||||
data class MissingProperty(
|
||||
val key: String, val expectedValue: String
|
||||
) : GradlePropertyIssue()
|
||||
}
|
||||
|
||||
+310
@@ -0,0 +1,310 @@
|
||||
import org.gradle.internal.deprecation.DeprecatableConfiguration
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinBasePluginWrapper
|
||||
|
||||
// Contains common configuration that should be applied to all projects
|
||||
|
||||
// Common Group and version
|
||||
val kotlinVersion: String by rootProject.extra
|
||||
group = "org.jetbrains.kotlin"
|
||||
version = kotlinVersion
|
||||
|
||||
// Forcing minimal gson dependency version
|
||||
val gsonVersion = rootProject.extra["versions.gson"] as String
|
||||
dependencies {
|
||||
constraints {
|
||||
configurations.all {
|
||||
if (isCanBeResolved && !isCanBeConsumed) {
|
||||
allDependencies.configureEach {
|
||||
if (group == "com.google.code.gson" && name == "gson" && this@all.isCanBeDeclared) {
|
||||
this@constraints.add(this@all.name, "com.google.code.gson:gson") {
|
||||
version {
|
||||
require(gsonVersion)
|
||||
}
|
||||
because("Force using same gson version because of https://github.com/google/gson/pull/1991")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
project.configureJvmDefaultToolchain()
|
||||
project.addEmbeddedConfigurations()
|
||||
project.addImplicitDependenciesConfiguration()
|
||||
project.configureJavaCompile()
|
||||
project.configureJavaBasePlugin()
|
||||
project.configureKotlinCompilationOptions()
|
||||
project.configureArtifacts()
|
||||
project.configureTests()
|
||||
|
||||
// There are problems with common build dir:
|
||||
// - some tests (in particular js and binary-compatibility-validator depend on the fixed (default) location
|
||||
// - idea seems unable to exclude common buildDir from indexing
|
||||
// therefore it is disabled by default
|
||||
// buildDir = File(commonBuildDir, project.name)
|
||||
|
||||
afterEvaluate {
|
||||
run configureCompilerClasspath@{
|
||||
val bootstrapCompilerClasspath by rootProject.buildscript.configurations
|
||||
configurations.findByName("kotlinCompilerClasspath")?.let {
|
||||
dependencies.add(it.name, files(bootstrapCompilerClasspath))
|
||||
}
|
||||
|
||||
configurations.findByName("kotlinCompilerPluginClasspath")
|
||||
?.exclude("org.jetbrains.kotlin", "kotlin-scripting-compiler-embeddable")
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.addImplicitDependenciesConfiguration() {
|
||||
configurations.maybeCreate("implicitDependencies").apply {
|
||||
isCanBeConsumed = false
|
||||
isCanBeResolved = false
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.addEmbeddedConfigurations() {
|
||||
configurations.maybeCreate("embedded").apply {
|
||||
isCanBeConsumed = false
|
||||
isCanBeResolved = true
|
||||
attributes {
|
||||
attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME))
|
||||
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements.JAR))
|
||||
}
|
||||
}
|
||||
|
||||
configurations.maybeCreate("embeddedElements").apply {
|
||||
extendsFrom(configurations["embedded"])
|
||||
isCanBeConsumed = true
|
||||
isCanBeResolved = false
|
||||
attributes {
|
||||
attribute(Usage.USAGE_ATTRIBUTE, objects.named("embedded-java-runtime"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.configureJavaCompile() {
|
||||
plugins.withType<JavaPlugin> {
|
||||
tasks.withType<JavaCompile>().configureEach {
|
||||
options.compilerArgs.add("-Xlint:deprecation")
|
||||
options.compilerArgs.add("-Xlint:unchecked")
|
||||
options.compilerArgs.add("-Werror")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.configureJavaBasePlugin() {
|
||||
plugins.withId("java-base") {
|
||||
fun File.toProjectRootRelativePathOrSelf() = (relativeToOrNull(rootDir)?.takeUnless { it.startsWith("..") } ?: this).path
|
||||
|
||||
fun FileCollection.printClassPath(role: String) =
|
||||
println("${project.path} $role classpath:\n ${joinToString("\n ") { it.toProjectRootRelativePathOrSelf() }}")
|
||||
|
||||
val javaExtension = javaPluginExtension()
|
||||
tasks {
|
||||
register("printCompileClasspath") { doFirst { javaExtension.sourceSets["main"].compileClasspath.printClassPath("compile") } }
|
||||
register("printRuntimeClasspath") { doFirst { javaExtension.sourceSets["main"].runtimeClasspath.printClassPath("runtime") } }
|
||||
register("printTestCompileClasspath") { doFirst { javaExtension.sourceSets["test"].compileClasspath.printClassPath("test compile") } }
|
||||
register("printTestRuntimeClasspath") { doFirst { javaExtension.sourceSets["test"].runtimeClasspath.printClassPath("test runtime") } }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.configureKotlinCompilationOptions() {
|
||||
plugins.withType<KotlinBasePluginWrapper> {
|
||||
val commonCompilerArgs = listOfNotNull(
|
||||
"-opt-in=kotlin.RequiresOptIn",
|
||||
"-progressive".takeIf { getBooleanProperty("test.progressive.mode") ?: false }
|
||||
)
|
||||
|
||||
val kotlinLanguageVersion: String by rootProject.extra
|
||||
val useJvmFir by extra(project.kotlinBuildProperties.useFir)
|
||||
val useFirLT by extra(project.kotlinBuildProperties.useFirWithLightTree)
|
||||
val useFirIC by extra(project.kotlinBuildProperties.useFirTightIC)
|
||||
val renderDiagnosticNames by extra(project.kotlinBuildProperties.renderDiagnosticNames)
|
||||
|
||||
@Suppress("DEPRECATION")
|
||||
tasks.withType<org.jetbrains.kotlin.gradle.dsl.KotlinCompile<*>>().configureEach {
|
||||
kotlinOptions {
|
||||
languageVersion = kotlinLanguageVersion
|
||||
apiVersion = kotlinLanguageVersion
|
||||
freeCompilerArgs += commonCompilerArgs
|
||||
}
|
||||
|
||||
val relativePathBaseArg: String? =
|
||||
"-Xklib-relative-path-base=$buildDir,$projectDir,$rootDir".takeIf {
|
||||
!kotlinBuildProperties.getBoolean("kotlin.build.use.absolute.paths.in.klib")
|
||||
}
|
||||
|
||||
// Workaround to avoid remote build cache misses due to absolute paths in relativePathBaseArg
|
||||
doFirst {
|
||||
if (relativePathBaseArg != null) {
|
||||
@Suppress("DEPRECATION")
|
||||
kotlinOptions.freeCompilerArgs += relativePathBaseArg
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val jvmCompilerArgs = listOf(
|
||||
"-Xno-optimized-callable-references",
|
||||
"-Xno-kotlin-nothing-value-exception",
|
||||
)
|
||||
|
||||
val coreLibProjects: List<String> by rootProject.extra
|
||||
val projectsWithDisabledFirBootstrap = coreLibProjects + listOf(
|
||||
":kotlin-gradle-plugin",
|
||||
":kotlinx-metadata",
|
||||
":kotlinx-metadata-jvm",
|
||||
// For some reason stdlib isn't imported correctly for this module
|
||||
// Probably it's related to kotlin-test module usage
|
||||
":kotlin-gradle-statistics",
|
||||
// Requires serialization plugin
|
||||
":wasm:wasm.ir",
|
||||
// Uses multiplatform
|
||||
":kotlin-stdlib-jvm-minimal-for-test",
|
||||
":kotlin-native:endorsedLibraries:kotlinx.cli",
|
||||
":kotlin-native:klib",
|
||||
// Requires serialization plugin
|
||||
":js:js.tests",
|
||||
)
|
||||
|
||||
// TODO: fix remaining warnings and remove this property.
|
||||
val tasksWithWarnings = listOf(
|
||||
":kotlin-gradle-plugin:compileCommonKotlin",
|
||||
":kotlin-native:build-tools:compileKotlin"
|
||||
)
|
||||
|
||||
val projectsWithEnabledContextReceivers: List<String> by rootProject.extra
|
||||
val projectsWithOptInToUnsafeCastFunctionsFromAddToStdLib: List<String> by rootProject.extra
|
||||
|
||||
@Suppress("SuspiciousCollectionReassignment", "DEPRECATION")
|
||||
tasks.withType<org.jetbrains.kotlin.gradle.dsl.KotlinJvmCompile>().configureEach {
|
||||
kotlinOptions {
|
||||
freeCompilerArgs += jvmCompilerArgs
|
||||
|
||||
if (useJvmFir) {
|
||||
if (project.path !in projectsWithDisabledFirBootstrap) {
|
||||
freeCompilerArgs += "-Xuse-k2"
|
||||
freeCompilerArgs += "-Xabi-stability=stable"
|
||||
if (useFirLT) {
|
||||
freeCompilerArgs += "-Xuse-fir-lt"
|
||||
}
|
||||
if (useFirIC) {
|
||||
freeCompilerArgs += "-Xuse-fir-ic"
|
||||
}
|
||||
} else {
|
||||
freeCompilerArgs += "-Xskip-prerelease-check"
|
||||
}
|
||||
}
|
||||
if (renderDiagnosticNames) {
|
||||
freeCompilerArgs += "-Xrender-internal-diagnostic-names"
|
||||
}
|
||||
if (path !in tasksWithWarnings) {
|
||||
allWarningsAsErrors = !kotlinBuildProperties.disableWerror
|
||||
}
|
||||
if (project.path in projectsWithEnabledContextReceivers) {
|
||||
freeCompilerArgs += "-Xcontext-receivers"
|
||||
}
|
||||
if (project.path in projectsWithOptInToUnsafeCastFunctionsFromAddToStdLib) {
|
||||
freeCompilerArgs += "-opt-in=org.jetbrains.kotlin.utils.addToStdlib.UnsafeCastFunction"
|
||||
}
|
||||
|
||||
if (project.path == ":kotlin-util-klib") {
|
||||
// This is a temporary workaround for a configuration problem in kotlin-native. Namely, module `:kotlin-native-shared`
|
||||
// depends on kotlin-util-klib from bootstrap for some reason (see `kotlin-native/shared/build.gradle.kts`), but when
|
||||
// we're packing dependencies for the use in the IDE, we pass paths to the newly built libraries to Proguard
|
||||
// (see `prepare/ide-plugin-dependencies/kotlin-backend-native-for-ide/build.gradle.kts`).
|
||||
//
|
||||
// So the code which was compiled against one version of a library, is analyzed by Proguard against another version.
|
||||
//
|
||||
// This is a bad situation for JVM default flag behavior specifically. If kotlin-util-klib from bootstrap is compiled
|
||||
// in the old mode (with DefaultImpls for interfaces), then subclasses in kotlin-native-shared will also be generated
|
||||
// in the old mode (with DefaultImpls). But then Proguard will analyze these subclasses and their DefaultImpls classes,
|
||||
// and will observe calls to non-existing methods from DefaultImpls of the interfaces in kotlin-util-klib, and report
|
||||
// an error.
|
||||
//
|
||||
// This change will most likely not be needed after the bootstrap, as soon as kotlin-util-klib is compiled with
|
||||
// `-Xjvm-default=all`.
|
||||
freeCompilerArgs += "-Xjvm-default=all-compatibility"
|
||||
} else if (!skipJvmDefaultAllForModule(project.path)) {
|
||||
freeCompilerArgs += "-Xjvm-default=all"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.configureArtifacts() {
|
||||
tasks.withType<Javadoc>().configureEach {
|
||||
enabled = false
|
||||
}
|
||||
|
||||
tasks.withType<Jar>().configureEach {
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
}
|
||||
|
||||
tasks.withType<AbstractArchiveTask>().configureEach {
|
||||
isPreserveFileTimestamps = false
|
||||
isReproducibleFileOrder = true
|
||||
val `rw-r--r--` = 0b110100100
|
||||
val `rwxr-xr-x` = 0b111101101
|
||||
fileMode = `rw-r--r--`
|
||||
dirMode = `rwxr-xr-x`
|
||||
filesMatching("**/bin/*") { mode = `rwxr-xr-x` }
|
||||
filesMatching("**/bin/*.bat") { mode = `rw-r--r--` }
|
||||
}
|
||||
|
||||
normalization {
|
||||
runtimeClasspath {
|
||||
ignore("META-INF/MANIFEST.MF")
|
||||
ignore("META-INF/compiler.version")
|
||||
ignore("META-INF/plugin.xml")
|
||||
ignore("kotlin/KotlinVersionCurrentValue.class")
|
||||
}
|
||||
}
|
||||
|
||||
fun Task.listConfigurationContents(configName: String) {
|
||||
doFirst {
|
||||
project.configurations.findByName(configName)?.let {
|
||||
println("$configName configuration files:\n${it.allArtifacts.files.files.joinToString("\n ", " ")}")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks.register("listArchives") { listConfigurationContents("archives") }
|
||||
tasks.register("listDistJar") { listConfigurationContents("distJar") }
|
||||
}
|
||||
|
||||
fun Project.configureTests() {
|
||||
val ignoreTestFailures: Boolean by rootProject.extra
|
||||
tasks.configureEach {
|
||||
if (this is VerificationTask) {
|
||||
ignoreFailures = ignoreTestFailures
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType<Test>().configureEach {
|
||||
outputs.doNotCacheIf("https://youtrack.jetbrains.com/issue/KTI-112") { true }
|
||||
}
|
||||
|
||||
// Aggregate task for build related checks
|
||||
tasks.register("checkBuild")
|
||||
|
||||
configureTestRetriesForTestTasks()
|
||||
}
|
||||
|
||||
// TODO: migrate remaining modules to the new JVM default scheme.
|
||||
fun skipJvmDefaultAllForModule(path: String): Boolean =
|
||||
// Gradle plugin modules are disabled because different Gradle versions bundle different Kotlin compilers,
|
||||
// and not all of them support the new JVM default scheme.
|
||||
"-gradle" in path || "-runtime" in path || path == ":kotlin-project-model" ||
|
||||
// Visitor/transformer interfaces in ir.tree are very sensitive to the way interface methods are implemented.
|
||||
// Enabling default method generation results in a performance loss of several % on full pipeline test on Kotlin.
|
||||
// TODO: investigate the performance difference and enable new mode for ir.tree.
|
||||
path == ":compiler:ir.tree" ||
|
||||
// Workaround a Proguard issue:
|
||||
// java.lang.IllegalAccessError: tried to access method kotlin.reflect.jvm.internal.impl.types.checker.ClassicTypeSystemContext$substitutionSupertypePolicy$2.<init>(
|
||||
// Lkotlin/reflect/jvm/internal/impl/types/checker/ClassicTypeSystemContext;Lkotlin/reflect/jvm/internal/impl/types/TypeSubstitutor;
|
||||
// )V from class kotlin.reflect.jvm.internal.impl.resolve.OverridingUtilTypeSystemContext
|
||||
// KT-54749
|
||||
path == ":core:descriptors"
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
import org.gradle.api.Action
|
||||
import org.gradle.api.NamedDomainObjectContainer
|
||||
import org.gradle.api.NamedDomainObjectProvider
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.artifacts.Dependency
|
||||
import org.gradle.api.artifacts.ExternalModuleDependency
|
||||
import org.gradle.api.artifacts.ModuleDependency
|
||||
import org.gradle.api.artifacts.dsl.DependencyHandler
|
||||
import org.gradle.kotlin.dsl.accessors.runtime.addDependencyTo
|
||||
import org.gradle.kotlin.dsl.accessors.runtime.addExternalModuleDependencyTo
|
||||
import org.gradle.kotlin.dsl.add
|
||||
|
||||
val NamedDomainObjectContainer<Configuration>.embedded: NamedDomainObjectProvider<Configuration>
|
||||
get() = named("embedded")
|
||||
|
||||
fun DependencyHandler.embedded(dependencyNotation: Any): Dependency? =
|
||||
add("embedded", dependencyNotation)
|
||||
|
||||
val NamedDomainObjectContainer<Configuration>.implicitDependencies: NamedDomainObjectProvider<Configuration>
|
||||
get() = named("implicitDependencies")
|
||||
|
||||
fun DependencyHandler.implicitDependencies(dependencyNotation: Any): Dependency? =
|
||||
add("implicitDependencies", dependencyNotation)
|
||||
@@ -0,0 +1,177 @@
|
||||
@file:Suppress("unused") // usages in build scripts are not tracked properly
|
||||
|
||||
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.DependencySubstitution
|
||||
import org.gradle.api.artifacts.component.ProjectComponentSelector
|
||||
import org.gradle.api.attributes.LibraryElements
|
||||
import org.gradle.api.attributes.Usage
|
||||
import org.gradle.api.file.DuplicatesStrategy
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.tasks.TaskProvider
|
||||
import org.gradle.jvm.tasks.Jar
|
||||
import org.gradle.kotlin.dsl.exclude
|
||||
import org.gradle.kotlin.dsl.named
|
||||
import org.gradle.kotlin.dsl.project
|
||||
import org.gradle.kotlin.dsl.register
|
||||
import java.io.File
|
||||
|
||||
const val kotlinEmbeddableRootPackage = "org.jetbrains.kotlin"
|
||||
|
||||
val packagesToRelocate =
|
||||
listOf(
|
||||
"com.intellij",
|
||||
"com.google",
|
||||
"com.sampullara",
|
||||
"org.apache",
|
||||
"org.jdom",
|
||||
"org.picocontainer",
|
||||
"org.jline",
|
||||
"org.fusesource",
|
||||
"net.jpountz",
|
||||
"one.util.streamex",
|
||||
"it.unimi.dsi.fastutil",
|
||||
"kotlinx.collections.immutable",
|
||||
"com.fasterxml",
|
||||
"org.codehaus"
|
||||
)
|
||||
|
||||
// The shaded compiler "dummy" is used to rewrite dependencies in projects that are used with the embeddable compiler
|
||||
// on the runtime and use some shaded dependencies from the compiler
|
||||
// To speed-up rewriting process we want to have this dummy as small as possible.
|
||||
// But due to the shadow plugin bug (https://github.com/johnrengelman/shadow/issues/262) it is not possible to use
|
||||
// packagesToRelocate list to for the include list. Therefore the exclude list has to be created.
|
||||
val packagesToExcludeFromDummy =
|
||||
listOf(
|
||||
"org/jetbrains/kotlin/**",
|
||||
"org/intellij/lang/annotations/**",
|
||||
"org/jetbrains/jps/**",
|
||||
"META-INF/**",
|
||||
"com/sun/jna/**",
|
||||
"com/thoughtworks/xstream/**",
|
||||
"javaslang/**",
|
||||
"*.proto",
|
||||
"messages/**",
|
||||
"net/sf/cglib/**",
|
||||
"one/util/streamex/**",
|
||||
"org/iq80/snappy/**",
|
||||
"org/jline/**",
|
||||
"org/xmlpull/**",
|
||||
"*.txt"
|
||||
)
|
||||
|
||||
private fun ShadowJar.configureEmbeddableCompilerRelocation(withJavaxInject: Boolean = true) {
|
||||
relocate("com.google.protobuf", "org.jetbrains.kotlin.protobuf")
|
||||
packagesToRelocate.forEach {
|
||||
relocate(it, "$kotlinEmbeddableRootPackage.$it")
|
||||
}
|
||||
if (withJavaxInject) {
|
||||
relocate("javax.inject", "$kotlinEmbeddableRootPackage.javax.inject")
|
||||
}
|
||||
relocate("org.fusesource", "$kotlinEmbeddableRootPackage.org.fusesource") {
|
||||
// TODO: remove "it." after #KT-12848 get addressed
|
||||
exclude("org.fusesource.jansi.internal.CLibrary")
|
||||
}
|
||||
}
|
||||
|
||||
private fun Project.compilerShadowJar(taskName: String, body: ShadowJar.() -> Unit): TaskProvider<ShadowJar> {
|
||||
|
||||
val compilerJar = configurations.getOrCreate("compilerJar").apply {
|
||||
isCanBeConsumed = false
|
||||
isCanBeResolved = true
|
||||
attributes {
|
||||
attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME))
|
||||
attribute(LibraryElements.LIBRARY_ELEMENTS_ATTRIBUTE, objects.named(LibraryElements.JAR))
|
||||
}
|
||||
}
|
||||
|
||||
dependencies.add(compilerJar.name, dependencies.project(":kotlin-compiler")) { isTransitive = false }
|
||||
|
||||
return tasks.register<ShadowJar>(taskName) {
|
||||
destinationDirectory.set(project.file(File(buildDir, "libs")))
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
from(compilerJar)
|
||||
body()
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.embeddableCompiler(taskName: String = "embeddable", body: ShadowJar.() -> Unit = {}): TaskProvider<ShadowJar> =
|
||||
compilerShadowJar(taskName) {
|
||||
configureEmbeddableCompilerRelocation()
|
||||
body()
|
||||
}
|
||||
|
||||
fun Project.compilerDummyForDependenciesRewriting(
|
||||
taskName: String = "compilerDummy", body: ShadowJar.() -> Unit = {}
|
||||
): TaskProvider<out Jar> =
|
||||
compilerShadowJar(taskName) {
|
||||
exclude(packagesToExcludeFromDummy)
|
||||
body()
|
||||
}
|
||||
const val COMPILER_DUMMY_JAR_CONFIGURATION_NAME = "compilerDummyJar"
|
||||
|
||||
fun Project.compilerDummyJar(task: TaskProvider<out Jar>, body: Jar.() -> Unit = {}) {
|
||||
configurations.getOrCreate(COMPILER_DUMMY_JAR_CONFIGURATION_NAME).apply {
|
||||
isCanBeResolved = false
|
||||
isCanBeConsumed = true
|
||||
}
|
||||
|
||||
task.configure(body)
|
||||
addArtifact(COMPILER_DUMMY_JAR_CONFIGURATION_NAME, task)
|
||||
}
|
||||
|
||||
const val EMBEDDABLE_COMPILER_TASK_NAME = "embeddable"
|
||||
fun Project.embeddableCompilerDummyForDependenciesRewriting(
|
||||
taskName: String = EMBEDDABLE_COMPILER_TASK_NAME,
|
||||
body: ShadowJar.() -> Unit = {}
|
||||
): TaskProvider<ShadowJar> {
|
||||
val compilerDummyJar = configurations.getOrCreate(COMPILER_DUMMY_JAR_CONFIGURATION_NAME).apply {
|
||||
isCanBeResolved = true
|
||||
isCanBeConsumed = false
|
||||
}
|
||||
|
||||
dependencies.add(
|
||||
compilerDummyJar.name,
|
||||
dependencies.project(":kotlin-compiler-embeddable", configuration = COMPILER_DUMMY_JAR_CONFIGURATION_NAME)
|
||||
)
|
||||
|
||||
return tasks.register<ShadowJar>(taskName) {
|
||||
destinationDirectory.set(project.file(File(buildDir, "libs")))
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
from(compilerDummyJar)
|
||||
configureEmbeddableCompilerRelocation(withJavaxInject = false)
|
||||
body()
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.rewriteDepsToShadedJar(
|
||||
originalJarTask: TaskProvider<out Jar>, shadowJarTask: TaskProvider<ShadowJar>, body: Jar.() -> Unit = {}
|
||||
): TaskProvider<ShadowJar> {
|
||||
originalJarTask.configure {
|
||||
archiveClassifier.set("original")
|
||||
}
|
||||
|
||||
|
||||
shadowJarTask.configure {
|
||||
dependsOn(originalJarTask)
|
||||
from(originalJarTask)// { include("**") }
|
||||
|
||||
// When Gradle traverses the inputs, reject the shaded compiler JAR,
|
||||
// which leads to the content of that JAR being excluded as well:
|
||||
exclude {
|
||||
// Docstring says `file` never returns null, but it does
|
||||
@Suppress("UNNECESSARY_SAFE_CALL", "SAFE_CALL_WILL_CHANGE_NULLABILITY")
|
||||
it.file?.name?.startsWith("kotlin-compiler-embeddable") ?: false
|
||||
}
|
||||
|
||||
archiveClassifier.set("original")
|
||||
body()
|
||||
}
|
||||
return shadowJarTask
|
||||
}
|
||||
|
||||
fun Project.rewriteDepsToShadedCompiler(originalJarTask: TaskProvider<out Jar>, body: Jar.() -> Unit = {}): TaskProvider<ShadowJar> =
|
||||
rewriteDepsToShadedJar(originalJarTask, embeddableCompilerDummyForDependenciesRewriting(), body)
|
||||
|
||||
fun Project.rewriteDefaultJarDepsToShadedCompiler(body: Jar.() -> Unit = {}): TaskProvider<ShadowJar> =
|
||||
rewriteDepsToShadedJar(tasks.named<Jar>("jar"), embeddableCompilerDummyForDependenciesRewriting(), body)
|
||||
+113
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
import com.gradle.publish.PluginBundleExtension
|
||||
import plugins.signLibraryPublication
|
||||
|
||||
plugins {
|
||||
kotlin("jvm")
|
||||
`java-gradle-plugin`
|
||||
`maven-publish`
|
||||
id("com.gradle.plugin-publish")
|
||||
}
|
||||
|
||||
// Enable signing for publications into Gradle Plugin Portal
|
||||
val signPublication = !version.toString().contains("-SNAPSHOT") &&
|
||||
(project.gradle.startParameter.taskNames.contains("publishPlugins") || signLibraryPublication)
|
||||
|
||||
configureCommonPublicationSettingsForGradle(signPublication)
|
||||
configureKotlinCompileTasksGradleCompatibility()
|
||||
addBomCheckTask()
|
||||
extensions.extraProperties["kotlin.stdlib.default.dependency"] = "false"
|
||||
|
||||
// common plugin bundle configuration
|
||||
gradlePlugin {
|
||||
website.set("https://kotlinlang.org/")
|
||||
vcsUrl.set("https://github.com/jetbrains/kotlin")
|
||||
plugins.configureEach {
|
||||
tags.add("kotlin")
|
||||
}
|
||||
}
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
withType<MavenPublication>().configureEach {
|
||||
if (name.endsWith("PluginMarkerMaven")) {
|
||||
pom {
|
||||
// https://github.com/gradle/gradle/issues/8754
|
||||
// and https://github.com/gradle/gradle/issues/6155
|
||||
packaging = "pom"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
tasks {
|
||||
named("install") {
|
||||
dependsOn(named("validatePlugins"))
|
||||
}
|
||||
}
|
||||
|
||||
val commonSourceSet = createGradleCommonSourceSet()
|
||||
reconfigureMainSourcesSetForGradlePlugin(commonSourceSet)
|
||||
publishShadowedJar(sourceSets[SourceSet.MAIN_SOURCE_SET_NAME], commonSourceSet)
|
||||
|
||||
// Disabling this task, so "com.gradle.plugin-publish" will not publish unshadowed jar into Gradle Plugin Portal
|
||||
// Without it 'jar' task is asked to run by "com.gradle.plugin-publish" even if artifacts are removed. The problem
|
||||
// is that 'jar' task runs after shadow task plus their outputs has the same name leading to '.jar' file overwrite.
|
||||
tasks.named("jar") {
|
||||
enabled = false
|
||||
}
|
||||
|
||||
if (!kotlinBuildProperties.isInJpsBuildIdeaSync) {
|
||||
// Used for Gradle 7.0 version
|
||||
val gradle70SourceSet = createGradlePluginVariant(
|
||||
GradlePluginVariant.GRADLE_70,
|
||||
commonSourceSet = commonSourceSet
|
||||
)
|
||||
publishShadowedJar(gradle70SourceSet, commonSourceSet)
|
||||
|
||||
// Used for Gradle 7.1+ versions
|
||||
val gradle71SourceSet = createGradlePluginVariant(
|
||||
GradlePluginVariant.GRADLE_71,
|
||||
commonSourceSet = commonSourceSet
|
||||
)
|
||||
publishShadowedJar(gradle71SourceSet, commonSourceSet)
|
||||
|
||||
// Used for Gradle 7.4+ versions
|
||||
val gradle74SourceSet = createGradlePluginVariant(
|
||||
GradlePluginVariant.GRADLE_74,
|
||||
commonSourceSet = commonSourceSet
|
||||
)
|
||||
publishShadowedJar(gradle74SourceSet, commonSourceSet)
|
||||
|
||||
// Used for Gradle 7.5+ versions
|
||||
val gradle75SourceSet = createGradlePluginVariant(
|
||||
GradlePluginVariant.GRADLE_75,
|
||||
commonSourceSet = commonSourceSet
|
||||
)
|
||||
publishShadowedJar(gradle75SourceSet, commonSourceSet)
|
||||
|
||||
// Used for Gradle 7.6+ versions
|
||||
val gradle76SourceSet = createGradlePluginVariant(
|
||||
GradlePluginVariant.GRADLE_76,
|
||||
commonSourceSet = commonSourceSet
|
||||
)
|
||||
publishShadowedJar(gradle76SourceSet, commonSourceSet)
|
||||
|
||||
// Used for Gradle 8.0+ versions
|
||||
val gradle80SourceSet = createGradlePluginVariant(
|
||||
GradlePluginVariant.GRADLE_80,
|
||||
commonSourceSet = commonSourceSet
|
||||
)
|
||||
publishShadowedJar(gradle80SourceSet, commonSourceSet)
|
||||
|
||||
// Used for Gradle 8.1+ versions
|
||||
val gradle81SourceSet = createGradlePluginVariant(
|
||||
GradlePluginVariant.GRADLE_81,
|
||||
commonSourceSet = commonSourceSet
|
||||
)
|
||||
publishShadowedJar(gradle81SourceSet, commonSourceSet)
|
||||
}
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
import plugins.KotlinBuildPublishingPlugin.Companion.DEFAULT_MAIN_PUBLICATION_NAME
|
||||
import plugins.signLibraryPublication
|
||||
|
||||
plugins {
|
||||
`java-library`
|
||||
kotlin("jvm")
|
||||
`maven-publish`
|
||||
}
|
||||
|
||||
configureCommonPublicationSettingsForGradle(signLibraryPublication)
|
||||
configureKotlinCompileTasksGradleCompatibility()
|
||||
addBomCheckTask()
|
||||
extensions.extraProperties["kotlin.stdlib.default.dependency"] = "false"
|
||||
|
||||
val commonSourceSet = createGradleCommonSourceSet()
|
||||
reconfigureMainSourcesSetForGradlePlugin(commonSourceSet)
|
||||
|
||||
// Used for Gradle 7.0 version
|
||||
createGradlePluginVariant(
|
||||
GradlePluginVariant.GRADLE_70,
|
||||
commonSourceSet = commonSourceSet,
|
||||
isGradlePlugin = false
|
||||
)
|
||||
|
||||
// Used for Gradle 7.1+ versions
|
||||
createGradlePluginVariant(
|
||||
GradlePluginVariant.GRADLE_71,
|
||||
commonSourceSet = commonSourceSet,
|
||||
isGradlePlugin = false
|
||||
)
|
||||
|
||||
// Used for Gradle 7.4+ versions
|
||||
createGradlePluginVariant(
|
||||
GradlePluginVariant.GRADLE_74,
|
||||
commonSourceSet = commonSourceSet,
|
||||
isGradlePlugin = false
|
||||
)
|
||||
|
||||
// Used for Gradle 7.5+ versions
|
||||
createGradlePluginVariant(
|
||||
GradlePluginVariant.GRADLE_75,
|
||||
commonSourceSet = commonSourceSet,
|
||||
isGradlePlugin = false
|
||||
)
|
||||
|
||||
// Used for Gradle 7.6+ versions
|
||||
createGradlePluginVariant(
|
||||
GradlePluginVariant.GRADLE_76,
|
||||
commonSourceSet = commonSourceSet,
|
||||
isGradlePlugin = false
|
||||
)
|
||||
|
||||
// Used for Gradle 8.0+ versions
|
||||
createGradlePluginVariant(
|
||||
GradlePluginVariant.GRADLE_80,
|
||||
commonSourceSet = commonSourceSet,
|
||||
isGradlePlugin = false
|
||||
)
|
||||
|
||||
// Used for Gradle 8.1+ versions
|
||||
createGradlePluginVariant(
|
||||
GradlePluginVariant.GRADLE_81,
|
||||
commonSourceSet = commonSourceSet,
|
||||
isGradlePlugin = false
|
||||
)
|
||||
|
||||
publishing {
|
||||
publications {
|
||||
register<MavenPublication>(DEFAULT_MAIN_PUBLICATION_NAME) {
|
||||
from(components["java"])
|
||||
suppressAllPomMetadataWarnings() // Don't warn about additional published variants
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
@file:Suppress("PackageDirectoryMismatch")
|
||||
package org.jetbrains.kotlin.ideaExt
|
||||
|
||||
import org.gradle.api.NamedDomainObjectContainer
|
||||
import org.gradle.api.plugins.ExtensionAware
|
||||
import org.gradle.kotlin.dsl.configure
|
||||
import org.gradle.plugins.ide.idea.model.IdeaProject
|
||||
import org.jetbrains.gradle.ext.*
|
||||
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
fun org.gradle.api.Project.idea(configure: org.gradle.plugins.ide.idea.model.IdeaModel.() -> Unit): Unit =
|
||||
(this as org.gradle.api.plugins.ExtensionAware).extensions.configure("idea", configure)
|
||||
|
||||
fun IdeaProject.settings(block: ProjectSettings.() -> Unit) =
|
||||
(this@settings as ExtensionAware).extensions.configure(block)
|
||||
|
||||
fun ProjectSettings.compiler(block: IdeaCompilerConfiguration.() -> Unit) =
|
||||
(this@compiler as ExtensionAware).extensions.configure(block)
|
||||
|
||||
fun ProjectSettings.delegateActions(block: ActionDelegationConfig.() -> Unit) =
|
||||
(this@delegateActions as ExtensionAware).extensions.configure(block)
|
||||
|
||||
fun ProjectSettings.runConfigurations(block: RunConfigurationContainer.() -> Unit) =
|
||||
(this@runConfigurations as ExtensionAware).extensions.configure("runConfigurations", block)
|
||||
|
||||
inline fun <reified T: RunConfiguration> RunConfigurationContainer.defaults(noinline block: T.() -> Unit) =
|
||||
defaults(T::class.java, block)
|
||||
|
||||
fun RunConfigurationContainer.junit(name: String, block: JUnit.() -> Unit) =
|
||||
create(name, JUnit::class.java, block)
|
||||
|
||||
fun RunConfigurationContainer.application(name: String, block: Application.() -> Unit) =
|
||||
create(name, Application::class.java, block)
|
||||
|
||||
fun ProjectSettings.ideArtifacts(block: NamedDomainObjectContainer<org.jetbrains.gradle.ext.TopLevelArtifact>.() -> Unit) =
|
||||
(this@ideArtifacts as ExtensionAware).extensions.configure("ideArtifacts", block)
|
||||
@@ -0,0 +1,39 @@
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.kotlin.dsl.extra
|
||||
import org.gradle.kotlin.dsl.project
|
||||
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
val Project.intellijVersion
|
||||
get() = rootProject.extra["versions.intellijSdk"]
|
||||
|
||||
fun Project.intellijCore() = dependencies.project(":dependencies:intellij-core")
|
||||
fun Project.intellijUtilRt() = "com.jetbrains.intellij.platform:util-rt:$intellijVersion"
|
||||
|
||||
fun Project.jpsModel() = "com.jetbrains.intellij.platform:jps-model:$intellijVersion"
|
||||
fun Project.jpsModelSerialization() = "com.jetbrains.intellij.platform:jps-model-serialization:$intellijVersion"
|
||||
fun Project.jpsModelImpl() = "com.jetbrains.intellij.platform:jps-model-impl:$intellijVersion"
|
||||
fun Project.jpsBuildTest() = "com.jetbrains.intellij.idea:jps-build-test:$intellijVersion"
|
||||
fun Project.jpsBuild() = "com.jetbrains.intellij.platform:jps-build:$intellijVersion"
|
||||
fun Project.testFramework() = "com.jetbrains.intellij.platform:test-framework:$intellijVersion"
|
||||
fun Project.devKitJps() = "com.jetbrains.intellij.devkit:devkit-jps:$intellijVersion"
|
||||
fun Project.intellijPlatformUtil() = "com.jetbrains.intellij.platform:util:$intellijVersion"
|
||||
fun Project.intellijJavaRt() = "com.jetbrains.intellij.java:java-rt:$intellijVersion"
|
||||
fun Project.intellijAnalysis() = "com.jetbrains.intellij.platform:analysis:$intellijVersion"
|
||||
fun Project.intellijResources() = "com.jetbrains.intellij.platform:resources:$intellijVersion"
|
||||
|
||||
/**
|
||||
* Runtime version of annotations that are already in Kotlin stdlib (historically Kotlin has older version of this one).
|
||||
*
|
||||
* SHOULD NOT BE USED IN COMPILE CLASSPATH!
|
||||
*
|
||||
* `@NonNull`, `@Nullabe` from `idea/annotations.jar` has `TYPE` target which leads to different types treatment in Kotlin compiler.
|
||||
* On the other hand, `idea/annotations.jar` contains org/jetbrains/annotations/Async annations which is required for IDEA debugger.
|
||||
*
|
||||
* So, we are excluding `annotaions.jar` from all other `kotlin.build` and using this one for runtime only
|
||||
* to avoid accidentally including `annotations.jar` by calling `intellijDep()`.
|
||||
*/
|
||||
fun Project.intellijRuntimeAnnotations() = "org.jetbrains:annotations:${rootProject.extra["versions.annotations"]}"
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// usages in build scripts are not tracked properly
|
||||
@file:Suppress("unused")
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.ModuleDependency
|
||||
import org.gradle.api.artifacts.dsl.RepositoryHandler
|
||||
import org.gradle.api.artifacts.repositories.IvyArtifactRepository
|
||||
import org.gradle.kotlin.dsl.extra
|
||||
import java.io.File
|
||||
|
||||
private fun Project.kotlinBuildLocalDependenciesDir(): File =
|
||||
(findProperty("kotlin.build.dependencies.dir") as String?)?.let(::File)
|
||||
?: rootProject.gradle.gradleUserHomeDir.resolve("kotlin-build-dependencies")
|
||||
|
||||
private fun Project.kotlinBuildLocalRepoDir(): File = kotlinBuildLocalDependenciesDir().resolve("repo")
|
||||
|
||||
fun Project.ideModuleName() = when (IdeVersionConfigurator.currentIde.kind) {
|
||||
Ide.Kind.AndroidStudio -> "android-studio-ide"
|
||||
Ide.Kind.IntelliJ -> "ideaIC"
|
||||
}
|
||||
|
||||
private fun Project.ideModuleVersion(forIde: Boolean) = when (IdeVersionConfigurator.currentIde.kind) {
|
||||
Ide.Kind.AndroidStudio -> rootProject.findProperty("versions.androidStudioBuild")
|
||||
Ide.Kind.IntelliJ -> {
|
||||
if (forIde) {
|
||||
intellijSdkVersionForIde()
|
||||
?: error("Please specify 'attachedIntellijVersion' in your local.properties")
|
||||
} else {
|
||||
rootProject.findProperty("versions.intellijSdk")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.intellijSdkVersionForIde(): String? {
|
||||
val majorVersion = kotlinBuildProperties.getOrNull("attachedIntellijVersion") as? String ?: return null
|
||||
return rootProject.findProperty("versions.intellijSdk.forIde.$majorVersion") as? String
|
||||
}
|
||||
|
||||
fun RepositoryHandler.kotlinBuildLocalRepo(project: Project): IvyArtifactRepository = ivy {
|
||||
val baseDir = project.kotlinBuildLocalRepoDir()
|
||||
url = baseDir.toURI()
|
||||
|
||||
patternLayout {
|
||||
ivy("[organisation]/[module]/[revision]/[module].ivy.xml")
|
||||
ivy("[organisation]/[module]/[revision]/ivy/[module].ivy.xml")
|
||||
ivy("[organisation]/${project.ideModuleName()}/[revision]/ivy/[module].ivy.xml") // bundled plugins
|
||||
|
||||
artifact("[organisation]/[module]/[revision]/artifacts/lib/[artifact](-[classifier]).[ext]")
|
||||
artifact("[organisation]/[module]/[revision]/artifacts/[artifact](-[classifier]).[ext]")
|
||||
artifact("[organisation]/intellij-core/[revision]/artifacts/[artifact](-[classifier]).[ext]")
|
||||
artifact("[organisation]/${project.ideModuleName()}/[revision]/artifacts/plugins/[module]/lib/[artifact](-[classifier]).[ext]") // bundled plugins
|
||||
artifact("[organisation]/sources/[artifact]-[revision](-[classifier]).[ext]")
|
||||
artifact("[organisation]/[module]/[revision]/[artifact](-[classifier]).[ext]")
|
||||
}
|
||||
|
||||
metadataSources {
|
||||
ivyDescriptor()
|
||||
}
|
||||
}
|
||||
|
||||
/* <used only for cooperative development for non kt-master branches> */
|
||||
@JvmOverloads
|
||||
fun Project.intellijDep(module: String? = null, forIde: Boolean = false) =
|
||||
"kotlin.build:${module ?: ideModuleName()}:${ideModuleVersion(forIde)}"
|
||||
|
||||
|
||||
fun Project.intellijCoreDep() = "kotlin.build:intellij-core:${rootProject.extra["versions.intellijSdk"]}"
|
||||
|
||||
fun Project.intellijPluginDep(plugin: String, forIde: Boolean = false) = intellijDep(plugin, forIde)
|
||||
|
||||
/* </used only for cooperative development for non kt-master branches> */
|
||||
|
||||
|
||||
/* <used only for cooperative development for kt-master branch> */
|
||||
fun Project.intellijMavenDep(subsystem: String, artifact: String) =
|
||||
"com.jetbrains.$subsystem:$artifact:${ideModuleVersion(forIde = true)}"
|
||||
|
||||
|
||||
/* </used only for cooperative development for kt-master branch> */
|
||||
|
||||
|
||||
fun ModuleDependency.includeJars(vararg names: String, rootProject: Project? = null) {
|
||||
names.forEach {
|
||||
var baseName = it.removeSuffix(".jar")
|
||||
if (rootProject != null && rootProject.extra.has("ignore.$baseName")) {
|
||||
return@forEach
|
||||
}
|
||||
if (rootProject != null && rootProject.extra.has("versions.$baseName")) {
|
||||
baseName += "-${rootProject.extra["versions.$baseName"]}"
|
||||
}
|
||||
artifact {
|
||||
name = baseName
|
||||
type = "jar"
|
||||
extension = "jar"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Workaround. Top-level Kotlin function in a default package can't be called from a non-default package
|
||||
object IntellijRootUtils {
|
||||
fun getRepositoryRootDir(project: Project): File = with(project.rootProject) {
|
||||
return File(kotlinBuildLocalRepoDir(), "kotlin.build")
|
||||
}
|
||||
|
||||
fun getIntellijRootDir(project: Project): File = with(project.rootProject) {
|
||||
return File(
|
||||
getRepositoryRootDir(this),
|
||||
"${ideModuleName()}/${ideModuleVersion(forIde = false)}/artifacts"
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.ideaHomePathForTests() = rootProject.buildDir.resolve("ideaHomeForTests")
|
||||
|
||||
fun Project.ideaBuildNumberFileForTests() = File(ideaHomePathForTests(), "build.txt")
|
||||
|
||||
fun Project.writeIdeaBuildNumberForTests() {
|
||||
ideaHomePathForTests().mkdirs()
|
||||
ideaBuildNumberFileForTests().writeText("IC-${rootProject.extra["versions.intellijSdk"]}")
|
||||
}
|
||||
@@ -0,0 +1,213 @@
|
||||
import TestProperty.*
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.tasks.testing.Test
|
||||
import org.gradle.kotlin.dsl.project
|
||||
import java.io.File
|
||||
|
||||
private enum class TestProperty(shortName: String) {
|
||||
// Use a separate Gradle property to pass Kotlin/Native home to tests: "kotlin.internal.native.test.nativeHome".
|
||||
// Don't use "kotlin.native.home" and similar properties for this purpose, as these properties may have undesired
|
||||
// effect on other Gradle tasks (ex: :kotlin-native:dist) that might be executed along with test task.
|
||||
KOTLIN_NATIVE_HOME("nativeHome"),
|
||||
COMPILER_CLASSPATH("compilerClasspath"),
|
||||
CUSTOM_KLIBS("customKlibs"),
|
||||
TEST_TARGET("target"),
|
||||
TEST_MODE("mode"),
|
||||
FORCE_STANDALONE("forceStandalone"),
|
||||
COMPILE_ONLY("compileOnly"),
|
||||
OPTIMIZATION_MODE("optimizationMode"),
|
||||
USE_THREAD_STATE_CHECKER("useThreadStateChecker"),
|
||||
GC_TYPE("gcType"),
|
||||
GC_SCHEDULER("gcScheduler"),
|
||||
ALLOCATOR("alloc"),
|
||||
CACHE_MODE("cacheMode"),
|
||||
EXECUTION_TIMEOUT("executionTimeout"),
|
||||
SANITIZER("sanitizer"),
|
||||
TEAMCITY("teamcity");
|
||||
|
||||
val fullName = "kotlin.internal.native.test.$shortName"
|
||||
}
|
||||
|
||||
private sealed class ComputedTestProperty {
|
||||
abstract val name: String
|
||||
abstract val value: String?
|
||||
|
||||
class Normal(override val name: String, override val value: String?) : ComputedTestProperty()
|
||||
class Lazy(override val name: String, private val lazyValue: kotlin.Lazy<String?>) : ComputedTestProperty() {
|
||||
override val value get() = lazyValue.value
|
||||
}
|
||||
}
|
||||
|
||||
private class ComputedTestProperties(private val task: Test) {
|
||||
private val computedProperties = arrayListOf<ComputedTestProperty>()
|
||||
|
||||
fun Project.compute(property: TestProperty, defaultValue: () -> String? = { null }) {
|
||||
val gradleValue = readFromGradle(property)
|
||||
computedProperties += ComputedTestProperty.Normal(property.fullName, gradleValue ?: defaultValue())
|
||||
}
|
||||
|
||||
fun Project.computeLazy(property: TestProperty, defaultLazyValue: () -> Lazy<String?>) {
|
||||
val gradleValue = readFromGradle(property)
|
||||
computedProperties += if (gradleValue != null)
|
||||
ComputedTestProperty.Normal(property.fullName, gradleValue)
|
||||
else
|
||||
ComputedTestProperty.Lazy(property.fullName, defaultLazyValue())
|
||||
}
|
||||
|
||||
// Do not attempt to read the property from Gradle. Instead, set it based on the lambda return value.
|
||||
fun computePrivate(property: TestProperty, value: () -> String) {
|
||||
computedProperties += ComputedTestProperty.Normal(property.fullName, value())
|
||||
}
|
||||
|
||||
fun lazyClassPath(builder: MutableList<File>.() -> Unit): Lazy<String?> = lazy(LazyThreadSafetyMode.NONE) {
|
||||
buildList(builder).takeIf { it.isNotEmpty() }?.joinToString(File.pathSeparator) { it.absolutePath }
|
||||
}
|
||||
|
||||
fun Project.readFromGradle(property: TestProperty): String? = findProperty(property.fullName)?.toString()
|
||||
|
||||
fun resolveAndApplyToTask() {
|
||||
computedProperties.forEach { computedProperty ->
|
||||
task.systemProperty(computedProperty.name, computedProperty.value ?: return@forEach)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun Test.ComputedTestProperties(init: ComputedTestProperties.() -> Unit): ComputedTestProperties =
|
||||
ComputedTestProperties(this).apply { init() }
|
||||
|
||||
fun Project.nativeTest(
|
||||
taskName: String,
|
||||
tag: String?,
|
||||
requirePlatformLibs: Boolean = false,
|
||||
customDependencies: List<Configuration> = emptyList(),
|
||||
customKlibDependencies: List<Configuration> = emptyList()
|
||||
) = projectTest(
|
||||
taskName,
|
||||
jUnitMode = JUnitMode.JUnit5,
|
||||
maxHeapSizeMb = 3072 // Extra heap space for Kotlin/Native compiler.
|
||||
) {
|
||||
group = "verification"
|
||||
|
||||
if (kotlinBuildProperties.isKotlinNativeEnabled) {
|
||||
workingDir = rootDir
|
||||
outputs.upToDateWhen {
|
||||
// Don't treat any test task as up-to-date, no matter what.
|
||||
// Note: this project should contain only test tasks, including ones that build binaries, and ones that run binaries.
|
||||
false
|
||||
}
|
||||
|
||||
// Effectively remove the limit for the amount of stack trace elements in Throwable.
|
||||
jvmArgs("-XX:MaxJavaStackTraceDepth=1000000")
|
||||
|
||||
// Double the stack size. This is needed to compile some marginal tests with extra-deep IR tree, which requires a lot of stack frames
|
||||
// for visiting it. Example: codegen/box/strings/concatDynamicWithConstants.kt
|
||||
// Such tests are successfully compiled in old test infra with the default 1 MB stack just by accident. New test infra requires ~55
|
||||
// additional stack frames more compared to the old one because of another launcher, etc. and it turns out this is not enough.
|
||||
jvmArgs("-Xss2m")
|
||||
|
||||
val availableCpuCores: Int = Runtime.getRuntime().availableProcessors()
|
||||
if (!kotlinBuildProperties.isTeamcityBuild
|
||||
&& minOf(kotlinBuildProperties.junit5NumberOfThreadsForParallelExecution ?: 16, availableCpuCores) > 4
|
||||
) {
|
||||
logger.info("$path JIT C2 compiler has been disabled")
|
||||
jvmArgs("-XX:TieredStopAtLevel=1") // Disable C2 if there are more than 4 CPUs at the host machine.
|
||||
}
|
||||
|
||||
// Compute test properties in advance. Make sure that the necessary dependencies are settled.
|
||||
// But do not resolve any configurations until the execution phase.
|
||||
val computedTestProperties = ComputedTestProperties {
|
||||
compute(KOTLIN_NATIVE_HOME) {
|
||||
val testTarget = readFromGradle(TEST_TARGET)
|
||||
if (testTarget != null) {
|
||||
dependsOn(":kotlin-native:${testTarget}CrossDist")
|
||||
if (requirePlatformLibs) dependsOn(":kotlin-native:${testTarget}PlatformLibs")
|
||||
} else {
|
||||
dependsOn(":kotlin-native:dist")
|
||||
if (requirePlatformLibs) dependsOn(":kotlin-native:distPlatformLibs")
|
||||
}
|
||||
project(":kotlin-native").projectDir.resolve("dist").absolutePath
|
||||
}
|
||||
|
||||
computeLazy(COMPILER_CLASSPATH) {
|
||||
val customNativeHome = readFromGradle(KOTLIN_NATIVE_HOME)
|
||||
|
||||
val kotlinNativeCompilerEmbeddable = if (customNativeHome == null)
|
||||
configurations.detachedConfiguration(
|
||||
dependencies.project(":kotlin-native-compiler-embeddable"),
|
||||
dependencies.module(commonDependency("org.jetbrains.intellij.deps:trove4j"))
|
||||
).also { dependsOn(it) }
|
||||
else
|
||||
null
|
||||
|
||||
customDependencies.forEach(::dependsOn)
|
||||
|
||||
lazyClassPath {
|
||||
if (customNativeHome == null) {
|
||||
addAll(kotlinNativeCompilerEmbeddable!!.files)
|
||||
} else {
|
||||
this += file(customNativeHome).resolve("konan/lib/kotlin-native-compiler-embeddable.jar")
|
||||
this += file(customNativeHome).resolve("konan/lib/trove4j.jar")
|
||||
}
|
||||
|
||||
customDependencies.flatMapTo(this) { it.files }
|
||||
}
|
||||
}
|
||||
|
||||
computeLazy(CUSTOM_KLIBS) {
|
||||
customKlibDependencies.forEach(::dependsOn)
|
||||
lazyClassPath { customKlibDependencies.flatMapTo(this) { it.files } }
|
||||
}
|
||||
|
||||
// Pass Gradle properties as JVM properties so test process can read them.
|
||||
compute(TEST_TARGET)
|
||||
compute(TEST_MODE)
|
||||
compute(FORCE_STANDALONE)
|
||||
compute(COMPILE_ONLY)
|
||||
compute(OPTIMIZATION_MODE)
|
||||
compute(USE_THREAD_STATE_CHECKER)
|
||||
compute(GC_TYPE)
|
||||
compute(GC_SCHEDULER)
|
||||
compute(ALLOCATOR)
|
||||
compute(CACHE_MODE)
|
||||
compute(EXECUTION_TIMEOUT)
|
||||
compute(SANITIZER)
|
||||
|
||||
// Pass whether tests are running at TeamCity.
|
||||
computePrivate(TEAMCITY) { kotlinBuildProperties.isTeamcityBuild.toString() }
|
||||
}
|
||||
|
||||
// Pass the current Gradle task name so test can use it in logging.
|
||||
environment("GRADLE_TASK_NAME", path)
|
||||
|
||||
useJUnitPlatform {
|
||||
tag?.let { includeTags(it) }
|
||||
}
|
||||
|
||||
doFirst {
|
||||
logger.info(
|
||||
buildString {
|
||||
appendLine("$path parallel test execution parameters:")
|
||||
append(" Available CPU cores = $availableCpuCores")
|
||||
systemProperties.filterKeys { it.startsWith("junit.jupiter") }.toSortedMap().forEach { (key, value) ->
|
||||
append("\n $key = $value")
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
// Compute lazy properties and apply them all as JVM process properties.
|
||||
// This forces to resolve the necessary configurations.
|
||||
computedTestProperties.resolveAndApplyToTask()
|
||||
}
|
||||
} else
|
||||
doFirst {
|
||||
throw GradleException(
|
||||
"""
|
||||
Can't run task $path. The Kotlin/Native part of the project is currently disabled.
|
||||
Make sure that "kotlin.native.enabled" is set to "true" in local.properties file, or is passed
|
||||
as a Gradle command-line parameter via "-Pkotlin.native.enabled=true".
|
||||
""".trimIndent()
|
||||
)
|
||||
}
|
||||
}
|
||||
+36
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:Suppress("PackageDirectoryMismatch")
|
||||
package org.jetbrains.kotlin.pill
|
||||
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
|
||||
@Suppress("unused")
|
||||
class JpsCompatiblePlugin : Plugin<Project> {
|
||||
override fun apply(project: Project) {
|
||||
project.configurations.maybeCreate(EmbeddedComponents.CONFIGURATION_NAME)
|
||||
project.extensions.create("pill", PillExtension::class.java)
|
||||
|
||||
// 'jpsTest' does not require the 'tests-jar' artifact
|
||||
project.configurations.create("jpsTest")
|
||||
|
||||
if (project == project.rootProject) {
|
||||
project.tasks.register("pill") {
|
||||
dependsOn(":pill:pill-importer:pill")
|
||||
|
||||
if (System.getProperty("pill.android.tests", "false") == "true") {
|
||||
TaskUtils.useAndroidSdk(this)
|
||||
TaskUtils.useAndroidJar(this)
|
||||
}
|
||||
}
|
||||
|
||||
project.tasks.register("unpill") {
|
||||
dependsOn(":pill:pill-importer:unpill")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:Suppress("PackageDirectoryMismatch")
|
||||
package org.jetbrains.kotlin.pill
|
||||
|
||||
import java.io.File
|
||||
import org.gradle.api.Project
|
||||
|
||||
open class PillExtension {
|
||||
/*
|
||||
* Here's how you can specify a custom variant:
|
||||
* `./gradlew pill -Dpill.variant=<NAME>`
|
||||
*/
|
||||
enum class Variant {
|
||||
BASE, // Includes compiler and IDE (default)
|
||||
FULL, // Includes compiler, IDE and Gradle plugin
|
||||
}
|
||||
|
||||
open var variant: Variant? = null
|
||||
|
||||
open var excludedDirs: List<File> = emptyList()
|
||||
|
||||
@Suppress("unused")
|
||||
fun Project.excludedDirs(vararg dirs: String) {
|
||||
excludedDirs = excludedDirs + dirs.map { File(projectDir, it) }
|
||||
}
|
||||
|
||||
@Suppress("unused")
|
||||
fun serialize() = mapOf<String, Any?>(
|
||||
"variant" to variant?.name,
|
||||
"excludedDirs" to excludedDirs
|
||||
)
|
||||
}
|
||||
+172
@@ -0,0 +1,172 @@
|
||||
/*
|
||||
* Copyright 2010-2018 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
import com.jakewharton.dex.DexMethod
|
||||
import com.jakewharton.dex.DexParser.Companion.toDexParser
|
||||
import org.gradle.api.DefaultTask
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.file.ProjectLayout
|
||||
import org.gradle.api.file.RegularFileProperty
|
||||
import org.gradle.api.model.ObjectFactory
|
||||
import org.gradle.api.provider.ListProperty
|
||||
import org.gradle.api.provider.Property
|
||||
import org.gradle.api.tasks.*
|
||||
import org.gradle.jvm.tasks.Jar
|
||||
import org.gradle.kotlin.dsl.property
|
||||
import javax.inject.Inject
|
||||
|
||||
@CacheableTask
|
||||
abstract class DexMethodCount @Inject constructor(objectFactory: ObjectFactory, layout: ProjectLayout) : DefaultTask() {
|
||||
|
||||
data class Counts(
|
||||
val total: Int,
|
||||
val totalOwnPackages: Int?,
|
||||
val totalOtherPackages: Int?,
|
||||
val byPackage: Map<String, Int>,
|
||||
val byClass: Map<String, Int>
|
||||
)
|
||||
|
||||
@get:InputFile
|
||||
@get:Classpath
|
||||
abstract val jarFile: RegularFileProperty
|
||||
|
||||
@get:Optional
|
||||
@get:Input
|
||||
abstract val ownPackages: ListProperty<String>
|
||||
|
||||
private val projectName: String = project.name
|
||||
|
||||
@get:Input
|
||||
val artifactOrArchiveName: Property<String> = objectFactory.property<String>().convention(projectName)
|
||||
|
||||
fun from(jar: TaskProvider<Jar>) {
|
||||
jarFile.set(jar.flatMap { it.archiveFile })
|
||||
artifactOrArchiveName.set(jar.flatMap { it.archiveBaseName.orElse(projectName) })
|
||||
}
|
||||
|
||||
@Internal // plain output properties are not supported, mark as internal to suppress warning from validatePlugins
|
||||
lateinit var counts: Counts
|
||||
|
||||
@get:OutputFile
|
||||
val detailOutputFile: RegularFileProperty = objectFactory.fileProperty().value(artifactOrArchiveName.flatMap { layout.buildDirectory.file("$it-method-count.txt") })
|
||||
|
||||
@TaskAction
|
||||
fun invoke() {
|
||||
val methods = jarFile.get().asFile.toDexParser().listMethods()
|
||||
val counts = methods.getCounts().also { this.counts = it }
|
||||
outputDetails(counts)
|
||||
}
|
||||
|
||||
private fun List<DexMethod>.getCounts(): Counts {
|
||||
val byPackage = this.groupingBy { it.`package` }.eachCount()
|
||||
val byClass = this.groupingBy { it.declaringTypeFqn }.eachCount()
|
||||
|
||||
val ownPackages = ownPackages.map { list -> list.map { "$it." } }
|
||||
val byOwnPackages = if (ownPackages.isPresent) {
|
||||
this.partition { method -> ownPackages.get().any { method.declaringTypeFqn.startsWith(it) } }.let {
|
||||
it.first.size to it.second.size
|
||||
}
|
||||
} else (null to null)
|
||||
|
||||
return Counts(
|
||||
total = this.size,
|
||||
totalOwnPackages = byOwnPackages.first,
|
||||
totalOtherPackages = byOwnPackages.second,
|
||||
byPackage = byPackage,
|
||||
byClass = byClass
|
||||
)
|
||||
}
|
||||
|
||||
private fun outputDetails(counts: Counts) {
|
||||
detailOutputFile.get().asFile.printWriter().use { writer ->
|
||||
writer.println("${counts.total.padRight()}\tTotal methods")
|
||||
ownPackages.orNull?.let { packages ->
|
||||
writer.println("${counts.totalOwnPackages?.padRight()}\tTotal methods from packages ${packages.joinToString { "$it.*" }}")
|
||||
writer.println("${counts.totalOtherPackages?.padRight()}\tTotal methods from other packages")
|
||||
}
|
||||
writer.println()
|
||||
writer.println("Method count by package:")
|
||||
counts.byPackage.forEach { (name, count) ->
|
||||
writer.println("${count.padRight()}\t$name")
|
||||
}
|
||||
writer.println()
|
||||
writer.println("Method count by class:")
|
||||
counts.byClass.forEach { (name, count) ->
|
||||
writer.println("${count.padRight()}\t$name")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
abstract class DexMethodCountStats : DefaultTask() {
|
||||
@get:InputFile
|
||||
internal abstract val inputFile: RegularFileProperty
|
||||
|
||||
@get:Input
|
||||
internal abstract val artifactOrArchiveName: Property<String>
|
||||
|
||||
@get:Input
|
||||
@get:Optional
|
||||
internal abstract val ownPackages: ListProperty<String>
|
||||
|
||||
private val isTeamCityBuild = project.kotlinBuildProperties.isTeamcityBuild
|
||||
|
||||
@TaskAction
|
||||
private fun printStats() {
|
||||
val artifactOrArchiveName = artifactOrArchiveName.get()
|
||||
inputFile.get().asFile.reader().useLines { lines ->
|
||||
fun String.getStatValue() = substringBefore("\t").trim()
|
||||
|
||||
val statsLineCount = if (!ownPackages.isPresent) 1 else 3
|
||||
val stats = lines.take(statsLineCount).map { it.getStatValue() }.toList()
|
||||
|
||||
val total = stats[0]
|
||||
logger.lifecycle("Artifact $artifactOrArchiveName, total methods: $total")
|
||||
|
||||
if (isTeamCityBuild) {
|
||||
println("##teamcity[buildStatisticValue key='DexMethodCount_${artifactOrArchiveName}' value='$total']")
|
||||
}
|
||||
|
||||
ownPackages.map { packages ->
|
||||
val totalOwnPackages = stats[1]
|
||||
val totalOtherPackages = stats[2]
|
||||
|
||||
logger.lifecycle("Artifact $artifactOrArchiveName, total methods from packages ${packages.joinToString { "$it.*" }}: $totalOwnPackages")
|
||||
logger.lifecycle("Artifact $artifactOrArchiveName, total methods from other packages: $totalOtherPackages")
|
||||
|
||||
if (project.kotlinBuildProperties.isTeamcityBuild) {
|
||||
println("##teamcity[buildStatisticValue key='DexMethodCount_${artifactOrArchiveName}_OwnPackages' value='$totalOwnPackages']")
|
||||
println("##teamcity[buildStatisticValue key='DexMethodCount_${artifactOrArchiveName}_OtherPackages' value='$totalOtherPackages']")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.printStats(dexMethodCount: TaskProvider<DexMethodCount>) {
|
||||
val dexMethodCountStats = tasks.register("dexMethodCountStats", DexMethodCountStats::class.java) {
|
||||
inputFile.set(dexMethodCount.flatMap { it.detailOutputFile })
|
||||
artifactOrArchiveName.set(dexMethodCount.flatMap { it.artifactOrArchiveName })
|
||||
ownPackages.set(dexMethodCount.flatMap { it.ownPackages })
|
||||
}
|
||||
|
||||
dexMethodCount.configure {
|
||||
finalizedBy(dexMethodCountStats)
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.dexMethodCount(action: DexMethodCount.() -> Unit): TaskProvider<DexMethodCount> {
|
||||
val dexMethodCount = tasks.register("dexMethodCount", DexMethodCount::class.java, action)
|
||||
printStats(dexMethodCount)
|
||||
tasks.getByName("check").dependsOn(dexMethodCount)
|
||||
return dexMethodCount
|
||||
}
|
||||
|
||||
private val DexMethod.`package`: String get() = declaringTypeFqn.substringBeforeLast('.')
|
||||
private fun Int.padRight() = toString().padStart(5, ' ')
|
||||
|
||||
private val DexMethod.declaringTypeFqn: String get() {
|
||||
return this.render(false).substringBefore(' ')
|
||||
}
|
||||
+204
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package plugins
|
||||
|
||||
import capitalize
|
||||
import org.gradle.api.Plugin
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.attributes.Usage
|
||||
import org.gradle.api.component.SoftwareComponentFactory
|
||||
import org.gradle.api.plugins.JavaBasePlugin
|
||||
import org.gradle.api.publish.PublishingExtension
|
||||
import org.gradle.api.publish.maven.MavenPublication
|
||||
import org.gradle.api.publish.maven.plugins.MavenPublishPlugin
|
||||
import org.gradle.api.publish.maven.tasks.PublishToMavenRepository
|
||||
import org.gradle.api.tasks.TaskProvider
|
||||
import org.gradle.kotlin.dsl.*
|
||||
import org.gradle.plugins.signing.SigningExtension
|
||||
import org.gradle.plugins.signing.SigningPlugin
|
||||
import java.util.*
|
||||
import javax.inject.Inject
|
||||
|
||||
class KotlinBuildPublishingPlugin @Inject constructor(
|
||||
private val componentFactory: SoftwareComponentFactory
|
||||
) : Plugin<Project> {
|
||||
override fun apply(target: Project): Unit = with(target) {
|
||||
apply<MavenPublishPlugin>()
|
||||
|
||||
val publishedRuntime = configurations.maybeCreate(RUNTIME_CONFIGURATION).apply {
|
||||
isCanBeConsumed = false
|
||||
isCanBeResolved = false
|
||||
attributes {
|
||||
attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_RUNTIME))
|
||||
}
|
||||
}
|
||||
|
||||
val publishedCompile = configurations.maybeCreate(COMPILE_CONFIGURATION).apply {
|
||||
isCanBeConsumed = false
|
||||
isCanBeResolved = false
|
||||
attributes {
|
||||
attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage.JAVA_API))
|
||||
}
|
||||
}
|
||||
|
||||
val kotlinLibraryComponent = componentFactory.adhoc(ADHOC_COMPONENT_NAME)
|
||||
components.add(kotlinLibraryComponent)
|
||||
kotlinLibraryComponent.addVariantsFromConfiguration(publishedCompile) { mapToMavenScope("compile") }
|
||||
kotlinLibraryComponent.addVariantsFromConfiguration(publishedRuntime) { mapToMavenScope("runtime") }
|
||||
|
||||
pluginManager.withPlugin("java-base") {
|
||||
val runtimeElements by configurations
|
||||
val apiElements by configurations
|
||||
|
||||
publishedRuntime.extendsFrom(runtimeElements)
|
||||
publishedCompile.extendsFrom(apiElements)
|
||||
|
||||
kotlinLibraryComponent.addVariantsFromConfiguration(runtimeElements) {
|
||||
mapToMavenScope("runtime")
|
||||
|
||||
if (configurationVariant.artifacts.any { JavaBasePlugin.UNPUBLISHABLE_VARIANT_ARTIFACTS.contains(it.type) }) {
|
||||
skip()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
configure<PublishingExtension> {
|
||||
publications {
|
||||
create<MavenPublication>(project.mainPublicationName) {
|
||||
from(kotlinLibraryComponent)
|
||||
|
||||
configureKotlinPomAttributes(project)
|
||||
}
|
||||
}
|
||||
}
|
||||
configureDefaultPublishing()
|
||||
}
|
||||
|
||||
companion object {
|
||||
const val DEFAULT_MAIN_PUBLICATION_NAME = "Main"
|
||||
const val MAIN_PUBLICATION_NAME_PROPERTY = "MainPublicationName"
|
||||
const val REPOSITORY_NAME = "Maven"
|
||||
const val ADHOC_COMPONENT_NAME = "kotlinLibrary"
|
||||
|
||||
const val COMPILE_CONFIGURATION = "publishedCompile"
|
||||
const val RUNTIME_CONFIGURATION = "publishedRuntime"
|
||||
}
|
||||
}
|
||||
|
||||
var Project.mainPublicationName: String
|
||||
get() {
|
||||
return if (project.extra.has(KotlinBuildPublishingPlugin.MAIN_PUBLICATION_NAME_PROPERTY))
|
||||
project.extra.get(KotlinBuildPublishingPlugin.MAIN_PUBLICATION_NAME_PROPERTY) as String
|
||||
else KotlinBuildPublishingPlugin.DEFAULT_MAIN_PUBLICATION_NAME
|
||||
}
|
||||
set(value) {
|
||||
project.extra.set(KotlinBuildPublishingPlugin.MAIN_PUBLICATION_NAME_PROPERTY, value)
|
||||
}
|
||||
|
||||
@OptIn(ExperimentalStdlibApi::class)
|
||||
private fun humanReadableName(name: String) =
|
||||
name.split("-").joinToString(separator = " ") { it.capitalize(Locale.ROOT) }
|
||||
|
||||
fun MavenPublication.configureKotlinPomAttributes(project: Project, explicitDescription: String? = null, packaging: String = "jar") {
|
||||
val publication = this
|
||||
pom {
|
||||
this.packaging = packaging
|
||||
name.set(humanReadableName(publication.artifactId))
|
||||
description.set(explicitDescription ?: project.description ?: humanReadableName(publication.artifactId))
|
||||
url.set("https://kotlinlang.org/")
|
||||
licenses {
|
||||
license {
|
||||
name.set("The Apache License, Version 2.0")
|
||||
url.set("http://www.apache.org/licenses/LICENSE-2.0.txt")
|
||||
}
|
||||
}
|
||||
scm {
|
||||
url.set("https://github.com/JetBrains/kotlin")
|
||||
connection.set("scm:git:https://github.com/JetBrains/kotlin.git")
|
||||
developerConnection.set("scm:git:https://github.com/JetBrains/kotlin.git")
|
||||
}
|
||||
developers {
|
||||
developer {
|
||||
name.set("Kotlin Team")
|
||||
organization.set("JetBrains")
|
||||
organizationUrl.set("https://www.jetbrains.com")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val Project.signLibraryPublication: Boolean
|
||||
get() = project.providers.gradleProperty("signingRequired").orNull?.toBoolean()
|
||||
?: project.providers.gradleProperty("isSonatypeRelease").orNull?.toBoolean()
|
||||
?: false
|
||||
|
||||
fun Project.configureDefaultPublishing(
|
||||
signingRequired: Boolean = signLibraryPublication
|
||||
) {
|
||||
configure<PublishingExtension> {
|
||||
repositories {
|
||||
maven {
|
||||
name = KotlinBuildPublishingPlugin.REPOSITORY_NAME
|
||||
url = file("${project.rootDir}/build/repo").toURI()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (signingRequired) {
|
||||
apply<SigningPlugin>()
|
||||
configureSigning()
|
||||
}
|
||||
|
||||
tasks.register("install") {
|
||||
dependsOn(tasks.named("publishToMavenLocal"))
|
||||
}
|
||||
|
||||
tasks.withType<PublishToMavenRepository>()
|
||||
.matching { it.name.endsWith("PublicationTo${KotlinBuildPublishingPlugin.REPOSITORY_NAME}Repository") }
|
||||
.all { configureRepository() }
|
||||
}
|
||||
|
||||
private fun Project.getSensitiveProperty(name: String): String? {
|
||||
return project.findProperty(name) as? String ?: System.getenv(name)
|
||||
}
|
||||
|
||||
private fun Project.configureSigning() {
|
||||
configure<SigningExtension> {
|
||||
sign(extensions.getByType<PublishingExtension>().publications) // all publications
|
||||
|
||||
val signKeyId = project.getSensitiveProperty("signKeyId")
|
||||
if (!signKeyId.isNullOrBlank()) {
|
||||
val signKeyPrivate = project.getSensitiveProperty("signKeyPrivate") ?: error("Parameter `signKeyPrivate` not found")
|
||||
val signKeyPassphrase = project.getSensitiveProperty("signKeyPassphrase") ?: error("Parameter `signKeyPassphrase` not found")
|
||||
useInMemoryPgpKeys(signKeyId, signKeyPrivate, signKeyPassphrase)
|
||||
} else {
|
||||
useGpgCmd()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun TaskProvider<PublishToMavenRepository>.configureRepository() =
|
||||
configure { configureRepository() }
|
||||
|
||||
private fun PublishToMavenRepository.configureRepository() {
|
||||
dependsOn(project.rootProject.tasks.named("preparePublication"))
|
||||
doFirst {
|
||||
val preparePublication = project.rootProject.tasks.named("preparePublication").get()
|
||||
val username: String? by preparePublication.extra
|
||||
val password: String? by preparePublication.extra
|
||||
val repoUrl: String by preparePublication.extra
|
||||
|
||||
repository.apply {
|
||||
url = project.uri(repoUrl)
|
||||
if (url.scheme != "file" && username != null && password != null) {
|
||||
credentials {
|
||||
this.username = username
|
||||
this.password = password
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
import io.ktor.client.*
|
||||
import io.ktor.client.request.*
|
||||
import io.ktor.client.statement.*
|
||||
import io.ktor.http.*
|
||||
import kotlinx.coroutines.runBlocking
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.kotlin.dsl.*
|
||||
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
fun Project.preparePublication() {
|
||||
tasks.register("preparePublication") {
|
||||
assert(project.version != "unspecified")
|
||||
|
||||
val repositoryProviders = mapOf<String?, String?>(
|
||||
"sonatype-nexus-staging" to "sonatype",
|
||||
"sonatype-nexus-snapshots" to "sonatype"
|
||||
)
|
||||
val isRelease: Boolean by extra(!project.version.toString().contains("-SNAPSHOT"))
|
||||
|
||||
val repo: String? = properties["deployRepo"]?.toString() ?: properties["deploy-repo"]?.toString()
|
||||
val repoProvider = repositoryProviders.getOrDefault(repo, repo)
|
||||
val isSonatypePublish: Boolean by extra(repoProvider == "sonatype")
|
||||
val isSonatypeRelease: Boolean by extra(isSonatypePublish && isRelease)
|
||||
|
||||
val deployRepoUrl = properties["deployRepoUrl"]?.toString() ?: properties["deploy-url"]?.toString()
|
||||
val deployFolder = properties["deployRepoFolder"]?.toString()
|
||||
?.let { "file://${rootProject.buildDir}/$it" }
|
||||
val sonatypeSnapshotsUrl = if (isSonatypePublish && !isRelease) {
|
||||
"https://oss.sonatype.org/content/repositories/snapshots/"
|
||||
} else {
|
||||
null
|
||||
}
|
||||
val deployUrlFromParameters = deployRepoUrl ?: deployFolder ?: sonatypeSnapshotsUrl
|
||||
|
||||
val isDeployStagingRepoGenerationRequired: Boolean by extra(isSonatypeRelease && deployUrlFromParameters == null)
|
||||
|
||||
var repoUrl: String by extra((deployUrlFromParameters ?: "file://${rootProject.buildDir}/repo").toString())
|
||||
logger.info("Deployment repository preliminary url: $repoUrl ($repoProvider)")
|
||||
|
||||
val username: String? by extra(
|
||||
properties["deployRepoUsername"]?.toString() ?: properties["kotlin.${repoProvider}.user"]?.toString()
|
||||
)
|
||||
val password: String? by extra(
|
||||
properties["deployRepoPassword"]?.toString() ?: properties["kotlin.${repoProvider}.password"]?.toString()
|
||||
)
|
||||
|
||||
if (isDeployStagingRepoGenerationRequired) {
|
||||
doFirst {
|
||||
HttpClient().use { client ->
|
||||
runBlocking {
|
||||
val sonatypeUsername = requireNotNull(username) {
|
||||
"Username to authenticate on sonatype staging was not provided!"
|
||||
}
|
||||
val sonatypePassword = requireNotNull(password) {
|
||||
"Password to authenticate on sonatype staging was not provided!"
|
||||
}
|
||||
|
||||
val response = client.post("https://oss.sonatype.org/service/local/staging/profiles/169b36e205a64e/start") {
|
||||
basicAuth(sonatypeUsername, sonatypePassword)
|
||||
contentType(ContentType.Application.Xml)
|
||||
accept(ContentType.Application.Xml)
|
||||
setBody("<promoteRequest><data><description>Repository for publishing $version</description></data></promoteRequest>")
|
||||
}
|
||||
|
||||
if (response.status.value in 200..299) {
|
||||
val responseText = response.bodyAsText()
|
||||
val repoId = responseText
|
||||
.substringAfter("<stagingRepositoryId>")
|
||||
.substringBefore("</stagingRepositoryId>")
|
||||
repoUrl = "https://oss.sonatype.org/service/local/staging/deployByRepositoryId/$repoId/"
|
||||
logger.warn("##teamcity[setParameter name='system.deploy-url' value='$repoUrl']")
|
||||
} else {
|
||||
throw GradleException("Failed to connect to sonatype API: ${response.status.description}")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
doLast {
|
||||
logger.warn("Deployment repository url: $repoUrl")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
import org.gradle.api.Action
|
||||
import org.gradle.api.NamedDomainObjectContainer
|
||||
import org.gradle.api.NamedDomainObjectProvider
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.artifacts.Dependency
|
||||
import org.gradle.api.artifacts.ExternalModuleDependency
|
||||
import org.gradle.api.artifacts.dsl.DependencyHandler
|
||||
import org.gradle.kotlin.dsl.accessors.runtime.addDependencyTo
|
||||
|
||||
/*
|
||||
* Copyright 2010-2019 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
val NamedDomainObjectContainer<Configuration>.publishedRuntime: NamedDomainObjectProvider<Configuration> get() = named("publishedRuntime")
|
||||
|
||||
fun DependencyHandler.publishedRuntime(dependencyNotation: Any): Dependency? =
|
||||
add("publishedRuntime", dependencyNotation)
|
||||
|
||||
fun DependencyHandler.publishedRuntime(
|
||||
dependencyNotation: String,
|
||||
dependencyConfiguration: Action<ExternalModuleDependency>
|
||||
): ExternalModuleDependency =
|
||||
addDependencyTo(this, "publishedRuntime", dependencyNotation, dependencyConfiguration)
|
||||
|
||||
|
||||
val NamedDomainObjectContainer<Configuration>.publishedCompile: NamedDomainObjectProvider<Configuration> get() = named("publishedCompile")
|
||||
|
||||
fun DependencyHandler.publishedCompile(dependencyNotation: Any): Dependency? =
|
||||
add("publishedCompile", dependencyNotation)
|
||||
|
||||
fun DependencyHandler.publishedCompile(
|
||||
dependencyNotation: String,
|
||||
dependencyConfiguration: Action<ExternalModuleDependency>
|
||||
): ExternalModuleDependency =
|
||||
addDependencyTo(this, "publishedCompile", dependencyNotation, dependencyConfiguration)
|
||||
|
||||
@@ -0,0 +1,484 @@
|
||||
@file:Suppress("unused") // usages in build scripts are not tracked properly
|
||||
@file:JvmName("RepoArtifacts")
|
||||
|
||||
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.artifacts.ConfigurablePublishArtifact
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.artifacts.ConfigurationContainer
|
||||
import org.gradle.api.artifacts.PublishArtifact
|
||||
import org.gradle.api.artifacts.component.ProjectComponentIdentifier
|
||||
import org.gradle.api.component.AdhocComponentWithVariants
|
||||
import org.gradle.api.file.ArchiveOperations
|
||||
import org.gradle.api.file.DuplicatesStrategy
|
||||
import org.gradle.api.plugins.BasePluginExtension
|
||||
import org.gradle.api.plugins.JavaPlugin
|
||||
import org.gradle.api.plugins.JavaPlugin.JAVADOC_ELEMENTS_CONFIGURATION_NAME
|
||||
import org.gradle.api.plugins.JavaPlugin.SOURCES_ELEMENTS_CONFIGURATION_NAME
|
||||
import org.gradle.api.plugins.JavaPluginExtension
|
||||
import org.gradle.api.provider.Provider
|
||||
import org.gradle.api.publish.PublishingExtension
|
||||
import org.gradle.api.publish.maven.MavenPublication
|
||||
import org.gradle.api.publish.tasks.GenerateModuleMetadata
|
||||
import org.gradle.api.tasks.TaskProvider
|
||||
import org.gradle.api.tasks.javadoc.Javadoc
|
||||
import org.gradle.configurationcache.extensions.serviceOf
|
||||
import org.gradle.jvm.tasks.Jar
|
||||
import org.gradle.kotlin.dsl.*
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinSourceSetContainer
|
||||
import plugins.KotlinBuildPublishingPlugin
|
||||
import plugins.mainPublicationName
|
||||
import java.io.File
|
||||
|
||||
|
||||
private const val MAGIC_DO_NOT_CHANGE_TEST_JAR_TASK_NAME = "testJar"
|
||||
|
||||
fun Project.testsJar(body: Jar.() -> Unit = {}): Jar {
|
||||
val testsJarCfg = configurations.getOrCreate("tests-jar").extendsFrom(configurations["testApi"])
|
||||
|
||||
return task<Jar>(MAGIC_DO_NOT_CHANGE_TEST_JAR_TASK_NAME) {
|
||||
dependsOn("testClasses")
|
||||
pluginManager.withPlugin("java") {
|
||||
from(testSourceSet.output)
|
||||
}
|
||||
archiveClassifier.set("tests")
|
||||
body()
|
||||
project.addArtifact(testsJarCfg, this, this)
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.setPublishableArtifact(
|
||||
jarTask: TaskProvider<out Jar>
|
||||
) {
|
||||
addArtifact("runtimeElements", jarTask)
|
||||
addArtifact("apiElements", jarTask)
|
||||
addArtifact("archives", jarTask)
|
||||
}
|
||||
|
||||
fun removeJarTaskArtifact(
|
||||
jarTask: TaskProvider<out Jar>
|
||||
): Configuration.() -> Unit = {
|
||||
val jarFile = jarTask.get().archiveFile.get().asFile
|
||||
artifacts.removeIf { it.file == jarFile }
|
||||
}
|
||||
|
||||
fun Project.noDefaultJar() {
|
||||
val jarTask = tasks.named<Jar>("jar") {
|
||||
enabled = false
|
||||
}
|
||||
|
||||
configurations.named("apiElements", removeJarTaskArtifact(jarTask))
|
||||
configurations.named("runtimeElements", removeJarTaskArtifact(jarTask))
|
||||
configurations.named("archives", removeJarTaskArtifact(jarTask))
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun Jar.addEmbeddedRuntime(embeddedConfigurationName: String = "embedded") {
|
||||
project.configurations.findByName(embeddedConfigurationName)?.let { embedded ->
|
||||
dependsOn(embedded)
|
||||
val archiveOperations = project.serviceOf<ArchiveOperations>()
|
||||
from {
|
||||
embedded.map { dependency: File ->
|
||||
check(!dependency.path.contains("kotlin-stdlib")) {
|
||||
"""
|
||||
|There's an attempt to have an embedded kotlin-stdlib in $project which is likely a misconfiguration
|
||||
|All embedded dependencies:
|
||||
| ${embedded.files.joinToString(separator = "\n| ")}
|
||||
""".trimMargin()
|
||||
}
|
||||
|
||||
if (dependency.extension.equals("jar", ignoreCase = true)) {
|
||||
archiveOperations.zipTree(dependency)
|
||||
} else {
|
||||
dependency
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.runtimeJar(body: Jar.() -> Unit = {}): TaskProvider<out Jar> {
|
||||
val jarTask = tasks.named<Jar>("jar")
|
||||
jarTask.configure {
|
||||
addEmbeddedRuntime()
|
||||
setupPublicJar(project.extensions.getByType<BasePluginExtension>().archivesName.get())
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
body()
|
||||
}
|
||||
|
||||
return jarTask
|
||||
}
|
||||
|
||||
fun Project.runtimeJarWithRelocation(body: ShadowJar.() -> Unit = {}): TaskProvider<out Jar> {
|
||||
noDefaultJar()
|
||||
|
||||
val shadowJarTask = tasks.register<ShadowJar>("shadowJar") {
|
||||
archiveClassifier.set("shadow")
|
||||
configurations = configurations + listOf(project.configurations["embedded"])
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
body()
|
||||
}
|
||||
|
||||
val runtimeJarTask = tasks.register<Jar>("runtimeJar") {
|
||||
dependsOn(shadowJarTask)
|
||||
from {
|
||||
zipTree(shadowJarTask.get().outputs.files.singleFile)
|
||||
}
|
||||
setupPublicJar(project.extensions.getByType<BasePluginExtension>().archivesName.get())
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
}
|
||||
|
||||
project.addArtifact("archives", runtimeJarTask, runtimeJarTask)
|
||||
project.addArtifact("runtimeElements", runtimeJarTask, runtimeJarTask)
|
||||
project.addArtifact("apiElements", runtimeJarTask, runtimeJarTask)
|
||||
|
||||
return runtimeJarTask
|
||||
}
|
||||
|
||||
fun Project.runtimeJar(task: TaskProvider<ShadowJar>, body: ShadowJar.() -> Unit = {}): TaskProvider<out Jar> {
|
||||
|
||||
noDefaultJar()
|
||||
|
||||
task.configure {
|
||||
configurations = configurations + listOf(project.configurations["embedded"])
|
||||
setupPublicJar(project.extensions.getByType<BasePluginExtension>().archivesName.get())
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
body()
|
||||
}
|
||||
|
||||
project.addArtifact("archives", task, task)
|
||||
project.addArtifact("runtimeElements", task, task)
|
||||
project.addArtifact("apiElements", task, task)
|
||||
|
||||
return task
|
||||
}
|
||||
|
||||
private fun Project.mainJavaPluginSourceSet() = findJavaPluginExtension()?.sourceSets?.findByName("main")
|
||||
private fun Project.mainKotlinSourceSet() =
|
||||
(extensions.findByName("kotlin") as? KotlinSourceSetContainer)?.sourceSets?.findByName("main")
|
||||
private fun Project.sources() = mainJavaPluginSourceSet()?.allSource ?: mainKotlinSourceSet()?.kotlin
|
||||
|
||||
@JvmOverloads
|
||||
fun Project.sourcesJar(body: Jar.() -> Unit = {}): TaskProvider<Jar> {
|
||||
configure<JavaPluginExtension> {
|
||||
withSourcesJar()
|
||||
}
|
||||
|
||||
val sourcesJar = getOrCreateTask<Jar>("sourcesJar") {
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
archiveClassifier.set("sources")
|
||||
|
||||
from(project.sources())
|
||||
addEmbeddedSources()
|
||||
|
||||
body()
|
||||
}
|
||||
|
||||
addArtifact("archives", sourcesJar)
|
||||
addArtifact("sources", sourcesJar)
|
||||
|
||||
configurePublishedComponent {
|
||||
addVariantsFromConfiguration(configurations[SOURCES_ELEMENTS_CONFIGURATION_NAME]) { }
|
||||
}
|
||||
|
||||
return sourcesJar
|
||||
}
|
||||
|
||||
/**
|
||||
* Also embeds into final '-sources.jar' file source files from embedded dependencies.
|
||||
*/
|
||||
fun Project.sourcesJarWithSourcesFromEmbedded(
|
||||
vararg embeddedDepSourcesJarTasks: TaskProvider<out Jar>,
|
||||
body: Jar.() -> Unit = {},
|
||||
): TaskProvider<Jar> {
|
||||
val sourcesJarTask = sourcesJar(body)
|
||||
|
||||
sourcesJarTask.configure {
|
||||
val archiveOperations = serviceOf<ArchiveOperations>()
|
||||
embeddedDepSourcesJarTasks.forEach { embeddedSourceJarTask ->
|
||||
dependsOn(embeddedSourceJarTask)
|
||||
from(embeddedSourceJarTask.map { archiveOperations.zipTree(it.archiveFile) })
|
||||
}
|
||||
}
|
||||
|
||||
return sourcesJarTask
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun Jar.addEmbeddedSources(configurationName: String = "embedded") {
|
||||
project.configurations.findByName(configurationName)?.let { embedded ->
|
||||
val allSources by lazy {
|
||||
embedded.resolvedConfiguration
|
||||
.resolvedArtifacts
|
||||
.map { it.id.componentIdentifier }
|
||||
.filterIsInstance<ProjectComponentIdentifier>()
|
||||
.mapNotNull {
|
||||
project.project(it.projectPath).sources()
|
||||
}
|
||||
}
|
||||
from({ allSources })
|
||||
}
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun Project.javadocJar(body: Jar.() -> Unit = {}): TaskProvider<Jar> {
|
||||
configure<JavaPluginExtension> {
|
||||
withJavadocJar()
|
||||
}
|
||||
|
||||
val javadocTask = getOrCreateTask<Jar>("javadocJar") {
|
||||
duplicatesStrategy = DuplicatesStrategy.EXCLUDE
|
||||
archiveClassifier.set("javadoc")
|
||||
tasks.findByName("javadoc")?.let { it as Javadoc }?.takeIf { it.enabled }?.let {
|
||||
dependsOn(it)
|
||||
from(it.destinationDir)
|
||||
}
|
||||
body()
|
||||
}
|
||||
|
||||
addArtifact("archives", javadocTask)
|
||||
|
||||
configurePublishedComponent {
|
||||
addVariantsFromConfiguration(configurations[JAVADOC_ELEMENTS_CONFIGURATION_NAME]) { }
|
||||
}
|
||||
|
||||
return javadocTask
|
||||
}
|
||||
|
||||
/**
|
||||
* Also embeds into final '-javadoc.jar' file javadoc files from embedded dependencies.
|
||||
*/
|
||||
fun Project.javadocJarWithJavadocFromEmbedded(
|
||||
vararg embeddedDepJavadocJarTasks: TaskProvider<out Jar>,
|
||||
body: Jar.() -> Unit = {},
|
||||
): TaskProvider<Jar> {
|
||||
val javadocJarTask = javadocJar(body)
|
||||
|
||||
javadocJarTask.configure {
|
||||
val archiveOperations = serviceOf<ArchiveOperations>()
|
||||
embeddedDepJavadocJarTasks.forEach { embeddedJavadocJarTask ->
|
||||
dependsOn(embeddedJavadocJarTask)
|
||||
from(embeddedJavadocJarTask.map { archiveOperations.zipTree(it.archiveFile) })
|
||||
}
|
||||
}
|
||||
|
||||
return javadocJarTask
|
||||
}
|
||||
|
||||
|
||||
fun Project.standardPublicJars() {
|
||||
runtimeJar()
|
||||
sourcesJar()
|
||||
javadocJar()
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun Project.publish(moduleMetadata: Boolean = false, sbom: Boolean = true, configure: MavenPublication.() -> Unit = { }) {
|
||||
apply<KotlinBuildPublishingPlugin>()
|
||||
|
||||
if (!moduleMetadata) {
|
||||
tasks.withType<GenerateModuleMetadata> {
|
||||
enabled = false
|
||||
}
|
||||
}
|
||||
|
||||
val publication = extensions.findByType<PublishingExtension>()
|
||||
?.publications
|
||||
?.findByName(mainPublicationName) as MavenPublication
|
||||
publication.configure()
|
||||
if (sbom) {
|
||||
configureSbom()
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.idePluginDependency(block: () -> Unit) {
|
||||
val shouldActivate = rootProject.findProperty("publish.ide.plugin.dependencies")?.toString()?.toBoolean() == true
|
||||
if (shouldActivate) {
|
||||
block()
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.publishJarsForIde(projects: List<String>, libraryDependencies: List<String> = emptyList()) {
|
||||
idePluginDependency {
|
||||
publishProjectJars(projects, libraryDependencies)
|
||||
}
|
||||
configurations.all {
|
||||
// Don't allow `ideaIC` from compiler to leak into Kotlin plugin modules. Compiler and
|
||||
// plugin may depend on different versions of IDEA and it will lead to version conflict
|
||||
exclude(module = ideModuleName())
|
||||
}
|
||||
dependencies {
|
||||
projects.forEach {
|
||||
jpsLikeJarDependency(project(it), JpsDepScope.COMPILE, { isTransitive = false }, exported = true)
|
||||
}
|
||||
libraryDependencies.forEach {
|
||||
jpsLikeJarDependency(it, JpsDepScope.COMPILE, exported = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.publishTestJarsForIde(projectNames: List<String>) {
|
||||
idePluginDependency {
|
||||
// Compiler test infrastructure should not affect test running in IDE.
|
||||
// If required, the components should be registered on the IDE plugin side.
|
||||
val excludedPaths = listOf("junit-platform.properties", "META-INF/services/**/*")
|
||||
publishTestJar(projectNames, excludedPaths)
|
||||
}
|
||||
configurations.all {
|
||||
// Don't allow `ideaIC` from compiler to leak into Kotlin plugin modules. Compiler and
|
||||
// plugin may depend on different versions of IDEA and it will lead to version conflict
|
||||
exclude(module = ideModuleName())
|
||||
}
|
||||
dependencies {
|
||||
for (projectName in projectNames) {
|
||||
jpsLikeJarDependency(projectTests(projectName), JpsDepScope.COMPILE, exported = true)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.publishProjectJars(projects: List<String>, libraryDependencies: List<String> = emptyList()) {
|
||||
apply<JavaPlugin>()
|
||||
|
||||
val fatJarContents by configurations.creating
|
||||
|
||||
dependencies {
|
||||
for (projectName in projects) {
|
||||
fatJarContents(project(projectName)) { isTransitive = false }
|
||||
}
|
||||
|
||||
for (libraryDependency in libraryDependencies) {
|
||||
fatJarContents(libraryDependency) { isTransitive = false }
|
||||
}
|
||||
}
|
||||
|
||||
publish()
|
||||
|
||||
val jar: Jar by tasks
|
||||
|
||||
jar.apply {
|
||||
dependsOn(fatJarContents)
|
||||
val archiveOperations = project.serviceOf<ArchiveOperations>()
|
||||
from {
|
||||
fatJarContents.map(archiveOperations::zipTree)
|
||||
}
|
||||
}
|
||||
|
||||
sourcesJar {
|
||||
for (projectPath in projects) {
|
||||
val projectTasks = project(projectPath).tasks
|
||||
if (projectTasks.names.any { it == "compileKotlin" }) {
|
||||
// this is needed in order to declare explicit dependency on code generation tasks
|
||||
dependsOn(projectTasks.named("compileKotlin").map { it.dependsOn })
|
||||
}
|
||||
}
|
||||
from {
|
||||
projects.map {
|
||||
project(it).mainSourceSet.allSource
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
javadocJar()
|
||||
}
|
||||
|
||||
fun Project.publishTestJar(projects: List<String>, excludedPaths: List<String>) {
|
||||
apply<JavaPlugin>()
|
||||
|
||||
val fatJarContents by configurations.creating
|
||||
|
||||
dependencies {
|
||||
for (projectName in projects) {
|
||||
fatJarContents(project(projectName, configuration = "tests-jar")) { isTransitive = false }
|
||||
}
|
||||
}
|
||||
|
||||
publish(sbom = false)
|
||||
|
||||
val jar: Jar by tasks
|
||||
|
||||
jar.apply {
|
||||
dependsOn(fatJarContents)
|
||||
val archiveOperations = project.serviceOf<ArchiveOperations>()
|
||||
from {
|
||||
fatJarContents.map(archiveOperations::zipTree)
|
||||
}
|
||||
|
||||
exclude(excludedPaths)
|
||||
}
|
||||
|
||||
sourcesJar {
|
||||
from {
|
||||
projects.map { project(it).testSourceSet.allSource }
|
||||
}
|
||||
}
|
||||
|
||||
javadocJar()
|
||||
}
|
||||
|
||||
fun ConfigurationContainer.getOrCreate(name: String): Configuration = findByName(name) ?: create(name)
|
||||
|
||||
fun Jar.setupPublicJar(
|
||||
baseName: String,
|
||||
classifier: String = ""
|
||||
) = setupPublicJar(
|
||||
project.provider { baseName },
|
||||
project.provider { classifier }
|
||||
)
|
||||
|
||||
fun Jar.setupPublicJar(
|
||||
baseName: Provider<String>,
|
||||
classifier: Provider<String> = project.provider { "" }
|
||||
) {
|
||||
val buildNumber = project.rootProject.extra["buildNumber"] as String
|
||||
this.archiveBaseName.set(baseName)
|
||||
this.archiveClassifier.set(classifier)
|
||||
manifest.attributes.apply {
|
||||
put("Implementation-Vendor", "JetBrains")
|
||||
put("Implementation-Title", baseName.get())
|
||||
put("Implementation-Version", buildNumber)
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.addArtifact(configuration: Configuration, task: Task, artifactRef: Any, body: ConfigurablePublishArtifact.() -> Unit = {}) {
|
||||
artifacts.add(configuration.name, artifactRef) {
|
||||
builtBy(task)
|
||||
body()
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.addArtifact(configurationName: String, task: Task, artifactRef: Any, body: ConfigurablePublishArtifact.() -> Unit = {}) =
|
||||
addArtifact(configurations.getOrCreate(configurationName), task, artifactRef, body)
|
||||
|
||||
fun <T : Task> Project.addArtifact(
|
||||
configurationName: String,
|
||||
task: TaskProvider<T>,
|
||||
body: ConfigurablePublishArtifact.() -> Unit = {}
|
||||
): PublishArtifact {
|
||||
configurations.maybeCreate(configurationName)
|
||||
return artifacts.add(configurationName, task, body)
|
||||
}
|
||||
|
||||
fun <T : Task> Project.addArtifact(
|
||||
configurationName: String,
|
||||
task: TaskProvider<T>,
|
||||
artifactRef: Any,
|
||||
body: ConfigurablePublishArtifact.() -> Unit = {}
|
||||
): PublishArtifact {
|
||||
configurations.maybeCreate(configurationName)
|
||||
return artifacts.add(configurationName, artifactRef) {
|
||||
builtBy(task)
|
||||
body()
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.cleanArtifacts() {
|
||||
configurations["archives"].artifacts.let { artifacts ->
|
||||
artifacts.forEach {
|
||||
artifacts.remove(it)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.configurePublishedComponent(configure: AdhocComponentWithVariants.() -> Unit) =
|
||||
(components.findByName(KotlinBuildPublishingPlugin.ADHOC_COMPONENT_NAME) as AdhocComponentWithVariants?)?.apply(configure)
|
||||
@@ -0,0 +1,298 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
@file:JvmName("RepoDependencies")
|
||||
|
||||
import org.gradle.api.GradleException
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.*
|
||||
import org.gradle.api.artifacts.dsl.DependencyHandler
|
||||
import org.gradle.api.file.ConfigurableFileCollection
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.internal.jvm.Jvm
|
||||
import org.gradle.kotlin.dsl.closureOf
|
||||
import org.gradle.kotlin.dsl.extra
|
||||
import org.gradle.kotlin.dsl.project
|
||||
import java.io.File
|
||||
|
||||
private val Project.isEAPIntellij get() = rootProject.extra["versions.intellijSdk"].toString().contains("-EAP-")
|
||||
private val Project.isNightlyIntellij get() = rootProject.extra["versions.intellijSdk"].toString().endsWith("SNAPSHOT") && !isEAPIntellij
|
||||
|
||||
val Project.intellijRepo
|
||||
get() =
|
||||
when {
|
||||
isEAPIntellij -> "https://www.jetbrains.com/intellij-repository/snapshots"
|
||||
isNightlyIntellij -> "https://www.jetbrains.com/intellij-repository/nightly"
|
||||
else -> "https://www.jetbrains.com/intellij-repository/releases"
|
||||
}
|
||||
|
||||
fun Project.commonDependency(coordinates: String): String {
|
||||
val parts = coordinates.split(':')
|
||||
return when (parts.size) {
|
||||
1 -> "$coordinates:$coordinates:${commonDependencyVersion(coordinates, coordinates)}"
|
||||
2 -> "${parts[0]}:${parts[1]}:${commonDependencyVersion(parts[0], parts[1])}"
|
||||
3 -> coordinates
|
||||
else -> throw IllegalArgumentException("Illegal maven coordinates: $coordinates")
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.commonDependency(group: String, artifact: String, vararg suffixesAndClassifiers: String): String {
|
||||
val (classifiers, artifactSuffixes) = suffixesAndClassifiers.partition { it.startsWith(':') }
|
||||
return "$group:$artifact${artifactSuffixes.joinToString("")}:${commonDependencyVersion(group, artifact)}${classifiers.joinToString("")}"
|
||||
}
|
||||
|
||||
fun Project.commonDependencyVersion(group: String, artifact: String): String =
|
||||
when {
|
||||
rootProject.extra.has("versions.$artifact") -> rootProject.extra["versions.$artifact"]
|
||||
rootProject.extra.has("versions.$group") -> rootProject.extra["versions.$group"]
|
||||
else -> throw GradleException("Neither versions.$artifact nor versions.$group is defined in the root project's extra")
|
||||
} as String
|
||||
|
||||
fun Project.preloadedDeps(
|
||||
vararg artifactBaseNames: String,
|
||||
baseDir: File = File(rootDir, "dependencies"),
|
||||
subDir: String? = null,
|
||||
optional: Boolean = false
|
||||
): ConfigurableFileCollection {
|
||||
val dir = if (subDir != null) File(baseDir, subDir) else baseDir
|
||||
if (!dir.exists() || !dir.isDirectory) {
|
||||
if (optional) return files()
|
||||
throw GradleException("Invalid base directory $dir")
|
||||
}
|
||||
val matchingFiles = dir.listFiles { file -> artifactBaseNames.any { file.matchMaybeVersionedArtifact(it) } }
|
||||
if (matchingFiles == null || matchingFiles.size < artifactBaseNames.size) {
|
||||
throw GradleException(
|
||||
"Not all matching artifacts '${artifactBaseNames.joinToString()}' found in the '$dir' " +
|
||||
"(missing: ${
|
||||
artifactBaseNames.filterNot { request ->
|
||||
matchingFiles?.any {
|
||||
it.matchMaybeVersionedArtifact(
|
||||
request
|
||||
)
|
||||
} ?: false
|
||||
}.joinToString()
|
||||
};" +
|
||||
" found: ${matchingFiles?.joinToString { it.name }})"
|
||||
)
|
||||
}
|
||||
return files(*matchingFiles.map { it.canonicalPath }.toTypedArray())
|
||||
}
|
||||
|
||||
fun kotlinDep(artifactBaseName: String, version: String, classifier: String? = null): String =
|
||||
listOfNotNull("org.jetbrains.kotlin:kotlin-$artifactBaseName:$version", classifier).joinToString(":")
|
||||
|
||||
@JvmOverloads
|
||||
fun Project.kotlinStdlib(suffix: String? = null, classifier: String? = null): Any {
|
||||
return if (kotlinBuildProperties.useBootstrapStdlib)
|
||||
kotlinDep(listOfNotNull("stdlib", suffix).joinToString("-"), bootstrapKotlinVersion, classifier)
|
||||
else
|
||||
dependencies.project(listOfNotNull(":kotlin-stdlib", suffix).joinToString("-"), classifier)
|
||||
}
|
||||
|
||||
fun Project.kotlinBuiltins(): Any = kotlinBuiltins(forJvm = false)
|
||||
|
||||
fun Project.kotlinBuiltins(forJvm: Boolean): Any =
|
||||
if (kotlinBuildProperties.useBootstrapStdlib) "org.jetbrains.kotlin:builtins:$bootstrapKotlinVersion"
|
||||
else dependencies.project(":core:builtins", configuration = "runtimeElementsJvm".takeIf { forJvm })
|
||||
|
||||
fun DependencyHandler.projectTests(name: String): ProjectDependency = project(name, configuration = "tests-jar")
|
||||
|
||||
enum class JpsDepScope {
|
||||
COMPILE, TEST, RUNTIME, PROVIDED
|
||||
}
|
||||
|
||||
fun DependencyHandler.add(configurationName: String, dependencyNotation: Any, configure: (ModuleDependency.() -> Unit)?) {
|
||||
// Avoid `dependencyNotation` to `ModuleDependency` class cast exception if possible
|
||||
if (configure != null) {
|
||||
add(configurationName, dependencyNotation, closureOf(configure))
|
||||
} else {
|
||||
add(configurationName, dependencyNotation)
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("unused") // Used in cooperative mode with IDEA Kotlin plugin
|
||||
fun Project.disableDependencyVerification() {
|
||||
configurations.all {
|
||||
resolutionStrategy {
|
||||
disableDependencyVerification()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun DependencyHandler.jpsLikeJarDependency(
|
||||
dependencyNotation: Any,
|
||||
scope: JpsDepScope,
|
||||
dependencyConfiguration: (ModuleDependency.() -> Unit)? = null,
|
||||
exported: Boolean = false
|
||||
) {
|
||||
when (scope) {
|
||||
JpsDepScope.COMPILE -> {
|
||||
if (exported) {
|
||||
add("api", dependencyNotation, dependencyConfiguration)
|
||||
add("testApi", dependencyNotation, dependencyConfiguration)
|
||||
} else {
|
||||
add("implementation", dependencyNotation, dependencyConfiguration)
|
||||
}
|
||||
}
|
||||
JpsDepScope.TEST -> {
|
||||
if (exported) {
|
||||
add("testApi", dependencyNotation, dependencyConfiguration)
|
||||
} else {
|
||||
add("testImplementation", dependencyNotation, dependencyConfiguration)
|
||||
}
|
||||
}
|
||||
JpsDepScope.RUNTIME -> {
|
||||
add("testRuntimeOnly", dependencyNotation, dependencyConfiguration)
|
||||
}
|
||||
JpsDepScope.PROVIDED -> {
|
||||
if (exported) {
|
||||
add("compileOnlyApi", dependencyNotation, dependencyConfiguration)
|
||||
add("testApi", dependencyNotation, dependencyConfiguration)
|
||||
} else {
|
||||
add("compileOnly", dependencyNotation, dependencyConfiguration)
|
||||
add("testImplementation", dependencyNotation, dependencyConfiguration)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Suppress("unused") // Used in cooperative mode with IDEA Kotlin plugin
|
||||
fun DependencyHandler.jpsLikeModuleDependency(moduleName: String, scope: JpsDepScope, exported: Boolean = false) {
|
||||
jpsLikeJarDependency(project(moduleName), scope, exported = exported)
|
||||
when (scope) {
|
||||
JpsDepScope.COMPILE -> {
|
||||
if (exported) {
|
||||
add("testApi", projectTests(moduleName))
|
||||
} else {
|
||||
add("testImplementation", projectTests(moduleName))
|
||||
}
|
||||
}
|
||||
JpsDepScope.TEST -> {
|
||||
if (exported) {
|
||||
add("testApi", projectTests(moduleName))
|
||||
} else {
|
||||
add("testImplementation", projectTests(moduleName))
|
||||
}
|
||||
}
|
||||
JpsDepScope.RUNTIME -> {
|
||||
add("runtimeOnly", projectTests(moduleName))
|
||||
}
|
||||
JpsDepScope.PROVIDED -> {
|
||||
if (exported) {
|
||||
add("testApi", projectTests(moduleName))
|
||||
} else {
|
||||
add("testImplementation", projectTests(moduleName))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fun Project.testApiJUnit5(
|
||||
vintageEngine: Boolean = false,
|
||||
runner: Boolean = false,
|
||||
suiteApi: Boolean = false,
|
||||
jupiterParams: Boolean = false
|
||||
) {
|
||||
with(dependencies) {
|
||||
val platformVersion = commonDependencyVersion("org.junit", "junit-bom")
|
||||
testApi(platform("org.junit:junit-bom:$platformVersion"))
|
||||
testApi("org.junit.jupiter:junit-jupiter")
|
||||
if (vintageEngine) {
|
||||
testApi("org.junit.vintage:junit-vintage-engine:$platformVersion")
|
||||
}
|
||||
|
||||
if (jupiterParams) {
|
||||
testApi("org.junit.jupiter:junit-jupiter-params:$platformVersion")
|
||||
}
|
||||
|
||||
val componentsVersion = commonDependencyVersion("org.junit.platform", "")
|
||||
|
||||
val components = mutableListOf(
|
||||
"org.junit.platform:junit-platform-commons",
|
||||
"org.junit.platform:junit-platform-launcher"
|
||||
)
|
||||
if (runner) {
|
||||
components += "org.junit.platform:junit-platform-runner"
|
||||
}
|
||||
if (suiteApi) {
|
||||
components += "org.junit.platform:junit-platform-suite-api"
|
||||
}
|
||||
|
||||
for (component in components) {
|
||||
testApi("$component:$componentsVersion")
|
||||
}
|
||||
|
||||
// This dependency is needed only for FileComparisonFailure
|
||||
add("testImplementation", intellijJavaRt())
|
||||
|
||||
// This is needed only for using FileComparisonFailure, which relies on JUnit 3 classes
|
||||
add("testRuntimeOnly", commonDependency("junit:junit"))
|
||||
}
|
||||
}
|
||||
|
||||
private fun DependencyHandler.testApi(dependencyNotation: Any) {
|
||||
add("testApi", dependencyNotation)
|
||||
}
|
||||
|
||||
val Project.protobufRelocatedVersion: String get() = findProperty("versions.protobuf-relocated") as String
|
||||
fun Project.protobufLite(): String = "org.jetbrains.kotlin:protobuf-lite:$protobufRelocatedVersion"
|
||||
fun Project.protobufFull(): String = "org.jetbrains.kotlin:protobuf-relocated:$protobufRelocatedVersion"
|
||||
fun Project.kotlinxCollectionsImmutable() =
|
||||
"org.jetbrains.kotlinx:kotlinx-collections-immutable-jvm:${rootProject.extra["versions.kotlinx-collections-immutable"]}"
|
||||
|
||||
val Project.kotlinNativeVersion: String get() = property("versions.kotlin-native") as String
|
||||
|
||||
val Project.nodejsVersion: String get() = property("versions.nodejs") as String
|
||||
val Project.v8Version: String get() = property("versions.v8") as String
|
||||
|
||||
fun File.matchMaybeVersionedArtifact(baseName: String) = name.matches(baseName.toMaybeVersionedJarRegex())
|
||||
|
||||
private val wildcardsRe = """[^*?]+|(\*)|(\?)""".toRegex()
|
||||
|
||||
private fun String.wildcardsToEscapedRegexString(): String = buildString {
|
||||
wildcardsRe.findAll(this@wildcardsToEscapedRegexString).forEach {
|
||||
when {
|
||||
it.groups[1] != null -> append(".*")
|
||||
it.groups[2] != null -> append(".")
|
||||
else -> append("\\Q${it.groups[0]!!.value}\\E")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun String.toMaybeVersionedJarRegex(): Regex {
|
||||
val hasJarExtension = endsWith(".jar")
|
||||
val escaped = this.wildcardsToEscapedRegexString()
|
||||
return Regex(if (hasJarExtension) escaped else "$escaped(-\\d.*)?\\.jar") // TODO: consider more precise version part of the regex
|
||||
}
|
||||
|
||||
fun Project.firstFromJavaHomeThatExists(
|
||||
vararg paths: String,
|
||||
jdkHome: File = File((this.property("JDK_1_8") ?: this.property("JDK_18") ?: error("Can't find JDK_1_8 property")) as String)
|
||||
): File? =
|
||||
paths.map { File(jdkHome, it) }.firstOrNull { it.exists() }.also {
|
||||
if (it == null)
|
||||
logger.warn("Cannot find file by paths: ${paths.toList()} in $jdkHome")
|
||||
}
|
||||
|
||||
fun Project.toolsJarApi(): Any =
|
||||
if (kotlinBuildProperties.isInJpsBuildIdeaSync)
|
||||
toolsJar()
|
||||
else
|
||||
dependencies.project(":dependencies:tools-jar-api")
|
||||
|
||||
fun Project.toolsJar(): FileCollection = files(
|
||||
getToolchainLauncherFor(DEFAULT_JVM_TOOLCHAIN)
|
||||
.map {
|
||||
Jvm.forHome(it.metadata.installationPath.asFile).toolsJar ?: throw GradleException("tools.jar not found!")
|
||||
}
|
||||
)
|
||||
|
||||
val compilerManifestClassPath
|
||||
get() = "annotations-13.0.jar kotlin-stdlib.jar kotlin-reflect.jar kotlin-script-runtime.jar trove4j.jar"
|
||||
|
||||
object EmbeddedComponents {
|
||||
const val CONFIGURATION_NAME = "embedded"
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
import org.gradle.api.NamedDomainObjectProvider
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.artifacts.ModuleVersionIdentifier
|
||||
import org.gradle.api.publish.PublishingExtension
|
||||
import org.gradle.api.publish.maven.MavenPublication
|
||||
import org.gradle.api.tasks.TaskProvider
|
||||
import org.gradle.kotlin.dsl.*
|
||||
import org.spdx.sbom.gradle.SpdxSbomExtension
|
||||
import org.spdx.sbom.gradle.SpdxSbomPlugin
|
||||
import org.spdx.sbom.gradle.SpdxSbomTask
|
||||
import org.spdx.sbom.gradle.extensions.DefaultSpdxSbomTaskExtension
|
||||
import plugins.mainPublicationName
|
||||
import java.net.URI
|
||||
import java.util.*
|
||||
|
||||
|
||||
fun Project.configureSbom(
|
||||
target: String? = null,
|
||||
documentName: String? = null,
|
||||
gradleConfigurations: Iterable<String> = setOf("runtimeClasspath"),
|
||||
publication: NamedDomainObjectProvider<MavenPublication>? = null,
|
||||
): TaskProvider<SpdxSbomTask> {
|
||||
assert(target == null && publication != null) { "provided publication will be ignored when target is null" }
|
||||
val project = this
|
||||
val targetName = target ?: "${mainPublicationName}Publication"
|
||||
apply<SpdxSbomPlugin>()
|
||||
|
||||
configure<SpdxSbomExtension> {
|
||||
targets.create(targetName) {
|
||||
configurations.set(gradleConfigurations)
|
||||
scm {
|
||||
tool.set("git")
|
||||
uri.set("https://github.com/JetBrains/kotlin.git")
|
||||
revision.set("v${project.version}")
|
||||
}
|
||||
|
||||
// adjust properties of the document
|
||||
document {
|
||||
name.set(documentName ?: project.name)
|
||||
// NOTE: The URI does not have to be accessible. It is only intended to provide a unique ID.
|
||||
// In many cases, the URI will point to a Web accessible document, but this should not be assumed to be the case.
|
||||
namespace.set("https://www.jetbrains.com/spdxdocs/${UUID.randomUUID()}")
|
||||
creator.set("Organization: JetBrains s.r.o.")
|
||||
packageSupplier.set("Organization: JetBrains s.r.o.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val NOASSERTION = URI.create("NOASSERTION")
|
||||
tasks.withType<SpdxSbomTask>().configureEach {
|
||||
taskExtension.set(object : DefaultSpdxSbomTaskExtension() {
|
||||
override fun mapRepoUri(input: URI?, moduleId: ModuleVersionIdentifier): URI {
|
||||
return NOASSERTION
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
val sbomOutputDirectory = layout.buildDirectory.dir("spdx/$targetName")
|
||||
val spdxSbomTask = tasks.named<SpdxSbomTask>("spdxSbomFor$targetName") {
|
||||
outputDirectory.set(sbomOutputDirectory)
|
||||
}
|
||||
val sbomFile = sbomOutputDirectory.map { it.file("$targetName.spdx.json") }
|
||||
val sbomCfg = configurations.maybeCreate("sbomFor$targetName").apply {
|
||||
isCanBeResolved = false
|
||||
isCanBeConsumed = true
|
||||
}
|
||||
|
||||
val sbomArtifact = artifacts.add(sbomCfg.name, sbomFile) {
|
||||
type = "sbom"
|
||||
extension = "spdx.json"
|
||||
builtBy(spdxSbomTask)
|
||||
}
|
||||
|
||||
if (target == null) {
|
||||
pluginManager.withPlugin("kotlin-build-publishing") {
|
||||
val mainPublication = the<PublishingExtension>().publications[mainPublicationName] as MavenPublication
|
||||
mainPublication.artifact(sbomArtifact)
|
||||
}
|
||||
} else if (publication != null) {
|
||||
publication.configure {
|
||||
artifact(sbomArtifact)
|
||||
}
|
||||
}
|
||||
|
||||
return spdxSbomTask
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
import org.gradle.api.tasks.testing.Test
|
||||
|
||||
fun Test.useJsIrBoxTests(
|
||||
version: Any,
|
||||
buildDir: String = "",
|
||||
fullStdLib: String = "libraries/stdlib/js-ir/build/classes/kotlin/js/main",
|
||||
reducedStdlibPath: String = "libraries/stdlib/js-ir-minimal-for-test/build/classes/kotlin/js/main",
|
||||
kotlinJsTestPath: String = "libraries/kotlin.test/js-ir/build/classes/kotlin/js/main"
|
||||
) {
|
||||
setupV8()
|
||||
dependsOn(":kotlin-stdlib-js-ir:compileKotlinJs")
|
||||
dependsOn(":kotlin-test:kotlin-test-js-ir:compileKotlinJs")
|
||||
dependsOn(":kotlin-stdlib-js-ir-minimal-for-test:compileKotlinJs")
|
||||
|
||||
systemProperty("kotlin.js.test.root.out.dir", buildDir)
|
||||
systemProperty("kotlin.js.full.stdlib.path", fullStdLib)
|
||||
systemProperty("kotlin.js.reduced.stdlib.path", reducedStdlibPath)
|
||||
systemProperty("kotlin.js.kotlin.test.path", kotlinJsTestPath)
|
||||
systemProperty("kotlin.js.stdlib.klib.path", "libraries/stdlib/js-ir/build/libs/kotlin-stdlib-js-ir-js-$version.klib")
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.tasks.testing.Test
|
||||
import org.jetbrains.kotlin.gradle.targets.js.d8.D8RootExtension
|
||||
import org.jetbrains.kotlin.gradle.targets.js.d8.D8RootPlugin
|
||||
|
||||
private object V8Utils {
|
||||
lateinit var d8Plugin: D8RootExtension
|
||||
|
||||
fun useD8Plugin(project: Project) {
|
||||
d8Plugin = D8RootPlugin.apply(project.rootProject)
|
||||
d8Plugin.version = project.v8Version
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.useD8Plugin() {
|
||||
V8Utils.useD8Plugin(this)
|
||||
}
|
||||
|
||||
fun Test.setupV8() {
|
||||
dependsOn(V8Utils.d8Plugin.setupTaskProvider)
|
||||
val v8ExecutablePath = project.provider {
|
||||
V8Utils.d8Plugin.requireConfigured().executablePath.absolutePath
|
||||
}
|
||||
doFirst {
|
||||
systemProperty("javascript.engine.path.V8", v8ExecutablePath.get())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.plugins.JavaPluginExtension
|
||||
import org.gradle.api.tasks.SourceSet
|
||||
import org.gradle.api.tasks.SourceSetContainer
|
||||
import org.gradle.kotlin.dsl.apply
|
||||
import org.jetbrains.kotlin.ideaExt.idea
|
||||
|
||||
inline fun Project.sourceSets(crossinline body: SourceSetsBuilder.() -> Unit) = SourceSetsBuilder(this).body()
|
||||
|
||||
class SourceSetsBuilder(val project: Project) {
|
||||
|
||||
inline operator fun String.invoke(crossinline body: SourceSet.() -> Unit): SourceSet {
|
||||
val sourceSetName = this
|
||||
return project.sourceSets.maybeCreate(sourceSetName).apply {
|
||||
none()
|
||||
body()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun SourceSet.none() {
|
||||
java.setSrcDirs(emptyList<String>())
|
||||
resources.setSrcDirs(emptyList<String>())
|
||||
}
|
||||
|
||||
val SourceSet.projectDefault: Project.() -> Unit
|
||||
get() = {
|
||||
when (this@projectDefault.name) {
|
||||
"main" -> {
|
||||
java.srcDirs("src")
|
||||
this@projectDefault.resources.srcDir("resources")
|
||||
}
|
||||
"test" -> {
|
||||
java.srcDirs("test", "tests")
|
||||
this@projectDefault.resources.srcDir("testResources")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val SourceSet.generatedDir: Project.() -> Unit
|
||||
get() = {
|
||||
generatedDir(this, "gen")
|
||||
}
|
||||
|
||||
val SourceSet.generatedTestDir: Project.() -> Unit
|
||||
get() = {
|
||||
generatedDir(this, "tests-gen")
|
||||
}
|
||||
|
||||
private fun SourceSet.generatedDir(project: Project, dirName: String) {
|
||||
val generationRoot = project.projectDir.resolve(dirName)
|
||||
java.srcDir(generationRoot.name)
|
||||
|
||||
if (project.kotlinBuildProperties.isInJpsBuildIdeaSync) {
|
||||
project.apply(plugin = "idea")
|
||||
project.idea {
|
||||
this.module.generatedSourceDirs.add(generationRoot)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val Project.sourceSets: SourceSetContainer
|
||||
get() = javaPluginExtension().sourceSets
|
||||
|
||||
val Project.mainSourceSet: SourceSet
|
||||
get() = javaPluginExtension().mainSourceSet
|
||||
|
||||
val Project.testSourceSet: SourceSet
|
||||
get() = javaPluginExtension().testSourceSet
|
||||
|
||||
val JavaPluginExtension.mainSourceSet: SourceSet
|
||||
get() = sourceSets.getByName("main")
|
||||
|
||||
val JavaPluginExtension.testSourceSet: SourceSet
|
||||
get() = sourceSets.getByName("test")
|
||||
@@ -0,0 +1,70 @@
|
||||
@file:Suppress("unused") // usages in build scripts are not tracked properly
|
||||
|
||||
import org.gradle.api.logging.Logger
|
||||
import org.jetbrains.org.objectweb.asm.*
|
||||
import java.io.BufferedOutputStream
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.util.*
|
||||
import java.util.jar.JarFile
|
||||
import java.util.zip.ZipEntry
|
||||
import java.util.zip.ZipOutputStream
|
||||
|
||||
private val CONSTANT_TIME_FOR_ZIP_ENTRIES = GregorianCalendar(1980, 1, 1, 0, 0, 0).timeInMillis
|
||||
|
||||
/**
|
||||
* Removes @kotlin.Metadata annotations from compiled Kotlin classes
|
||||
*/
|
||||
fun stripMetadata(logger: Logger, classNamePattern: String, inFile: File, outFile: File, preserveFileTimestamps: Boolean = true) {
|
||||
val classRegex = classNamePattern.toRegex()
|
||||
|
||||
assert(inFile.exists()) { "Input file not found at $inFile" }
|
||||
|
||||
fun transform(entryName: String, bytes: ByteArray): ByteArray {
|
||||
if (!entryName.endsWith(".class")) return bytes
|
||||
if (!classRegex.matches(entryName.removeSuffix(".class"))) return bytes
|
||||
|
||||
var changed = false
|
||||
val classWriter = ClassWriter(0)
|
||||
val classVisitor = object : ClassVisitor(Opcodes.API_VERSION, classWriter) {
|
||||
override fun visitAnnotation(desc: String, visible: Boolean): AnnotationVisitor? {
|
||||
if (Type.getType(desc).internalName == "kotlin/Metadata") {
|
||||
changed = true
|
||||
return null
|
||||
}
|
||||
return super.visitAnnotation(desc, visible)
|
||||
}
|
||||
}
|
||||
ClassReader(bytes).accept(classVisitor, 0)
|
||||
if (!changed) return bytes
|
||||
|
||||
return classWriter.toByteArray()
|
||||
}
|
||||
|
||||
ZipOutputStream(BufferedOutputStream(FileOutputStream(outFile))).use { outJar ->
|
||||
JarFile(inFile).use { inJar ->
|
||||
for (entry in inJar.entries()) {
|
||||
val inBytes = inJar.getInputStream(entry).readBytes()
|
||||
val outBytes = transform(entry.name, inBytes)
|
||||
|
||||
if (inBytes.size < outBytes.size) {
|
||||
error("Size increased for ${entry.name}: was ${inBytes.size} bytes, became ${outBytes.size} bytes")
|
||||
}
|
||||
|
||||
val newEntry = ZipEntry(entry.name)
|
||||
if (!preserveFileTimestamps) {
|
||||
newEntry.time = CONSTANT_TIME_FOR_ZIP_ENTRIES
|
||||
}
|
||||
outJar.putNextEntry(newEntry)
|
||||
outJar.write(outBytes)
|
||||
outJar.closeEntry()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
logger.info("Stripping @kotlin.Metadata annotations from all classes in $inFile")
|
||||
logger.info("Class name pattern: $classNamePattern")
|
||||
logger.info("Input file size: ${inFile.length()} bytes")
|
||||
logger.info("Output written to $outFile")
|
||||
logger.info("Output file size: ${outFile.length()} bytes")
|
||||
}
|
||||
@@ -0,0 +1,411 @@
|
||||
/*
|
||||
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
|
||||
// usages in build scripts are not tracked properly
|
||||
@file:Suppress("unused")
|
||||
|
||||
import com.sun.management.OperatingSystemMXBean
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.Task
|
||||
import org.gradle.api.artifacts.Configuration
|
||||
import org.gradle.api.artifacts.ProjectDependency
|
||||
import org.gradle.api.attributes.Usage
|
||||
import org.gradle.api.file.FileCollection
|
||||
import org.gradle.api.file.FileSystemOperations
|
||||
import org.gradle.api.internal.tasks.testing.filter.DefaultTestFilter
|
||||
import org.gradle.api.tasks.TaskProvider
|
||||
import org.gradle.api.tasks.testing.Test
|
||||
import org.gradle.kotlin.dsl.*
|
||||
import org.gradle.kotlin.dsl.support.serviceOf
|
||||
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
|
||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages
|
||||
import java.io.File
|
||||
import java.lang.Character.isLowerCase
|
||||
import java.lang.Character.isUpperCase
|
||||
import java.lang.management.ManagementFactory
|
||||
import java.nio.file.Files
|
||||
import java.nio.file.Path
|
||||
|
||||
val kotlinGradlePluginAndItsRequired = arrayOf(
|
||||
":kotlin-assignment",
|
||||
":kotlin-allopen",
|
||||
":kotlin-noarg",
|
||||
":kotlin-sam-with-receiver",
|
||||
":kotlin-lombok",
|
||||
":kotlin-serialization",
|
||||
":kotlin-android-extensions",
|
||||
":kotlin-android-extensions-runtime",
|
||||
":kotlin-parcelize-compiler",
|
||||
":kotlin-build-common",
|
||||
":kotlin-compiler-embeddable",
|
||||
":native:kotlin-native-utils",
|
||||
":kotlin-util-klib",
|
||||
":kotlin-util-io",
|
||||
":kotlin-compiler-runner",
|
||||
":kotlin-daemon-embeddable",
|
||||
":kotlin-daemon-client",
|
||||
":kotlin-project-model",
|
||||
":kotlin-gradle-plugins-bom",
|
||||
":kotlin-gradle-plugin-api",
|
||||
":kotlin-gradle-plugin-annotations",
|
||||
":kotlin-gradle-plugin-idea",
|
||||
":kotlin-gradle-plugin-idea-proto",
|
||||
":kotlin-gradle-plugin",
|
||||
":kotlin-gradle-plugin-model",
|
||||
":kotlin-tooling-metadata",
|
||||
":kotlin-tooling-core",
|
||||
":kotlin-reflect",
|
||||
":kotlin-test",
|
||||
":kotlin-gradle-subplugin-example",
|
||||
":kotlin-stdlib-common",
|
||||
":kotlin-stdlib",
|
||||
":kotlin-stdlib-jdk7",
|
||||
":kotlin-stdlib-jdk8",
|
||||
":kotlin-stdlib-js",
|
||||
":kotlin-stdlib-wasm",
|
||||
":examples:annotation-processor-example",
|
||||
":kotlin-assignment-compiler-plugin.embeddable",
|
||||
":kotlin-allopen-compiler-plugin.embeddable",
|
||||
":kotlin-noarg-compiler-plugin.embeddable",
|
||||
":kotlin-sam-with-receiver-compiler-plugin.embeddable",
|
||||
":kotlin-lombok-compiler-plugin.embeddable",
|
||||
":kotlinx-serialization-compiler-plugin.embeddable",
|
||||
":kotlin-annotation-processing-embeddable",
|
||||
":kotlin-script-runtime",
|
||||
":kotlin-scripting-common",
|
||||
":kotlin-scripting-jvm",
|
||||
":kotlin-scripting-compiler-embeddable",
|
||||
":kotlin-scripting-compiler-impl-embeddable",
|
||||
":kotlin-test-js-runner",
|
||||
":native:kotlin-klib-commonizer-embeddable",
|
||||
":native:kotlin-klib-commonizer-api",
|
||||
":compiler:build-tools:kotlin-build-tools-api",
|
||||
":compiler:build-tools:kotlin-build-tools-impl",
|
||||
)
|
||||
|
||||
fun Task.dependsOnKotlinGradlePluginInstall() {
|
||||
kotlinGradlePluginAndItsRequired.forEach {
|
||||
dependsOn("${it}:install")
|
||||
}
|
||||
}
|
||||
|
||||
fun Task.dependsOnKotlinGradlePluginPublish() {
|
||||
kotlinGradlePluginAndItsRequired.forEach {
|
||||
project.rootProject.tasks.findByPath("${it}:publish")?.let { task ->
|
||||
dependsOn(task)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Mixing JUnit4 and Junit5 in one module proved to be problematic, consider using separate modules instead
|
||||
enum class JUnitMode {
|
||||
JUnit4, JUnit5
|
||||
}
|
||||
|
||||
/**
|
||||
* @param parallel is redundant if @param jUnit5Enabled is true, because
|
||||
* JUnit5 supports parallel test execution by itself, without gradle help
|
||||
*/
|
||||
fun Project.projectTest(
|
||||
taskName: String = "test",
|
||||
parallel: Boolean = false,
|
||||
shortenTempRootName: Boolean = false,
|
||||
jUnitMode: JUnitMode = JUnitMode.JUnit4,
|
||||
maxHeapSizeMb: Int? = null,
|
||||
minHeapSizeMb: Int? = null,
|
||||
reservedCodeCacheSizeMb: Int = 256,
|
||||
defineJDKEnvVariables: List<JdkMajorVersion> = emptyList(),
|
||||
body: Test.() -> Unit = {}
|
||||
): TaskProvider<Test> {
|
||||
val shouldInstrument = project.providers.gradleProperty("kotlin.test.instrumentation.disable")
|
||||
.orNull?.toBoolean() != true
|
||||
if (shouldInstrument) {
|
||||
evaluationDependsOn(":test-instrumenter")
|
||||
}
|
||||
return getOrCreateTask<Test>(taskName) {
|
||||
dependsOn(":createIdeaHomeForTests")
|
||||
|
||||
doFirst {
|
||||
if (jUnitMode == JUnitMode.JUnit5) return@doFirst
|
||||
|
||||
val commandLineIncludePatterns = commandLineIncludePatterns.toMutableSet()
|
||||
val patterns = filter.includePatterns + commandLineIncludePatterns
|
||||
if (patterns.isEmpty() || patterns.any { '*' in it }) return@doFirst
|
||||
patterns.forEach { pattern ->
|
||||
var isClassPattern = false
|
||||
val maybeMethodName = pattern.substringAfterLast('.')
|
||||
val maybeClassFqName = if (maybeMethodName.isFirstChar(::isLowerCase)) {
|
||||
pattern.substringBeforeLast('.')
|
||||
} else {
|
||||
isClassPattern = true
|
||||
pattern
|
||||
}
|
||||
|
||||
if (!maybeClassFqName.substringAfterLast('.').isFirstChar(::isUpperCase)) {
|
||||
return@forEach
|
||||
}
|
||||
|
||||
val classFileNameWithoutExtension = maybeClassFqName.replace('.', '/')
|
||||
val classFileName = "$classFileNameWithoutExtension.class"
|
||||
|
||||
if (isClassPattern) {
|
||||
val innerClassPattern = "$pattern$*"
|
||||
if (pattern in commandLineIncludePatterns) {
|
||||
commandLineIncludePatterns.add(innerClassPattern)
|
||||
(filter as? DefaultTestFilter)?.setCommandLineIncludePatterns(commandLineIncludePatterns)
|
||||
} else {
|
||||
filter.includePatterns.add(innerClassPattern)
|
||||
}
|
||||
}
|
||||
|
||||
include { treeElement ->
|
||||
val path = treeElement.path
|
||||
if (treeElement.isDirectory) {
|
||||
classFileNameWithoutExtension.startsWith(path)
|
||||
} else {
|
||||
if (path == classFileName) return@include true
|
||||
if (!path.endsWith(".class")) return@include false
|
||||
path.startsWith("$classFileNameWithoutExtension$")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldInstrument) {
|
||||
val instrumentationArgsProperty = project.providers.gradleProperty("kotlin.test.instrumentation.args")
|
||||
val testInstrumenterOutputs = project.tasks.findByPath(":test-instrumenter:jar")!!.outputs.files
|
||||
doFirst {
|
||||
val agent = testInstrumenterOutputs.singleFile
|
||||
val args = instrumentationArgsProperty.orNull?.let { "=$it" }.orEmpty()
|
||||
jvmArgs("-javaagent:$agent$args")
|
||||
}
|
||||
dependsOn(":test-instrumenter:jar")
|
||||
}
|
||||
|
||||
jvmArgs(
|
||||
"-ea",
|
||||
"-XX:+HeapDumpOnOutOfMemoryError",
|
||||
"-XX:+UseCodeCacheFlushing",
|
||||
"-XX:ReservedCodeCacheSize=${reservedCodeCacheSizeMb}m",
|
||||
"-Djna.nosys=true"
|
||||
)
|
||||
|
||||
val junit5ParallelTestWorkers =
|
||||
project.kotlinBuildProperties.junit5NumberOfThreadsForParallelExecution ?: Runtime.getRuntime().availableProcessors()
|
||||
|
||||
val memoryPerTestProcessMb = maxHeapSizeMb ?: if (jUnitMode == JUnitMode.JUnit5)
|
||||
totalMaxMemoryForTestsMb.coerceIn(defaultMaxMemoryPerTestWorkerMb, defaultMaxMemoryPerTestWorkerMb * junit5ParallelTestWorkers)
|
||||
else
|
||||
defaultMaxMemoryPerTestWorkerMb
|
||||
|
||||
maxHeapSize = "${memoryPerTestProcessMb}m"
|
||||
|
||||
if (minHeapSizeMb != null) {
|
||||
minHeapSize = "${minHeapSizeMb}m"
|
||||
}
|
||||
|
||||
systemProperty("idea.is.unit.test", "true")
|
||||
systemProperty("idea.home.path", project.ideaHomePathForTests().canonicalPath)
|
||||
systemProperty("idea.use.native.fs.for.win", false)
|
||||
systemProperty("java.awt.headless", "true")
|
||||
environment("NO_FS_ROOTS_ACCESS_CHECK", "true")
|
||||
environment("PROJECT_CLASSES_DIRS", project.testSourceSet.output.classesDirs.asPath)
|
||||
environment("PROJECT_BUILD_DIR", project.buildDir)
|
||||
systemProperty("jps.kotlin.home", project.rootProject.extra["distKotlinHomeDir"]!!)
|
||||
systemProperty("org.jetbrains.kotlin.skip.muted.tests", if (project.rootProject.hasProperty("skipMutedTests")) "true" else "false")
|
||||
systemProperty("cacheRedirectorEnabled", project.rootProject.findProperty("cacheRedirectorEnabled")?.toString() ?: "false")
|
||||
project.kotlinBuildProperties.junit5NumberOfThreadsForParallelExecution?.let { n ->
|
||||
systemProperty("junit.jupiter.execution.parallel.config.strategy", "fixed")
|
||||
systemProperty("junit.jupiter.execution.parallel.config.fixed.parallelism", n)
|
||||
}
|
||||
|
||||
systemProperty("idea.ignore.disabled.plugins", "true")
|
||||
|
||||
var subProjectTempRoot: Path? = null
|
||||
val projectName = project.name
|
||||
val teamcity = project.rootProject.findProperty("teamcity") as? Map<*, *>
|
||||
doFirst {
|
||||
val systemTempRoot =
|
||||
// TC by default doesn't switch `teamcity.build.tempDir` to 'java.io.tmpdir' so it could cause to wasted disk space
|
||||
// Should be fixed soon on Teamcity side
|
||||
(teamcity?.get("teamcity.build.tempDir") as? String)
|
||||
?: System.getProperty("java.io.tmpdir")
|
||||
systemTempRoot.let {
|
||||
val prefix = (projectName + "Project_" + taskName + "_").takeUnless { shortenTempRootName }
|
||||
subProjectTempRoot = Files.createTempDirectory(File(systemTempRoot).toPath(), prefix)
|
||||
systemProperty("java.io.tmpdir", subProjectTempRoot.toString())
|
||||
}
|
||||
}
|
||||
|
||||
val fs = project.serviceOf<FileSystemOperations>()
|
||||
doLast {
|
||||
subProjectTempRoot?.let {
|
||||
try {
|
||||
fs.delete {
|
||||
delete(it)
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
logger.warn("Can't delete test temp root folder $it", e.printStackTrace())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (parallel && jUnitMode != JUnitMode.JUnit5) {
|
||||
val forks = (totalMaxMemoryForTestsMb / memoryPerTestProcessMb).coerceAtMost(16)
|
||||
maxParallelForks =
|
||||
project.providers.gradleProperty("kotlin.test.maxParallelForks").orNull?.toInt()
|
||||
?: forks.coerceIn(1, Runtime.getRuntime().availableProcessors())
|
||||
}
|
||||
|
||||
defineJDKEnvVariables.forEach { version ->
|
||||
val jdkHome = project.getToolchainJdkHomeFor(version).orNull ?: error("Can't find toolchain for $version")
|
||||
environment(version.envName, jdkHome)
|
||||
}
|
||||
}.apply { configure(body) }
|
||||
}
|
||||
|
||||
val defaultMaxMemoryPerTestWorkerMb = 1600
|
||||
val reservedMemoryMb = 9000 // system processes, gradle daemon, kotlin daemon, etc ...
|
||||
|
||||
val totalMaxMemoryForTestsMb: Int
|
||||
get() {
|
||||
val mxbean = ManagementFactory.getOperatingSystemMXBean() as OperatingSystemMXBean
|
||||
return (mxbean.totalPhysicalMemorySize / 1048576 - reservedMemoryMb).toInt()
|
||||
}
|
||||
|
||||
val Test.commandLineIncludePatterns: Set<String>
|
||||
get() = (filter as? DefaultTestFilter)?.commandLineIncludePatterns.orEmpty()
|
||||
|
||||
private inline fun String.isFirstChar(f: (Char) -> Boolean) = isNotEmpty() && f(first())
|
||||
|
||||
inline fun <reified T : Task> Project.getOrCreateTask(taskName: String, noinline body: T.() -> Unit): TaskProvider<T> =
|
||||
if (tasks.names.contains(taskName)) tasks.named(taskName, T::class.java).apply { configure(body) }
|
||||
else tasks.register(taskName, T::class.java, body)
|
||||
|
||||
object TaskUtils {
|
||||
fun useAndroidSdk(task: Task) {
|
||||
task.useAndroidConfiguration(systemPropertyName = "android.sdk", configName = "androidSdk")
|
||||
}
|
||||
|
||||
fun useAndroidJar(task: Task) {
|
||||
task.useAndroidConfiguration(systemPropertyName = "android.jar", configName = "androidJar")
|
||||
}
|
||||
|
||||
fun useAndroidEmulator(task: Task) {
|
||||
task.useAndroidConfiguration(systemPropertyName = "android.sdk", configName = "androidEmulator")
|
||||
}
|
||||
}
|
||||
|
||||
private fun Task.useAndroidConfiguration(systemPropertyName: String, configName: String) {
|
||||
val configuration = with(project) {
|
||||
configurations.getOrCreate(configName)
|
||||
.also {
|
||||
if (it.allDependencies.matching { dep ->
|
||||
dep is ProjectDependency &&
|
||||
dep.targetConfiguration == configName &&
|
||||
dep.dependencyProject.path == ":dependencies:android-sdk"
|
||||
}.count() == 0) {
|
||||
dependencies.add(
|
||||
configName,
|
||||
dependencies.project(":dependencies:android-sdk", configuration = configName)
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dependsOn(configuration)
|
||||
|
||||
if (this is Test) {
|
||||
val androidFilePath = configuration.singleFile.canonicalPath
|
||||
doFirst {
|
||||
systemProperty(systemPropertyName, androidFilePath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Task.useAndroidSdk() {
|
||||
TaskUtils.useAndroidSdk(this)
|
||||
}
|
||||
|
||||
fun Task.useAndroidJar() {
|
||||
TaskUtils.useAndroidJar(this)
|
||||
}
|
||||
|
||||
fun Task.acceptAndroidSdkLicenses() {
|
||||
val separator = System.lineSeparator()
|
||||
with(project) {
|
||||
val androidSdk = configurations["androidSdk"].singleFile
|
||||
val sdkLicensesDir = androidSdk.resolve("licenses").also {
|
||||
if (!it.exists()) it.mkdirs()
|
||||
}
|
||||
|
||||
val sdkLicenses = listOf(
|
||||
"8933bad161af4178b1185d1a37fbf41ea5269c55",
|
||||
"d56f5187479451eabf01fb78af6dfcb131a6481e",
|
||||
"24333f8a63b6825ea9c5514f83c2829b004d1fee",
|
||||
)
|
||||
val sdkPreviewLicense = "84831b9409646a918e30573bab4c9c91346d8abd"
|
||||
|
||||
val sdkLicenseFile = sdkLicensesDir.resolve("android-sdk-license")
|
||||
if (!sdkLicenseFile.exists()) {
|
||||
sdkLicenseFile.createNewFile()
|
||||
sdkLicenseFile.writeText(
|
||||
sdkLicenses.joinToString(separator = separator)
|
||||
)
|
||||
} else {
|
||||
sdkLicenses
|
||||
.subtract(
|
||||
sdkLicenseFile.readText().lines()
|
||||
)
|
||||
.forEach {
|
||||
sdkLicenseFile.appendText("$it$separator")
|
||||
}
|
||||
}
|
||||
|
||||
val sdkPreviewLicenseFile = sdkLicensesDir.resolve("android-sdk-preview-license")
|
||||
if (!sdkPreviewLicenseFile.exists()) {
|
||||
sdkPreviewLicenseFile.writeText(sdkPreviewLicense)
|
||||
} else {
|
||||
if (sdkPreviewLicense != sdkPreviewLicenseFile.readText().trim()) {
|
||||
sdkPreviewLicenseFile.writeText(sdkPreviewLicense)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.confugureFirPluginAnnotationsDependency(testTask: TaskProvider<Test>) {
|
||||
val firPluginJvmAnnotations: Configuration by configurations.creating
|
||||
val firPluginJsAnnotations: Configuration by configurations.creating {
|
||||
attributes {
|
||||
attribute(Usage.USAGE_ATTRIBUTE, objects.named(org.jetbrains.kotlin.gradle.plugin.mpp.KotlinUsages.KOTLIN_RUNTIME))
|
||||
attribute(org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType.attribute, org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType.js)
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
firPluginJvmAnnotations(project(":plugins:fir-plugin-prototype:plugin-annotations")) { isTransitive = false }
|
||||
firPluginJsAnnotations(project(":plugins:fir-plugin-prototype:plugin-annotations")) { isTransitive = false }
|
||||
}
|
||||
|
||||
testTask.configure {
|
||||
dependsOn(firPluginJvmAnnotations, firPluginJsAnnotations)
|
||||
val localFirPluginJvmAnnotations: FileCollection = firPluginJvmAnnotations
|
||||
val localFirPluginJsAnnotations: FileCollection = firPluginJsAnnotations
|
||||
doFirst {
|
||||
systemProperty("firPluginAnnotations.jvm.path", localFirPluginJvmAnnotations.singleFile.canonicalPath)
|
||||
systemProperty("firPluginAnnotations.js.path", localFirPluginJsAnnotations.singleFile.canonicalPath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun Project.optInToExperimentalCompilerApi() {
|
||||
@Suppress("DEPRECATION")
|
||||
tasks.withType<org.jetbrains.kotlin.gradle.dsl.KotlinCompile<*>>().configureEach {
|
||||
kotlinOptions {
|
||||
freeCompilerArgs += "-opt-in=org.jetbrains.kotlin.compiler.plugin.ExperimentalCompilerApi"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
import com.gradle.enterprise.gradleplugin.testdistribution.TestDistributionExtension
|
||||
import org.gradle.api.tasks.testing.Test
|
||||
import org.gradle.internal.os.OperatingSystem
|
||||
|
||||
|
||||
fun Test.configureTestDistribution(configure: TestDistributionExtension.() -> Unit = {}) {
|
||||
val isTeamcityBuild = project.kotlinBuildProperties.isTeamcityBuild
|
||||
val testDistributionEnabled =
|
||||
project.findProperty("kotlin.build.test.distribution.enabled")?.toString()?.toBoolean() ?: false
|
||||
|
||||
useJUnitPlatform()
|
||||
extensions.configure(TestDistributionExtension::class.java) {
|
||||
enabled.set(testDistributionEnabled)
|
||||
maxRemoteExecutors.set(20)
|
||||
if (isTeamcityBuild) {
|
||||
requirements.set(setOf("os=${OperatingSystem.current().familyName}"))
|
||||
} else {
|
||||
maxLocalExecutors.set(0)
|
||||
}
|
||||
configure()
|
||||
}
|
||||
}
|
||||
|
||||
fun Test.isTestDistributionEnabled(): Boolean =
|
||||
extensions.findByType(TestDistributionExtension::class.java)?.enabled?.orNull ?: false
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
import org.gradle.api.Project
|
||||
import org.gradle.api.tasks.testing.Test
|
||||
import com.gradle.enterprise.gradleplugin.testretry.retry
|
||||
import org.gradle.kotlin.dsl.withType
|
||||
|
||||
fun Project.configureTestRetriesForTestTasks() {
|
||||
val testRetryMaxRetries = findProperty("kotlin.build.testRetry.maxRetries")
|
||||
?.toString()?.toInt()
|
||||
?: (if (kotlinBuildProperties.isTeamcityBuild) 3 else 0)
|
||||
|
||||
tasks.withType<Test>().configureEach {
|
||||
retry {
|
||||
maxRetries.set(testRetryMaxRetries)
|
||||
maxFailures.set(20)
|
||||
failOnPassedAfterRetry.set(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
org.gradle.jvmargs=-Duser.country=US -Dfile.encoding=UTF-8
|
||||
org.gradle.kotlin.dsl.allWarningsAsErrors=true
|
||||
|
||||
cacheRedirectorEnabled=true
|
||||
|
||||
kotlin.build.gradlePlugin.version=0.0.39
|
||||
kotlin.options.suppressFreeCompilerArgsModificationWarning=true
|
||||
|
||||
# Please keep it in sync with root gradle.properties.
|
||||
# It's currently needed for proper configuration cache work, the reason will be investigated later
|
||||
org.gradle.java.installations.fromEnv=\
|
||||
JDK_1_6,JDK_16,\
|
||||
JDK_1_7,JDK_17,\
|
||||
JDK_1_8,JDK_18,\
|
||||
JDK_9_0,JDK_9,\
|
||||
JDK_10_0,JDK_10,\
|
||||
JDK_11_0,JDK_11,\
|
||||
JDK_15_0,JDK_15,\
|
||||
JDK_16_0,\
|
||||
JDK_17_0
|
||||
@@ -0,0 +1,45 @@
|
||||
pluginManagement {
|
||||
apply from: '../scripts/cache-redirector.settings.gradle.kts'
|
||||
apply from: '../scripts/kotlin-bootstrap.settings.gradle.kts'
|
||||
|
||||
includeBuild '../gradle-settings-conventions'
|
||||
|
||||
repositories {
|
||||
maven { url "https://maven.pkg.jetbrains.space/kotlin/p/kotlin/kotlin-dependencies" }
|
||||
mavenCentral()
|
||||
google()
|
||||
gradlePluginPortal()
|
||||
}
|
||||
}
|
||||
|
||||
plugins {
|
||||
id "build-cache"
|
||||
id "gradle-enterprise"
|
||||
id "jvm-toolchain-provisioning"
|
||||
id "kotlin-daemon-config"
|
||||
}
|
||||
|
||||
File versionPropertiesFile = new File(rootProject.projectDir.parentFile, "../gradle/versions.properties")
|
||||
def versionProperties = new Properties()
|
||||
versionPropertiesFile.withInputStream {
|
||||
versionProperties.load(it)
|
||||
}
|
||||
dependencyResolutionManagement {
|
||||
components {
|
||||
withModule("com.google.code.gson:gson") {
|
||||
allVariants {
|
||||
withDependencies {
|
||||
add("com.google.code.gson:gson") {
|
||||
version {
|
||||
it.require(versionProperties['versions.gson'])
|
||||
}
|
||||
because("Force using same gson version because of https://github.com/google/gson/pull/1991")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
include ":buildsrc-compat"
|
||||
include ":prepare-deps"
|
||||
@@ -64,7 +64,7 @@ fun getRootSettings(
|
||||
val gradleInternal = (gradle as GradleInternal)
|
||||
return when {
|
||||
gradleInternal.isRootBuild() ||
|
||||
settings.rootProject.name == "gradle-settings-conventions" -> {
|
||||
setOf("gradle-settings-conventions", "gradle-build-conventions").contains(settings.rootProject.name) -> {
|
||||
settings
|
||||
}
|
||||
else -> {
|
||||
@@ -91,6 +91,7 @@ val kotlinRootDir: File = when (rootSettings.rootProject.name) {
|
||||
}
|
||||
"benchmarksAnalyzer", "performance-server" -> rootSettings.rootDir.parentFile.parentFile.parentFile
|
||||
"gradle-settings-conventions" -> rootSettings.rootDir.parentFile.parentFile
|
||||
"gradle-build-conventions" -> rootSettings.rootDir.parentFile.parentFile
|
||||
"performance" -> rootSettings.rootDir.parentFile.parentFile
|
||||
"ui" -> rootSettings.rootDir.parentFile.parentFile.parentFile.parentFile
|
||||
else -> rootSettings.rootDir
|
||||
|
||||
Reference in New Issue
Block a user