KT-33908 Make Kotlin Gradle plugin compatible with configuration cache
#KT-33908 Fixed
This commit is contained in:
committed by
nataliya.valtman
parent
ea57b4cccb
commit
a766369e72
+1
-1
@@ -1,5 +1,5 @@
|
|||||||
distributionBase=GRADLE_USER_HOME
|
distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-6.0.1-bin.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-6.6-20200603220033+0000-bin.zip
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
|
|||||||
+1
-1
@@ -726,7 +726,7 @@ fun getSomething() = 10
|
|||||||
|
|
||||||
project.build("assemble", options = options) {
|
project.build("assemble", options = options) {
|
||||||
assertFailed()
|
assertFailed()
|
||||||
assertContains("Class 'User' is not abstract and does not implement abstract member public abstract fun writeToParcel")
|
assertContainsRegex("Class 'User' is not abstract and does not implement abstract member public abstract fun (writeToParcel|describeContents)".toRegex())
|
||||||
}
|
}
|
||||||
|
|
||||||
File(project.projectDir, "app/build.gradle").modify { it.replace("[\"views\"]", "[\"parcelize\", \"views\"]") }
|
File(project.projectDir, "app/build.gradle").modify { it.replace("[\"views\"]", "[\"parcelize\", \"views\"]") }
|
||||||
|
|||||||
+14
-4
@@ -13,7 +13,6 @@ import org.jetbrains.kotlin.gradle.model.ModelContainer
|
|||||||
import org.jetbrains.kotlin.gradle.model.ModelFetcherBuildAction
|
import org.jetbrains.kotlin.gradle.model.ModelFetcherBuildAction
|
||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinJsCompilerType
|
import org.jetbrains.kotlin.gradle.plugin.KotlinJsCompilerType
|
||||||
import org.jetbrains.kotlin.gradle.util.*
|
import org.jetbrains.kotlin.gradle.util.*
|
||||||
import org.jetbrains.kotlin.test.util.trimTrailingWhitespaces
|
|
||||||
import org.junit.After
|
import org.junit.After
|
||||||
import org.junit.AfterClass
|
import org.junit.AfterClass
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
@@ -22,6 +21,8 @@ import java.io.File
|
|||||||
import java.util.regex.Pattern
|
import java.util.regex.Pattern
|
||||||
import kotlin.test.*
|
import kotlin.test.*
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.test.util.trimTrailingWhitespaces
|
||||||
|
|
||||||
val SYSTEM_LINE_SEPARATOR: String = System.getProperty("line.separator")
|
val SYSTEM_LINE_SEPARATOR: String = System.getProperty("line.separator")
|
||||||
|
|
||||||
abstract class BaseGradleIT {
|
abstract class BaseGradleIT {
|
||||||
@@ -205,9 +206,15 @@ abstract class BaseGradleIT {
|
|||||||
val withBuildCache: Boolean = false,
|
val withBuildCache: Boolean = false,
|
||||||
val kaptOptions: KaptOptions? = null,
|
val kaptOptions: KaptOptions? = null,
|
||||||
val parallelTasksInProject: Boolean? = null,
|
val parallelTasksInProject: Boolean? = null,
|
||||||
val jsCompilerType: KotlinJsCompilerType? = null
|
val jsCompilerType: KotlinJsCompilerType? = null,
|
||||||
|
val configurationCache: Boolean = false,
|
||||||
|
val configurationCacheProblems: ConfigurationCacheProblems = ConfigurationCacheProblems.FAIL
|
||||||
)
|
)
|
||||||
|
|
||||||
|
enum class ConfigurationCacheProblems {
|
||||||
|
FAIL, WARN
|
||||||
|
}
|
||||||
|
|
||||||
data class KaptOptions(
|
data class KaptOptions(
|
||||||
val verbose: Boolean,
|
val verbose: Boolean,
|
||||||
val useWorkers: Boolean,
|
val useWorkers: Boolean,
|
||||||
@@ -707,9 +714,9 @@ Finished executing task ':$taskName'|
|
|||||||
val xmlString = buildString {
|
val xmlString = buildString {
|
||||||
appendln("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
|
appendln("<?xml version=\"1.0\" encoding=\"UTF-8\"?>")
|
||||||
appendln("<results>")
|
appendln("<results>")
|
||||||
files.forEach {
|
files.forEach { file ->
|
||||||
appendln(
|
appendln(
|
||||||
it.readText()
|
file.readText()
|
||||||
.trimTrailingWhitespaces()
|
.trimTrailingWhitespaces()
|
||||||
.replace(projectDir.absolutePath, "/\$PROJECT_DIR$")
|
.replace(projectDir.absolutePath, "/\$PROJECT_DIR$")
|
||||||
.replace(projectDir.name, "\$PROJECT_NAME$")
|
.replace(projectDir.name, "\$PROJECT_NAME$")
|
||||||
@@ -801,6 +808,9 @@ Finished executing task ':$taskName'|
|
|||||||
add("-Pkotlin.js.compiler=$it")
|
add("-Pkotlin.js.compiler=$it")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
add("-Dorg.gradle.unsafe.configuration-cache=${options.configurationCache}")
|
||||||
|
add("-Dorg.gradle.unsafe.configuration-cache-problems=${options.configurationCacheProblems.name.toLowerCase()}")
|
||||||
|
|
||||||
// Workaround: override a console type set in the user machine gradle.properties (since Gradle 4.3):
|
// Workaround: override a console type set in the user machine gradle.properties (since Gradle 4.3):
|
||||||
add("--console=plain")
|
add("--console=plain")
|
||||||
addAll(options.freeCommandLineArgs)
|
addAll(options.freeCommandLineArgs)
|
||||||
|
|||||||
+73
@@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.gradle
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.gradle.util.AGPVersion
|
||||||
|
import org.jetbrains.kotlin.test.KotlinTestUtils
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
class ConfigurationCacheForAndroidIT : AbstractConfigurationCacheIT() {
|
||||||
|
private val androidGradlePluginVersion: AGPVersion
|
||||||
|
get() = AGPVersion.v4_2_0
|
||||||
|
|
||||||
|
override fun defaultBuildOptions() =
|
||||||
|
super.defaultBuildOptions().copy(
|
||||||
|
androidHome = KotlinTestUtils.findAndroidSdk(),
|
||||||
|
androidGradlePluginVersion = androidGradlePluginVersion,
|
||||||
|
configurationCache = true,
|
||||||
|
/* AGP causes a configuration cache problem:
|
||||||
|
- plugin 'com.android.internal.application': registration of listener on 'TaskExecutionGraph.addTaskExecutionListener' is unsupported
|
||||||
|
|
||||||
|
which causes tests to fail when configuration-cache-problems=fail is used.
|
||||||
|
However, everything works fine with WARN level reporting.
|
||||||
|
TODO: switch to FAIL when AGP no longer causes the cache problem
|
||||||
|
*/
|
||||||
|
configurationCacheProblems = ConfigurationCacheProblems.WARN
|
||||||
|
)
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testAndroidKaptProject() = with(Project("android-dagger", directoryPrefix = "kapt2")) {
|
||||||
|
applyAndroid40Alpha4KotlinVersionWorkaround()
|
||||||
|
projectDir.resolve("gradle.properties").appendText("\nkapt.incremental.apt=false")
|
||||||
|
testConfigurationCacheOf(":app:compileDebugKotlin", ":app:kaptDebugKotlin", ":app:kaptGenerateStubsDebugKotlin")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testKotlinAndroidProject() = with(Project("AndroidProject")) {
|
||||||
|
applyAndroid40Alpha4KotlinVersionWorkaround()
|
||||||
|
testConfigurationCacheOf(":Lib:compileFlavor1DebugKotlin", ":Android:compileFlavor1DebugKotlin")
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Android Gradle plugin 4.0-alpha4 depends on the EAP versions of some o.j.k modules.
|
||||||
|
* Force the current Kotlin version, so the EAP versions are not queried from the
|
||||||
|
* test project's repositories, where there's no 'kotlin-eap' repo.
|
||||||
|
* TODO remove this workaround once an Android Gradle plugin version is used that depends on the stable Kotlin version
|
||||||
|
*/
|
||||||
|
private fun Project.applyAndroid40Alpha4KotlinVersionWorkaround() {
|
||||||
|
setupWorkingDir()
|
||||||
|
|
||||||
|
val resolutionStrategyHack = """
|
||||||
|
configurations.all {
|
||||||
|
resolutionStrategy.dependencySubstitution.all { dependency ->
|
||||||
|
def requested = dependency.requested
|
||||||
|
if (requested instanceof ModuleComponentSelector && requested.group == 'org.jetbrains.kotlin') {
|
||||||
|
dependency.useTarget requested.group + ':' + requested.module + ':' + '${defaultBuildOptions().kotlinVersion}'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""".trimIndent()
|
||||||
|
|
||||||
|
gradleBuildScript().appendText(
|
||||||
|
"\n" + """
|
||||||
|
buildscript {
|
||||||
|
$resolutionStrategyHack
|
||||||
|
}
|
||||||
|
$resolutionStrategyHack
|
||||||
|
""".trimIndent()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
+118
@@ -0,0 +1,118 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.gradle
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.gradle.util.findFileByName
|
||||||
|
import org.junit.Test
|
||||||
|
import java.io.File
|
||||||
|
import java.net.URI
|
||||||
|
import java.util.Arrays.asList
|
||||||
|
import kotlin.test.fail
|
||||||
|
|
||||||
|
class ConfigurationCacheIT : AbstractConfigurationCacheIT() {
|
||||||
|
@Test
|
||||||
|
fun testSimpleKotlinJvmProject() = with(Project("kotlinProject")) {
|
||||||
|
testConfigurationCacheOf(":compileKotlin")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testIncrementalKaptProject() = with(Project("kaptIncrementalCompilationProject")) {
|
||||||
|
setupIncrementalAptProject("AGGREGATING")
|
||||||
|
|
||||||
|
testConfigurationCacheOf(
|
||||||
|
":compileKotlin",
|
||||||
|
":kaptKotlin",
|
||||||
|
buildOptions = defaultBuildOptions().copy(
|
||||||
|
incremental = true,
|
||||||
|
kaptOptions = KaptOptions(
|
||||||
|
verbose = true,
|
||||||
|
useWorkers = true,
|
||||||
|
incrementalKapt = true,
|
||||||
|
includeCompileClasspath = false
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testInstantExecution() = with(Project("instantExecution")) {
|
||||||
|
testConfigurationCacheOf("assemble", executedTaskNames = asList(":lib-project:compileKotlin"))
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testInstantExecutionForJs() = with(Project("instantExecutionToJs")) {
|
||||||
|
testConfigurationCacheOf("assemble", executedTaskNames = asList(":compileKotlin2Js"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class AbstractConfigurationCacheIT : BaseGradleIT() {
|
||||||
|
override fun defaultBuildOptions() =
|
||||||
|
super.defaultBuildOptions().copy(configurationCache = true)
|
||||||
|
|
||||||
|
override val defaultGradleVersion: GradleVersionRequired = GradleVersionRequired.AtLeast("6.6-rc-3")
|
||||||
|
|
||||||
|
protected fun Project.testConfigurationCacheOf(
|
||||||
|
vararg taskNames: String,
|
||||||
|
executedTaskNames: List<String>? = null,
|
||||||
|
buildOptions: BuildOptions = defaultBuildOptions()
|
||||||
|
) {
|
||||||
|
// First, run a build that serializes the tasks state for instant execution in further builds
|
||||||
|
|
||||||
|
val executedTask: List<String> = executedTaskNames ?: taskNames.toList()
|
||||||
|
|
||||||
|
build(*taskNames, options = buildOptions) {
|
||||||
|
assertSuccessful()
|
||||||
|
assertTasksExecuted(executedTask)
|
||||||
|
assertContains("Calculating task graph as no configuration cache is available for tasks: ${taskNames.joinToString(separator = " ")}")
|
||||||
|
checkInstantExecutionSucceeded()
|
||||||
|
}
|
||||||
|
|
||||||
|
build("clean") {
|
||||||
|
assertSuccessful()
|
||||||
|
}
|
||||||
|
|
||||||
|
// Then run a build where tasks states are deserialized to check that they work correctly in this mode
|
||||||
|
build(*taskNames, options = buildOptions) {
|
||||||
|
assertSuccessful()
|
||||||
|
assertTasksExecuted(executedTask)
|
||||||
|
assertContains("Reusing configuration cache.")
|
||||||
|
}
|
||||||
|
|
||||||
|
build(*taskNames, options = buildOptions) {
|
||||||
|
assertSuccessful()
|
||||||
|
assertTasksUpToDate(executedTask)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Project.checkInstantExecutionSucceeded() {
|
||||||
|
instantExecutionReportFile()?.let { htmlReportFile ->
|
||||||
|
fail("Instant execution problems were found, check ${htmlReportFile.asClickableFileUrl()} for details.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies all files from the directory containing the given [htmlReportFile] to a
|
||||||
|
* fresh temp dir and returns a reference to the copied [htmlReportFile] in the new
|
||||||
|
* directory.
|
||||||
|
*/
|
||||||
|
private fun copyReportToTempDir(htmlReportFile: File): File =
|
||||||
|
createTempDir().let { tempDir ->
|
||||||
|
htmlReportFile.parentFile.copyRecursively(tempDir)
|
||||||
|
tempDir.resolve(htmlReportFile.name)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The instant execution report file, if exists, indicates problems were
|
||||||
|
* found while caching the task graph.
|
||||||
|
*/
|
||||||
|
private fun Project.instantExecutionReportFile() = projectDir
|
||||||
|
.resolve("configuration-cache")
|
||||||
|
.findFileByName("configuration-cache-report.html")
|
||||||
|
?.let { copyReportToTempDir(it) }
|
||||||
|
|
||||||
|
private fun File.asClickableFileUrl(): String =
|
||||||
|
URI("file", "", toURI().path, null, null).toString()
|
||||||
|
}
|
||||||
-149
@@ -1,149 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package org.jetbrains.kotlin.gradle
|
|
||||||
|
|
||||||
import org.jetbrains.kotlin.gradle.util.AGPVersion
|
|
||||||
import org.jetbrains.kotlin.gradle.util.findFileByName
|
|
||||||
import org.jetbrains.kotlin.test.KotlinTestUtils
|
|
||||||
import org.junit.Test
|
|
||||||
import java.io.File
|
|
||||||
import java.net.URI
|
|
||||||
import kotlin.test.fail
|
|
||||||
|
|
||||||
class InstantExecutionIT : BaseGradleIT() {
|
|
||||||
private val androidGradlePluginVersion: AGPVersion
|
|
||||||
get() = AGPVersion.v4_0_ALPHA_8
|
|
||||||
|
|
||||||
override fun defaultBuildOptions() =
|
|
||||||
super.defaultBuildOptions().copy(
|
|
||||||
androidHome = KotlinTestUtils.findAndroidSdk(),
|
|
||||||
androidGradlePluginVersion = androidGradlePluginVersion
|
|
||||||
)
|
|
||||||
|
|
||||||
private val minimumGradleVersion = GradleVersionRequired.AtLeast("6.1-rc-3")
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testSimpleKotlinJvmProject() = with(Project("kotlinProject", minimumGradleVersion)) {
|
|
||||||
testInstantExecutionOf(":compileKotlin")
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testSimpleKotlinAndroidProject() = with(Project("android-dagger", minimumGradleVersion, "kapt2")) {
|
|
||||||
applyAndroid40Alpha4KotlinVersionWorkaround()
|
|
||||||
projectDir.resolve("gradle.properties").appendText("\nkapt.incremental.apt=false")
|
|
||||||
testInstantExecutionOf(":app:compileDebugKotlin", ":app:kaptDebugKotlin", ":app:kaptGenerateStubsDebugKotlin")
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
fun testIncrementalKaptProject() = with(getIncrementalKaptProject()) {
|
|
||||||
testInstantExecutionOf(
|
|
||||||
":compileKotlin",
|
|
||||||
":kaptKotlin",
|
|
||||||
buildOptions = defaultBuildOptions().copy(
|
|
||||||
incremental = true,
|
|
||||||
kaptOptions = KaptOptions(
|
|
||||||
verbose = true,
|
|
||||||
useWorkers = true,
|
|
||||||
incrementalKapt = true,
|
|
||||||
includeCompileClasspath = false
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getIncrementalKaptProject() =
|
|
||||||
Project("kaptIncrementalCompilationProject", minimumGradleVersion).apply {
|
|
||||||
setupIncrementalAptProject("AGGREGATING")
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun Project.testInstantExecutionOf(vararg taskNames: String, buildOptions: BuildOptions = defaultBuildOptions()) {
|
|
||||||
// First, run a build that serializes the tasks state for instant execution in further builds
|
|
||||||
instantExecutionOf(*taskNames, buildOptions = buildOptions) {
|
|
||||||
assertSuccessful()
|
|
||||||
assertTasksExecuted(*taskNames)
|
|
||||||
checkInstantExecutionSucceeded()
|
|
||||||
}
|
|
||||||
|
|
||||||
build("clean") {
|
|
||||||
assertSuccessful()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Then run a build where tasks states are deserialized to check that they work correctly in this mode
|
|
||||||
instantExecutionOf(*taskNames, buildOptions = buildOptions) {
|
|
||||||
assertSuccessful()
|
|
||||||
assertTasksExecuted(*taskNames)
|
|
||||||
}
|
|
||||||
|
|
||||||
instantExecutionOf(*taskNames, buildOptions = buildOptions) {
|
|
||||||
assertSuccessful()
|
|
||||||
assertTasksUpToDate(*taskNames)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun Project.checkInstantExecutionSucceeded() {
|
|
||||||
instantExecutionReportFile()?.let { htmlReportFile ->
|
|
||||||
fail("Instant execution problems were found, check ${htmlReportFile.asClickableFileUrl()} for details.")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun Project.instantExecutionOf(
|
|
||||||
vararg tasks: String,
|
|
||||||
buildOptions: BuildOptions = defaultBuildOptions(),
|
|
||||||
check: CompiledProject.() -> Unit
|
|
||||||
) =
|
|
||||||
build("-Dorg.gradle.unsafe.instant-execution=true", *tasks, options = buildOptions, check = check)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Copies all files from the directory containing the given [htmlReportFile] to a
|
|
||||||
* fresh temp dir and returns a reference to the copied [htmlReportFile] in the new
|
|
||||||
* directory.
|
|
||||||
*/
|
|
||||||
private fun copyReportToTempDir(htmlReportFile: File): File =
|
|
||||||
createTempDir().let { tempDir ->
|
|
||||||
htmlReportFile.parentFile.copyRecursively(tempDir)
|
|
||||||
tempDir.resolve(htmlReportFile.name)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The instant execution report file, if exists, indicates problems were
|
|
||||||
* found while caching the task graph.
|
|
||||||
*/
|
|
||||||
private fun Project.instantExecutionReportFile() = projectDir
|
|
||||||
.resolve(".instant-execution-state")
|
|
||||||
.findFileByName("instant-execution-report.html")
|
|
||||||
?.let { copyReportToTempDir(it) }
|
|
||||||
|
|
||||||
private fun File.asClickableFileUrl(): String =
|
|
||||||
URI("file", "", toURI().path, null, null).toString()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Android Gradle plugin 4.0-alpha4 depends on the EAP versions of some o.j.k modules.
|
|
||||||
* Force the current Kotlin version, so the EAP versions are not queried from the
|
|
||||||
* test project's repositories, where there's no 'kotlin-eap' repo.
|
|
||||||
* TODO remove this workaround once an Android Gradle plugin version is used that depends on the stable Kotlin version
|
|
||||||
*/
|
|
||||||
private fun Project.applyAndroid40Alpha4KotlinVersionWorkaround() {
|
|
||||||
setupWorkingDir()
|
|
||||||
|
|
||||||
val resolutionStrategyHack = """
|
|
||||||
configurations.all {
|
|
||||||
resolutionStrategy.dependencySubstitution.all { dependency ->
|
|
||||||
def requested = dependency.requested
|
|
||||||
if (requested instanceof ModuleComponentSelector && requested.group == 'org.jetbrains.kotlin') {
|
|
||||||
dependency.useTarget requested.group + ':' + requested.module + ':' + '${defaultBuildOptions().kotlinVersion}'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
""".trimIndent()
|
|
||||||
|
|
||||||
gradleBuildScript().appendText("\n" + """
|
|
||||||
buildscript {
|
|
||||||
$resolutionStrategyHack
|
|
||||||
}
|
|
||||||
$resolutionStrategyHack
|
|
||||||
""".trimIndent())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
+2
-2
@@ -365,7 +365,7 @@ class KotlinGradleIT : BaseGradleIT() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
fun testDowngradeTo106() {
|
fun testDowngradePluginVersion() {
|
||||||
val project = Project("kotlinProject")
|
val project = Project("kotlinProject")
|
||||||
val options = defaultBuildOptions().copy(incremental = true, withDaemon = false)
|
val options = defaultBuildOptions().copy(incremental = true, withDaemon = false)
|
||||||
|
|
||||||
@@ -373,7 +373,7 @@ class KotlinGradleIT : BaseGradleIT() {
|
|||||||
assertSuccessful()
|
assertSuccessful()
|
||||||
}
|
}
|
||||||
|
|
||||||
project.build("clean", "assemble", options = options.copy(kotlinVersion = "1.0.6")) {
|
project.build("clean", "assemble", options = options.copy(kotlinVersion = "1.3.41")) {
|
||||||
assertSuccessful()
|
assertSuccessful()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-1
@@ -78,7 +78,9 @@ class UpToDateIT : BaseGradleIT() {
|
|||||||
val originalPaths get() = originalCompilerCp.map { it.replace("\\", "/") }.joinToString(", ") { "'$it'" }
|
val originalPaths get() = originalCompilerCp.map { it.replace("\\", "/") }.joinToString(", ") { "'$it'" }
|
||||||
|
|
||||||
override fun initProject(project: Project) = with(project) {
|
override fun initProject(project: Project) = with(project) {
|
||||||
buildGradle.appendText("\nprintln 'compiler_cp=' + compileKotlin.getComputedCompilerClasspath\$kotlin_gradle_plugin()")
|
buildGradle.appendText(
|
||||||
|
"\nafterEvaluate { println 'compiler_cp=' + compileKotlin.getComputedCompilerClasspath\$kotlin_gradle_plugin() }"
|
||||||
|
)
|
||||||
build("clean") { originalCompilerCp = "compiler_cp=\\[(.*)]".toRegex().find(output)!!.groupValues[1].split(", ") }
|
build("clean") { originalCompilerCp = "compiler_cp=\\[(.*)]".toRegex().find(output)!!.groupValues[1].split(", ") }
|
||||||
buildGradle.appendText("""${'\n'}
|
buildGradle.appendText("""${'\n'}
|
||||||
// Add Kapt to the project to test its input checks as well:
|
// Add Kapt to the project to test its input checks as well:
|
||||||
|
|||||||
+2
-1
@@ -24,6 +24,7 @@ class AGPVersion private constructor(private val versionNumber: VersionNumber) {
|
|||||||
val v3_3_2 = fromString("3.3.2")
|
val v3_3_2 = fromString("3.3.2")
|
||||||
val v3_4_1 = fromString("3.4.1")
|
val v3_4_1 = fromString("3.4.1")
|
||||||
val v3_6_0 = fromString("3.6.0")
|
val v3_6_0 = fromString("3.6.0")
|
||||||
val v4_0_ALPHA_8 = fromString("4.0.0-alpha08")
|
val v4_1_0 = fromString("4.1.0-beta02")
|
||||||
|
val v4_2_0 = fromString("4.2.0-alpha07")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
subprojects {
|
||||||
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
}
|
||||||
+5
@@ -0,0 +1,5 @@
|
|||||||
|
apply plugin: 'kotlin'
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package libproject
|
||||||
|
|
||||||
|
class Util {
|
||||||
|
val projectName: String = "lib-project"
|
||||||
|
}
|
||||||
+6
@@ -0,0 +1,6 @@
|
|||||||
|
apply plugin: 'kotlin'
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
||||||
|
compile project(':lib-project')
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
import libProject.Util
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
println(Util.projectName)
|
||||||
|
}
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
include ':main-project', ':lib-project'
|
||||||
+37
@@ -0,0 +1,37 @@
|
|||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
dependencies {
|
||||||
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apply plugin: 'kotlin2js'
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
mavenLocal()
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile "org.jetbrains.kotlin:kotlin-stdlib-js:$kotlin_version"
|
||||||
|
testCompile "org.jetbrains.kotlin:kotlin-test-js:$kotlin_version"
|
||||||
|
}
|
||||||
|
|
||||||
|
task jarSources(type: Jar) {
|
||||||
|
from sourceSets.main.allSource
|
||||||
|
classifier = 'source'
|
||||||
|
}
|
||||||
|
artifacts {
|
||||||
|
compile jarSources
|
||||||
|
}
|
||||||
|
|
||||||
|
compileKotlin2Js.kotlinOptions.outputFile = "${buildDir}/kotlin2js/main/module.js"
|
||||||
|
compileTestKotlin2Js.kotlinOptions.outputFile = "${buildDir}/kotlin2js/test/module-tests.js"
|
||||||
|
|
||||||
|
if (project.findProperty("kotlin.js.useIrBackend")?.toBoolean() == true) {
|
||||||
|
compileKotlin2Js.kotlinOptions.freeCompilerArgs += ["-Xir-produce-klib-dir", "-Xir-only"]
|
||||||
|
compileTestKotlin2Js.kotlinOptions.freeCompilerArgs += ["-Xir-produce-js"]
|
||||||
|
}
|
||||||
+10
@@ -0,0 +1,10 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package project
|
||||||
|
|
||||||
|
class Main {
|
||||||
|
fun value(): String = "instant"
|
||||||
|
}
|
||||||
+13
@@ -0,0 +1,13 @@
|
|||||||
|
/*
|
||||||
|
* 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 project.Main
|
||||||
|
import kotlin.test.*
|
||||||
|
|
||||||
|
class MainTest {
|
||||||
|
@Test
|
||||||
|
fun mySimpleTest() {
|
||||||
|
assertEquals("instant", Main().value())
|
||||||
|
}
|
||||||
|
}
|
||||||
+4
-4
@@ -2,12 +2,12 @@ apply plugin: 'com.android.library'
|
|||||||
apply plugin: 'kotlin-android'
|
apply plugin: 'kotlin-android'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 29
|
compileSdkVersion 26
|
||||||
buildToolsVersion "29.0.2"
|
buildToolsVersion "28.0.3"
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 21
|
minSdkVersion 26
|
||||||
targetSdkVersion 29
|
targetSdkVersion 26
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -2,12 +2,12 @@ apply plugin: 'com.android.library'
|
|||||||
apply plugin: 'kotlin-android'
|
apply plugin: 'kotlin-android'
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 29
|
compileSdkVersion 26
|
||||||
buildToolsVersion "29.0.2"
|
buildToolsVersion "28.0.3"
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 21
|
minSdkVersion 26
|
||||||
targetSdkVersion 29
|
targetSdkVersion 26
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+5
-4
@@ -5,17 +5,18 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.compilerRunner
|
package org.jetbrains.kotlin.compilerRunner
|
||||||
|
|
||||||
import org.gradle.api.Task
|
|
||||||
import org.gradle.workers.IsolationMode
|
import org.gradle.workers.IsolationMode
|
||||||
import org.gradle.workers.WorkerExecutor
|
import org.gradle.workers.WorkerExecutor
|
||||||
import org.jetbrains.kotlin.gradle.logging.kotlinDebug
|
import org.jetbrains.kotlin.gradle.logging.kotlinDebug
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.GradleCompileTaskProvider
|
||||||
|
|
||||||
internal class GradleCompilerRunnerWithWorkers(
|
internal class GradleCompilerRunnerWithWorkers(
|
||||||
task: Task,
|
taskProvider: GradleCompileTaskProvider,
|
||||||
private val workersExecutor: WorkerExecutor
|
private val workersExecutor: WorkerExecutor
|
||||||
) : GradleCompilerRunner(task) {
|
) : GradleCompilerRunner(taskProvider) {
|
||||||
|
|
||||||
override fun runCompilerAsync(workArgs: GradleKotlinCompilerWorkArguments) {
|
override fun runCompilerAsync(workArgs: GradleKotlinCompilerWorkArguments) {
|
||||||
task.logger.kotlinDebug { "Starting Kotlin compiler work from task '${task.path}'" }
|
loggerProvider.kotlinDebug { "Starting Kotlin compiler work from task '${pathProvider}'" }
|
||||||
// todo: write tests with Workers enabled;
|
// todo: write tests with Workers enabled;
|
||||||
workersExecutor.submit(GradleKotlinCompilerWork::class.java) { config ->
|
workersExecutor.submit(GradleKotlinCompilerWork::class.java) { config ->
|
||||||
config.isolationMode = IsolationMode.NONE
|
config.isolationMode = IsolationMode.NONE
|
||||||
|
|||||||
+38
-21
@@ -6,8 +6,8 @@
|
|||||||
package org.jetbrains.kotlin.compilerRunner
|
package org.jetbrains.kotlin.compilerRunner
|
||||||
|
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.Task
|
|
||||||
import org.gradle.api.invocation.Gradle
|
import org.gradle.api.invocation.Gradle
|
||||||
|
import org.gradle.api.logging.Logger
|
||||||
import org.gradle.api.plugins.JavaPluginConvention
|
import org.gradle.api.plugins.JavaPluginConvention
|
||||||
import org.gradle.api.tasks.bundling.AbstractArchiveTask
|
import org.gradle.api.tasks.bundling.AbstractArchiveTask
|
||||||
import org.gradle.jvm.tasks.Jar
|
import org.gradle.jvm.tasks.Jar
|
||||||
@@ -24,11 +24,12 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinWithJavaTarget
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.isMain
|
import org.jetbrains.kotlin.gradle.plugin.mpp.isMain
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.ownModuleName
|
import org.jetbrains.kotlin.gradle.plugin.mpp.ownModuleName
|
||||||
import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildStatsService
|
import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildStatsService
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.GradleCompileTaskProvider
|
||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompileTaskData
|
import org.jetbrains.kotlin.gradle.tasks.KotlinCompileTaskData
|
||||||
import org.jetbrains.kotlin.gradle.tasks.locateTask
|
import org.jetbrains.kotlin.gradle.tasks.locateTask
|
||||||
import org.jetbrains.kotlin.gradle.utils.archivePathCompatible
|
import org.jetbrains.kotlin.gradle.utils.archivePathCompatible
|
||||||
import org.jetbrains.kotlin.gradle.utils.newTmpFile
|
import org.jetbrains.kotlin.gradle.utils.newTmpFile
|
||||||
import org.jetbrains.kotlin.gradle.utils.relativeToRoot
|
import org.jetbrains.kotlin.gradle.utils.relativeOrCanonical
|
||||||
import org.jetbrains.kotlin.incremental.IncrementalModuleEntry
|
import org.jetbrains.kotlin.incremental.IncrementalModuleEntry
|
||||||
import org.jetbrains.kotlin.incremental.IncrementalModuleInfo
|
import org.jetbrains.kotlin.incremental.IncrementalModuleInfo
|
||||||
import org.jetbrains.kotlin.statistics.metrics.BooleanMetrics
|
import org.jetbrains.kotlin.statistics.metrics.BooleanMetrics
|
||||||
@@ -50,9 +51,21 @@ const val COULD_NOT_CONNECT_TO_DAEMON_MESSAGE = "Could not connect to Kotlin com
|
|||||||
internal fun kotlinCompilerExecutionStrategy(): String =
|
internal fun kotlinCompilerExecutionStrategy(): String =
|
||||||
System.getProperty(KOTLIN_COMPILER_EXECUTION_STRATEGY_PROPERTY) ?: DAEMON_EXECUTION_STRATEGY
|
System.getProperty(KOTLIN_COMPILER_EXECUTION_STRATEGY_PROPERTY) ?: DAEMON_EXECUTION_STRATEGY
|
||||||
|
|
||||||
internal open class GradleCompilerRunner(protected val task: Task) {
|
/*
|
||||||
protected val project: Project
|
Using real taskProvider cause "field 'taskProvider' from type 'org.jetbrains.kotlin.compilerRunner.GradleCompilerRunner':
|
||||||
get() = task.project
|
value 'fixed(class org.jetbrains.kotlin.gradle.tasks.KotlinCompile_Decorated, task ':compileKotlin')'
|
||||||
|
is not assignable to 'org.gradle.api.tasks.TaskProvider'" exception
|
||||||
|
*/
|
||||||
|
internal open class GradleCompilerRunner(protected val taskProvider: GradleCompileTaskProvider) {
|
||||||
|
|
||||||
|
internal val pathProvider = taskProvider.path
|
||||||
|
internal val loggerProvider = taskProvider.logger
|
||||||
|
internal val buildDirProvider = taskProvider.buildDir
|
||||||
|
internal val projectDirProvider = taskProvider.projectDir
|
||||||
|
internal val projectRootDirProvider = taskProvider.rootDir
|
||||||
|
internal val sessionDirProvider = taskProvider.sessionsDir
|
||||||
|
internal val projectNameProvider = taskProvider.projectName
|
||||||
|
internal val incrementalModuleInfoProvider = taskProvider.buildModulesInfo
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compiler might be executed asynchronously. Do not do anything requiring end of compilation after this function is called.
|
* Compiler might be executed asynchronously. Do not do anything requiring end of compilation after this function is called.
|
||||||
@@ -107,7 +120,7 @@ internal open class GradleCompilerRunner(protected val task: Task) {
|
|||||||
environment: GradleCompilerEnvironment
|
environment: GradleCompilerEnvironment
|
||||||
) {
|
) {
|
||||||
if (compilerArgs.version) {
|
if (compilerArgs.version) {
|
||||||
task.logger.lifecycle(
|
loggerProvider.lifecycle(
|
||||||
"Kotlin version " + loadCompilerVersion(environment.compilerClasspath) +
|
"Kotlin version " + loadCompilerVersion(environment.compilerClasspath) +
|
||||||
" (JRE " + System.getProperty("java.runtime.version") + ")"
|
" (JRE " + System.getProperty("java.runtime.version") + ")"
|
||||||
)
|
)
|
||||||
@@ -128,9 +141,16 @@ internal open class GradleCompilerRunner(protected val task: Task) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val incrementalCompilationEnvironment = environment.incrementalCompilationEnvironment
|
val incrementalCompilationEnvironment = environment.incrementalCompilationEnvironment
|
||||||
val modulesInfo = incrementalCompilationEnvironment?.let { buildModulesInfo(project.gradle) }
|
val modulesInfo = incrementalCompilationEnvironment?.let { incrementalModuleInfoProvider }
|
||||||
val workArgs = GradleKotlinCompilerWorkArguments(
|
val workArgs = GradleKotlinCompilerWorkArguments(
|
||||||
projectFiles = ProjectFilesForCompilation(project),
|
projectFiles = ProjectFilesForCompilation(
|
||||||
|
loggerProvider,
|
||||||
|
projectDirProvider,
|
||||||
|
buildDirProvider,
|
||||||
|
projectNameProvider,
|
||||||
|
projectRootDirProvider,
|
||||||
|
sessionDirProvider
|
||||||
|
),
|
||||||
compilerFullClasspath = environment.compilerFullClasspath,
|
compilerFullClasspath = environment.compilerFullClasspath,
|
||||||
compilerClassName = compilerClassName,
|
compilerClassName = compilerClassName,
|
||||||
compilerArgs = argsArray,
|
compilerArgs = argsArray,
|
||||||
@@ -138,12 +158,12 @@ internal open class GradleCompilerRunner(protected val task: Task) {
|
|||||||
incrementalCompilationEnvironment = incrementalCompilationEnvironment,
|
incrementalCompilationEnvironment = incrementalCompilationEnvironment,
|
||||||
incrementalModuleInfo = modulesInfo,
|
incrementalModuleInfo = modulesInfo,
|
||||||
outputFiles = environment.outputFiles.toList(),
|
outputFiles = environment.outputFiles.toList(),
|
||||||
taskPath = task.path,
|
taskPath = pathProvider,
|
||||||
buildReportMode = environment.buildReportMode,
|
buildReportMode = environment.buildReportMode,
|
||||||
kotlinScriptExtensions = environment.kotlinScriptExtensions,
|
kotlinScriptExtensions = environment.kotlinScriptExtensions,
|
||||||
allWarningsAsErrors = compilerArgs.allWarningsAsErrors
|
allWarningsAsErrors = compilerArgs.allWarningsAsErrors
|
||||||
)
|
)
|
||||||
TaskLoggers.put(task.path, task.logger)
|
TaskLoggers.put(pathProvider, loggerProvider)
|
||||||
runCompilerAsync(workArgs)
|
runCompilerAsync(workArgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -221,7 +241,7 @@ internal open class GradleCompilerRunner(protected val task: Task) {
|
|||||||
} else {
|
} else {
|
||||||
if (target is KotlinWithJavaTarget<*>) {
|
if (target is KotlinWithJavaTarget<*>) {
|
||||||
val jar = project.tasks.getByName(target.artifactsTaskName) as Jar
|
val jar = project.tasks.getByName(target.artifactsTaskName) as Jar
|
||||||
jarToClassListFile[jar.archivePathCompatible.canonicalFile] = target.defaultArtifactClassesListFile
|
jarToClassListFile[jar.archivePathCompatible.canonicalFile] = target.defaultArtifactClassesListFile.get()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -261,11 +281,9 @@ internal open class GradleCompilerRunner(protected val task: Task) {
|
|||||||
private var clientIsAliveFlagFile: File? = null
|
private var clientIsAliveFlagFile: File? = null
|
||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
internal fun getOrCreateClientFlagFile(project: Project): File {
|
internal fun getOrCreateClientFlagFile(log: Logger, projectName: String): File {
|
||||||
val log = project.logger
|
|
||||||
if (clientIsAliveFlagFile == null || !clientIsAliveFlagFile!!.exists()) {
|
if (clientIsAliveFlagFile == null || !clientIsAliveFlagFile!!.exists()) {
|
||||||
val projectName = project.rootProject.name.normalizeForFlagFile()
|
clientIsAliveFlagFile = newTmpFile(prefix = "kotlin-compiler-in-${projectName}-", suffix = ".alive")
|
||||||
clientIsAliveFlagFile = newTmpFile(prefix = "kotlin-compiler-in-$projectName-", suffix = ".alive")
|
|
||||||
log.kotlinDebug { CREATED_CLIENT_FILE_PREFIX + clientIsAliveFlagFile!!.canonicalPath }
|
log.kotlinDebug { CREATED_CLIENT_FILE_PREFIX + clientIsAliveFlagFile!!.canonicalPath }
|
||||||
} else {
|
} else {
|
||||||
log.kotlinDebug { EXISTING_CLIENT_FILE_PREFIX + clientIsAliveFlagFile!!.canonicalPath }
|
log.kotlinDebug { EXISTING_CLIENT_FILE_PREFIX + clientIsAliveFlagFile!!.canonicalPath }
|
||||||
@@ -274,7 +292,7 @@ internal open class GradleCompilerRunner(protected val task: Task) {
|
|||||||
return clientIsAliveFlagFile!!
|
return clientIsAliveFlagFile!!
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun String.normalizeForFlagFile(): String {
|
internal fun String.normalizeForFlagFile(): String {
|
||||||
val validChars = ('a'..'z') + ('0'..'9') + "-_"
|
val validChars = ('a'..'z') + ('0'..'9') + "-_"
|
||||||
return filter { it in validChars }
|
return filter { it in validChars }
|
||||||
}
|
}
|
||||||
@@ -285,14 +303,13 @@ internal open class GradleCompilerRunner(protected val task: Task) {
|
|||||||
|
|
||||||
// session files are deleted at org.jetbrains.kotlin.gradle.plugin.KotlinGradleBuildServices.buildFinished
|
// session files are deleted at org.jetbrains.kotlin.gradle.plugin.KotlinGradleBuildServices.buildFinished
|
||||||
@Synchronized
|
@Synchronized
|
||||||
internal fun getOrCreateSessionFlagFile(project: Project): File {
|
internal fun getOrCreateSessionFlagFile(log: Logger, sessionsDir: File, projectRootDir: File): File {
|
||||||
val log = project.logger
|
|
||||||
if (sessionFlagFile == null || !sessionFlagFile!!.exists()) {
|
if (sessionFlagFile == null || !sessionFlagFile!!.exists()) {
|
||||||
val sessionFilesDir = sessionsDir(project).apply { mkdirs() }
|
val sessionFilesDir = sessionsDir.apply { mkdirs() }
|
||||||
sessionFlagFile = newTmpFile(prefix = "kotlin-compiler-", suffix = ".salive", directory = sessionFilesDir)
|
sessionFlagFile = newTmpFile(prefix = "kotlin-compiler-", suffix = ".salive", directory = sessionFilesDir)
|
||||||
log.kotlinDebug { CREATED_SESSION_FILE_PREFIX + sessionFlagFile!!.relativeToRoot(project) }
|
log.kotlinDebug { CREATED_SESSION_FILE_PREFIX + sessionFlagFile!!.relativeOrCanonical(projectRootDir) }
|
||||||
} else {
|
} else {
|
||||||
log.kotlinDebug { EXISTING_SESSION_FILE_PREFIX + sessionFlagFile!!.relativeToRoot(project) }
|
log.kotlinDebug { EXISTING_SESSION_FILE_PREFIX + sessionFlagFile!!.relativeOrCanonical(projectRootDir) }
|
||||||
}
|
}
|
||||||
|
|
||||||
return sessionFlagFile!!
|
return sessionFlagFile!!
|
||||||
|
|||||||
+7
-5
@@ -6,6 +6,7 @@
|
|||||||
package org.jetbrains.kotlin.compilerRunner
|
package org.jetbrains.kotlin.compilerRunner
|
||||||
|
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.logging.Logger
|
||||||
import org.jetbrains.kotlin.cli.common.ExitCode
|
import org.jetbrains.kotlin.cli.common.ExitCode
|
||||||
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
import org.jetbrains.kotlin.cli.common.messages.MessageCollector
|
||||||
import org.jetbrains.kotlin.config.Services
|
import org.jetbrains.kotlin.config.Services
|
||||||
@@ -35,11 +36,12 @@ internal class ProjectFilesForCompilation(
|
|||||||
val sessionFlagFile: File,
|
val sessionFlagFile: File,
|
||||||
val buildDir: File
|
val buildDir: File
|
||||||
) : Serializable {
|
) : Serializable {
|
||||||
constructor(project: Project) : this(
|
//TODO
|
||||||
projectRootFile = project.rootProject.projectDir,
|
constructor(logger: Logger, projectDir:File, buildDir: File, prjectName: String, projectRootDir: File, sessionDir: File) : this(
|
||||||
clientIsAliveFlagFile = GradleCompilerRunner.getOrCreateClientFlagFile(project),
|
projectRootFile = projectDir,
|
||||||
sessionFlagFile = GradleCompilerRunner.getOrCreateSessionFlagFile(project),
|
clientIsAliveFlagFile = GradleCompilerRunner.getOrCreateClientFlagFile(logger, prjectName),
|
||||||
buildDir = project.buildDir
|
sessionFlagFile = GradleCompilerRunner.getOrCreateSessionFlagFile(logger, sessionDir, projectRootDir),
|
||||||
|
buildDir = buildDir
|
||||||
)
|
)
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
|||||||
+22
-31
@@ -5,13 +5,15 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.gradle.internal
|
package org.jetbrains.kotlin.gradle.internal
|
||||||
|
|
||||||
import org.gradle.api.tasks.TaskProvider
|
import org.jetbrains.kotlin.cli.common.arguments.CommonCompilerArguments
|
||||||
import org.jetbrains.kotlin.cli.common.arguments.*
|
import org.jetbrains.kotlin.cli.common.arguments.CommonToolArguments
|
||||||
import org.jetbrains.kotlin.gradle.dsl.*
|
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.Coroutines
|
||||||
|
import org.jetbrains.kotlin.gradle.dsl.fillDefaultValues
|
||||||
import org.jetbrains.kotlin.gradle.logging.kotlinDebug
|
import org.jetbrains.kotlin.gradle.logging.kotlinDebug
|
||||||
import org.jetbrains.kotlin.gradle.tasks.*
|
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile
|
||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
import org.jetbrains.kotlin.gradle.tasks.KotlinCompileArgumentsProvider
|
||||||
import org.jetbrains.kotlin.gradle.utils.getValue
|
import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompilerArgumentsProvider
|
||||||
import org.jetbrains.kotlin.gradle.utils.toSortedPathsArray
|
import org.jetbrains.kotlin.gradle.utils.toSortedPathsArray
|
||||||
import org.jetbrains.kotlin.incremental.classpathAsList
|
import org.jetbrains.kotlin.incremental.classpathAsList
|
||||||
import org.jetbrains.kotlin.incremental.destinationAsFile
|
import org.jetbrains.kotlin.incremental.destinationAsFile
|
||||||
@@ -38,22 +40,20 @@ internal fun compilerArgumentsConfigurationFlags(defaultsOnly: Boolean, ignoreCl
|
|||||||
* but outside the tasks, so that this state & logic can be reused without referencing the task directly. */
|
* but outside the tasks, so that this state & logic can be reused without referencing the task directly. */
|
||||||
internal open class AbstractKotlinCompileArgumentsContributor<T : CommonCompilerArguments>(
|
internal open class AbstractKotlinCompileArgumentsContributor<T : CommonCompilerArguments>(
|
||||||
// Don't save this reference into a property! That would be hostile to Gradle instant execution
|
// Don't save this reference into a property! That would be hostile to Gradle instant execution
|
||||||
taskProvider: TaskProvider<out AbstractKotlinCompile<T>>
|
taskProvider: KotlinCompileArgumentsProvider<out AbstractKotlinCompile<T>>
|
||||||
) : CompilerArgumentsContributor<T> {
|
) : CompilerArgumentsContributor<T> {
|
||||||
private val coroutines by taskProvider.map { it.coroutines }
|
|
||||||
|
|
||||||
protected val logger by taskProvider.map { it.logger }
|
private val coroutines = taskProvider.coroutines
|
||||||
|
protected val logger = taskProvider.logger
|
||||||
private val isMultiplatform by taskProvider.map { it.isMultiplatform }
|
private val isMultiplatform = taskProvider.isMultiplatform
|
||||||
|
private val pluginClasspath = taskProvider.pluginClasspath
|
||||||
private val pluginClasspath by taskProvider.map { it.pluginClasspath }
|
private val pluginOptions = taskProvider.pluginOptions
|
||||||
private val pluginOptions by taskProvider.map { it.pluginOptions }
|
|
||||||
|
|
||||||
override fun contributeArguments(
|
override fun contributeArguments(
|
||||||
args: T,
|
args: T,
|
||||||
flags: Collection<CompilerArgumentsConfigurationFlag>
|
flags: Collection<CompilerArgumentsConfigurationFlag>
|
||||||
) {
|
) {
|
||||||
args.coroutinesState = when (coroutines) {
|
args.coroutinesState = when (coroutines.get()) {
|
||||||
Coroutines.ENABLE -> CommonCompilerArguments.ENABLE
|
Coroutines.ENABLE -> CommonCompilerArguments.ENABLE
|
||||||
Coroutines.WARN -> CommonCompilerArguments.WARN
|
Coroutines.WARN -> CommonCompilerArguments.WARN
|
||||||
Coroutines.ERROR -> CommonCompilerArguments.ERROR
|
Coroutines.ERROR -> CommonCompilerArguments.ERROR
|
||||||
@@ -79,23 +79,14 @@ internal open class AbstractKotlinCompileArgumentsContributor<T : CommonCompiler
|
|||||||
|
|
||||||
internal open class KotlinJvmCompilerArgumentsContributor(
|
internal open class KotlinJvmCompilerArgumentsContributor(
|
||||||
// Don't save this reference into a property! That would be hostile to Gradle instant execution. Only map it to the task properties.
|
// Don't save this reference into a property! That would be hostile to Gradle instant execution. Only map it to the task properties.
|
||||||
taskProvider: TaskProvider<out KotlinCompile>
|
taskProvider: KotlinJvmCompilerArgumentsProvider
|
||||||
) : AbstractKotlinCompileArgumentsContributor<K2JVMCompilerArguments>(taskProvider) {
|
) : AbstractKotlinCompileArgumentsContributor<K2JVMCompilerArguments>(taskProvider) {
|
||||||
|
|
||||||
private val moduleName by taskProvider.map { it.moduleName }
|
private val moduleName = taskProvider.moduleName
|
||||||
|
private val friendPaths = taskProvider.friendPaths
|
||||||
private val friendPaths by taskProvider.map { it.friendPaths }
|
private val compileClasspath = taskProvider.compileClasspath
|
||||||
|
private val destinationDir = taskProvider.destinationDir
|
||||||
private val compileClasspath by taskProvider.map { it.compileClasspath }
|
private val kotlinOptions = taskProvider.kotlinOptions
|
||||||
|
|
||||||
private val destinationDir by taskProvider.map { it.destinationDir }
|
|
||||||
|
|
||||||
private val kotlinOptions by taskProvider.map {
|
|
||||||
listOfNotNull(
|
|
||||||
it.parentKotlinOptionsImpl as KotlinJvmOptionsImpl?,
|
|
||||||
it.kotlinOptions as KotlinJvmOptionsImpl
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun contributeArguments(
|
override fun contributeArguments(
|
||||||
args: K2JVMCompilerArguments,
|
args: K2JVMCompilerArguments,
|
||||||
@@ -121,6 +112,6 @@ internal open class KotlinJvmCompilerArgumentsContributor(
|
|||||||
}
|
}
|
||||||
args.destinationAsFile = destinationDir
|
args.destinationAsFile = destinationDir
|
||||||
|
|
||||||
kotlinOptions.forEach { it.updateArguments(args) }
|
kotlinOptions.forEach { it?.updateArguments(args) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+10
-2
@@ -10,6 +10,7 @@ import com.android.build.gradle.api.AndroidSourceSet
|
|||||||
import com.android.build.gradle.api.BaseVariant
|
import com.android.build.gradle.api.BaseVariant
|
||||||
import com.android.build.gradle.api.SourceKind
|
import com.android.build.gradle.api.SourceKind
|
||||||
import com.intellij.openapi.util.SystemInfo
|
import com.intellij.openapi.util.SystemInfo
|
||||||
|
import com.intellij.util.lang.JavaVersion
|
||||||
import org.gradle.api.GradleException
|
import org.gradle.api.GradleException
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.artifacts.Configuration
|
import org.gradle.api.artifacts.Configuration
|
||||||
@@ -22,7 +23,6 @@ import org.gradle.api.tasks.*
|
|||||||
import org.gradle.api.tasks.compile.AbstractCompile
|
import org.gradle.api.tasks.compile.AbstractCompile
|
||||||
import org.gradle.api.tasks.compile.JavaCompile
|
import org.gradle.api.tasks.compile.JavaCompile
|
||||||
import org.gradle.process.CommandLineArgumentProvider
|
import org.gradle.process.CommandLineArgumentProvider
|
||||||
import org.gradle.tooling.provider.model.ToolingModelBuilder
|
|
||||||
import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry
|
import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry
|
||||||
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
|
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
|
||||||
import org.jetbrains.kotlin.gradle.internal.kapt.incremental.CLASS_STRUCTURE_ARTIFACT_TYPE
|
import org.jetbrains.kotlin.gradle.internal.kapt.incremental.CLASS_STRUCTURE_ARTIFACT_TYPE
|
||||||
@@ -34,6 +34,7 @@ import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
|||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompileTaskData
|
import org.jetbrains.kotlin.gradle.tasks.KotlinCompileTaskData
|
||||||
import org.jetbrains.kotlin.gradle.tasks.locateTask
|
import org.jetbrains.kotlin.gradle.tasks.locateTask
|
||||||
import org.jetbrains.kotlin.gradle.tasks.registerTask
|
import org.jetbrains.kotlin.gradle.tasks.registerTask
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.isConfigurationCacheAvailable
|
||||||
import java.io.ByteArrayOutputStream
|
import java.io.ByteArrayOutputStream
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.ObjectOutputStream
|
import java.io.ObjectOutputStream
|
||||||
@@ -474,7 +475,14 @@ class Kapt3GradleSubplugin @Inject internal constructor(private val registry: To
|
|||||||
val dslJavacOptions: Provider<Map<String, String>> = project.provider {
|
val dslJavacOptions: Provider<Map<String, String>> = project.provider {
|
||||||
kaptExtension.getJavacOptions().toMutableMap().also { result ->
|
kaptExtension.getJavacOptions().toMutableMap().also { result ->
|
||||||
if (javaCompile != null && "-source" !in result && "--source" !in result && "--release" !in result) {
|
if (javaCompile != null && "-source" !in result && "--source" !in result && "--release" !in result) {
|
||||||
val sourceOptionKey = if (SystemInfo.isJavaVersionAtLeast(12, 0, 0)) {
|
val atLeast12Java =
|
||||||
|
if (isConfigurationCacheAvailable(project.gradle)) {
|
||||||
|
val currentJavaVersion = JavaVersion.parse(project.providers.systemProperty("java.version").forUseAtConfigurationTime().get())
|
||||||
|
currentJavaVersion.feature >= 12
|
||||||
|
} else {
|
||||||
|
SystemInfo.isJavaVersionAtLeast(12, 0, 0)
|
||||||
|
}
|
||||||
|
val sourceOptionKey = if (atLeast12Java) {
|
||||||
"--source"
|
"--source"
|
||||||
} else {
|
} else {
|
||||||
"-source"
|
"-source"
|
||||||
|
|||||||
+6
-3
@@ -20,7 +20,7 @@ import org.gradle.api.artifacts.Configuration
|
|||||||
import org.gradle.api.file.FileCollection
|
import org.gradle.api.file.FileCollection
|
||||||
import org.gradle.api.tasks.*
|
import org.gradle.api.tasks.*
|
||||||
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
|
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
|
||||||
import org.jetbrains.kotlin.gradle.dsl.*
|
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptions
|
||||||
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptionsImpl
|
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptionsImpl
|
||||||
import org.jetbrains.kotlin.gradle.tasks.FilteringSourceRootsContainer
|
import org.jetbrains.kotlin.gradle.tasks.FilteringSourceRootsContainer
|
||||||
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
|
||||||
@@ -50,7 +50,7 @@ open class KaptGenerateStubsTask : KotlinCompile() {
|
|||||||
@get:Classpath
|
@get:Classpath
|
||||||
@get:InputFiles
|
@get:InputFiles
|
||||||
val kaptClasspath: FileCollection
|
val kaptClasspath: FileCollection
|
||||||
get() = project.files(kaptClasspathConfigurations)
|
get() = objects.fileCollection().from(kaptClasspathConfigurations)
|
||||||
|
|
||||||
@get:Internal
|
@get:Internal
|
||||||
internal lateinit var kaptClasspathConfigurations: List<Configuration>
|
internal lateinit var kaptClasspathConfigurations: List<Configuration>
|
||||||
@@ -69,6 +69,9 @@ open class KaptGenerateStubsTask : KotlinCompile() {
|
|||||||
error("KaptGenerateStubsTask.useModuleDetection setter should not be called!")
|
error("KaptGenerateStubsTask.useModuleDetection setter should not be called!")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@get:Input
|
||||||
|
val verbose = (project.hasProperty("kapt.verbose") && project.property("kapt.verbose").toString().toBoolean() == true)
|
||||||
|
|
||||||
override fun source(vararg sources: Any): SourceTask {
|
override fun source(vararg sources: Any): SourceTask {
|
||||||
return super.source(sourceRootsContainer.add(sources))
|
return super.source(sourceRootsContainer.add(sources))
|
||||||
}
|
}
|
||||||
@@ -95,7 +98,7 @@ open class KaptGenerateStubsTask : KotlinCompile() {
|
|||||||
val pluginOptionsWithKapt = pluginOptions.withWrappedKaptOptions(withApClasspath = kaptClasspath)
|
val pluginOptionsWithKapt = pluginOptions.withWrappedKaptOptions(withApClasspath = kaptClasspath)
|
||||||
args.pluginOptions = (pluginOptionsWithKapt.arguments + args.pluginOptions!!).toTypedArray()
|
args.pluginOptions = (pluginOptionsWithKapt.arguments + args.pluginOptions!!).toTypedArray()
|
||||||
|
|
||||||
args.verbose = project.hasProperty("kapt.verbose") && project.property("kapt.verbose").toString().toBoolean() == true
|
args.verbose = verbose
|
||||||
args.classpathAsList = this.compileClasspath.filter { it.exists() }.toList()
|
args.classpathAsList = this.compileClasspath.filter { it.exists() }.toList()
|
||||||
args.destinationAsFile = this.destinationDir
|
args.destinationAsFile = this.destinationDir
|
||||||
}
|
}
|
||||||
|
|||||||
+35
-5
@@ -1,6 +1,5 @@
|
|||||||
package org.jetbrains.kotlin.gradle.internal
|
package org.jetbrains.kotlin.gradle.internal
|
||||||
|
|
||||||
import com.intellij.openapi.util.io.FileUtil
|
|
||||||
import org.gradle.api.artifacts.Configuration
|
import org.gradle.api.artifacts.Configuration
|
||||||
import org.gradle.api.file.FileCollection
|
import org.gradle.api.file.FileCollection
|
||||||
import org.gradle.api.internal.ConventionTask
|
import org.gradle.api.internal.ConventionTask
|
||||||
@@ -28,7 +27,7 @@ abstract class KaptTask : ConventionTask(), TaskWithLocalState {
|
|||||||
outputs.cacheIf(reason) { useBuildCache }
|
outputs.cacheIf(reason) { useBuildCache }
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun localStateDirectories(): FileCollection = project.files()
|
override fun localStateDirectories(): FileCollection = objects.fileCollection()
|
||||||
|
|
||||||
@get:Internal
|
@get:Internal
|
||||||
@field:Transient
|
@field:Transient
|
||||||
@@ -37,10 +36,13 @@ abstract class KaptTask : ConventionTask(), TaskWithLocalState {
|
|||||||
@get:Internal
|
@get:Internal
|
||||||
internal lateinit var stubsDir: File
|
internal lateinit var stubsDir: File
|
||||||
|
|
||||||
|
@get:Internal
|
||||||
|
internal val objects = project.objects
|
||||||
|
|
||||||
@get:Classpath
|
@get:Classpath
|
||||||
@get:InputFiles
|
@get:InputFiles
|
||||||
val kaptClasspath: FileCollection
|
val kaptClasspath: FileCollection
|
||||||
get() = project.files(kaptClasspathConfigurations)
|
get() = objects.fileCollection().from(kaptClasspathConfigurations)
|
||||||
|
|
||||||
@get:Classpath
|
@get:Classpath
|
||||||
@get:InputFiles
|
@get:InputFiles
|
||||||
@@ -137,8 +139,36 @@ abstract class KaptTask : ConventionTask(), TaskWithLocalState {
|
|||||||
|
|
||||||
private fun isRootAllowed(file: File): Boolean =
|
private fun isRootAllowed(file: File): Boolean =
|
||||||
file.exists() &&
|
file.exists() &&
|
||||||
!FileUtil.isAncestor(destinationDir, file, /* strict = */ false) &&
|
!isAncestor(destinationDir, file) &&
|
||||||
!FileUtil.isAncestor(classesDir, file, /* strict = */ false)
|
!isAncestor(classesDir, file)
|
||||||
|
|
||||||
|
//Have to avoid using FileUtil because it is required system property reading that is not allowed for configuration cache
|
||||||
|
private fun isAncestor(dir: File, file: File): Boolean {
|
||||||
|
val path = file.canonicalPath
|
||||||
|
val prefix = dir.canonicalPath
|
||||||
|
val pathLength = path.length
|
||||||
|
val prefixLength = prefix.length
|
||||||
|
//TODO
|
||||||
|
val caseSensitive = true
|
||||||
|
return if (prefixLength == 0) {
|
||||||
|
true
|
||||||
|
} else if (prefixLength > pathLength) {
|
||||||
|
false
|
||||||
|
} else if (!path.regionMatches(0, prefix, 0, prefixLength, ignoreCase = !caseSensitive)) {
|
||||||
|
return false
|
||||||
|
} else if (pathLength == prefixLength) {
|
||||||
|
return true
|
||||||
|
} else {
|
||||||
|
val lastPrefixChar: Char = prefix.get(prefixLength - 1)
|
||||||
|
var slashOrSeparatorIdx = prefixLength
|
||||||
|
if (lastPrefixChar == '/' || lastPrefixChar == File.separatorChar) {
|
||||||
|
slashOrSeparatorIdx = prefixLength - 1
|
||||||
|
}
|
||||||
|
val next1 = path[slashOrSeparatorIdx]
|
||||||
|
return !(next1 != '/' && next1 != File.separatorChar)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun FileCollection?.orEmpty(): FileCollection =
|
private fun FileCollection?.orEmpty(): FileCollection =
|
||||||
this ?: project.files()
|
this ?: project.files()
|
||||||
|
|||||||
+8
-3
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.gradle.logging.GradleKotlinLogger
|
|||||||
import org.jetbrains.kotlin.gradle.logging.GradlePrintingMessageCollector
|
import org.jetbrains.kotlin.gradle.logging.GradlePrintingMessageCollector
|
||||||
import org.jetbrains.kotlin.gradle.plugin.PLUGIN_CLASSPATH_CONFIGURATION_NAME
|
import org.jetbrains.kotlin.gradle.plugin.PLUGIN_CLASSPATH_CONFIGURATION_NAME
|
||||||
import org.jetbrains.kotlin.gradle.tasks.CompilerPluginOptions
|
import org.jetbrains.kotlin.gradle.tasks.CompilerPluginOptions
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.GradleCompileTaskProvider
|
||||||
import org.jetbrains.kotlin.gradle.utils.getValue
|
import org.jetbrains.kotlin.gradle.utils.getValue
|
||||||
import org.jetbrains.kotlin.gradle.utils.optionalProvider
|
import org.jetbrains.kotlin.gradle.utils.optionalProvider
|
||||||
import org.jetbrains.kotlin.gradle.utils.toSortedPathsArray
|
import org.jetbrains.kotlin.gradle.utils.toSortedPathsArray
|
||||||
@@ -43,6 +44,9 @@ open class KaptWithKotlincTask : KaptTask(), CompilerArgumentAwareWithInput<K2JV
|
|||||||
val pluginClasspath: FileCollection
|
val pluginClasspath: FileCollection
|
||||||
get() = project.configurations.getByName(PLUGIN_CLASSPATH_CONFIGURATION_NAME)
|
get() = project.configurations.getByName(PLUGIN_CLASSPATH_CONFIGURATION_NAME)
|
||||||
|
|
||||||
|
@get:Internal
|
||||||
|
val taskProvider = GradleCompileTaskProvider(this)
|
||||||
|
|
||||||
override fun createCompilerArgs(): K2JVMCompilerArguments = K2JVMCompilerArguments()
|
override fun createCompilerArgs(): K2JVMCompilerArguments = K2JVMCompilerArguments()
|
||||||
|
|
||||||
private val compileKotlinArgumentsContributor by project.provider {
|
private val compileKotlinArgumentsContributor by project.provider {
|
||||||
@@ -50,8 +54,9 @@ open class KaptWithKotlincTask : KaptTask(), CompilerArgumentAwareWithInput<K2JV
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun setupCompilerArgs(args: K2JVMCompilerArguments, defaultsOnly: Boolean, ignoreClasspathResolutionErrors: Boolean) {
|
override fun setupCompilerArgs(args: K2JVMCompilerArguments, defaultsOnly: Boolean, ignoreClasspathResolutionErrors: Boolean) {
|
||||||
compileKotlinArgumentsContributor.contributeArguments(args, compilerArgumentsConfigurationFlags(
|
compileKotlinArgumentsContributor.contributeArguments(
|
||||||
defaultsOnly,
|
args, compilerArgumentsConfigurationFlags(
|
||||||
|
defaultsOnly,
|
||||||
ignoreClasspathResolutionErrors
|
ignoreClasspathResolutionErrors
|
||||||
))
|
))
|
||||||
|
|
||||||
@@ -106,7 +111,7 @@ open class KaptWithKotlincTask : KaptTask(), CompilerArgumentAwareWithInput<K2JV
|
|||||||
throw GradleException("Could not find tools.jar in system classpath, which is required for kapt to work")
|
throw GradleException("Could not find tools.jar in system classpath, which is required for kapt to work")
|
||||||
}
|
}
|
||||||
|
|
||||||
val compilerRunner = GradleCompilerRunner(this)
|
val compilerRunner = GradleCompilerRunner(taskProvider)
|
||||||
compilerRunner.runJvmCompilerAsync(
|
compilerRunner.runJvmCompilerAsync(
|
||||||
sourcesToCompile = emptyList(),
|
sourcesToCompile = emptyList(),
|
||||||
commonSources = emptyList(),
|
commonSources = emptyList(),
|
||||||
|
|||||||
+29
-8
@@ -11,13 +11,12 @@ import org.gradle.workers.IsolationMode
|
|||||||
import org.gradle.workers.WorkerExecutor
|
import org.gradle.workers.WorkerExecutor
|
||||||
import org.jetbrains.kotlin.gradle.internal.Kapt3GradleSubplugin.Companion.KAPT_WORKER_DEPENDENCIES_CONFIGURATION_NAME
|
import org.jetbrains.kotlin.gradle.internal.Kapt3GradleSubplugin.Companion.KAPT_WORKER_DEPENDENCIES_CONFIGURATION_NAME
|
||||||
import org.jetbrains.kotlin.gradle.internal.kapt.incremental.KaptIncrementalChanges
|
import org.jetbrains.kotlin.gradle.internal.kapt.incremental.KaptIncrementalChanges
|
||||||
import org.jetbrains.kotlin.gradle.plugin.CompositeSubpluginOption
|
|
||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinAndroidPluginWrapper
|
import org.jetbrains.kotlin.gradle.plugin.KotlinAndroidPluginWrapper
|
||||||
import org.jetbrains.kotlin.gradle.plugin.SubpluginOption
|
|
||||||
import org.jetbrains.kotlin.gradle.tasks.CompilerPluginOptions
|
import org.jetbrains.kotlin.gradle.tasks.CompilerPluginOptions
|
||||||
import org.jetbrains.kotlin.gradle.tasks.findKotlinStdlibClasspath
|
import org.jetbrains.kotlin.gradle.tasks.findKotlinStdlibClasspath
|
||||||
import org.jetbrains.kotlin.gradle.tasks.findToolsJar
|
import org.jetbrains.kotlin.gradle.tasks.findToolsJar
|
||||||
import org.jetbrains.kotlin.gradle.utils.getValue
|
import org.jetbrains.kotlin.gradle.utils.getValue
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast
|
||||||
import org.jetbrains.kotlin.utils.PathUtil
|
import org.jetbrains.kotlin.utils.PathUtil
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
@@ -29,7 +28,7 @@ open class KaptWithoutKotlincTask @Inject constructor(private val workerExecutor
|
|||||||
@get:InputFiles
|
@get:InputFiles
|
||||||
@get:Classpath
|
@get:Classpath
|
||||||
@Suppress("unused")
|
@Suppress("unused")
|
||||||
val kaptJars: Collection<File> by project.provider {
|
val kaptJars: Collection<File> by lazy {
|
||||||
project.configurations.getByName(KAPT_WORKER_DEPENDENCIES_CONFIGURATION_NAME).resolve()
|
project.configurations.getByName(KAPT_WORKER_DEPENDENCIES_CONFIGURATION_NAME).resolve()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,6 +47,18 @@ open class KaptWithoutKotlincTask @Inject constructor(private val workerExecutor
|
|||||||
@get:Input
|
@get:Input
|
||||||
lateinit var javacOptions: Map<String, String>
|
lateinit var javacOptions: Map<String, String>
|
||||||
|
|
||||||
|
@get:Input
|
||||||
|
internal val kotlinAndroidPluginWrapperPluginDoesNotExist = project.plugins.none { it is KotlinAndroidPluginWrapper }
|
||||||
|
|
||||||
|
@get:Input
|
||||||
|
internal val kotlinStdlibClasspath = findKotlinStdlibClasspath(project)
|
||||||
|
|
||||||
|
@get:Internal
|
||||||
|
internal val projectDir = project.projectDir
|
||||||
|
|
||||||
|
@get:Internal
|
||||||
|
internal val providers = project.providers
|
||||||
|
|
||||||
private fun getAnnotationProcessorOptions(): Map<String, String> {
|
private fun getAnnotationProcessorOptions(): Map<String, String> {
|
||||||
val options = processorOptions.subpluginOptionsByPluginId[Kapt3GradleSubplugin.KAPT_SUBPLUGIN_ID] ?: return emptyMap()
|
val options = processorOptions.subpluginOptionsByPluginId[Kapt3GradleSubplugin.KAPT_SUBPLUGIN_ID] ?: return emptyMap()
|
||||||
|
|
||||||
@@ -70,7 +81,7 @@ open class KaptWithoutKotlincTask @Inject constructor(private val workerExecutor
|
|||||||
}
|
}
|
||||||
|
|
||||||
val compileClasspath = classpath.files.toMutableList()
|
val compileClasspath = classpath.files.toMutableList()
|
||||||
if (project.plugins.none { it is KotlinAndroidPluginWrapper }) {
|
if (kotlinAndroidPluginWrapperPluginDoesNotExist) {
|
||||||
compileClasspath.addAll(0, PathUtil.getJdkClassesRootsFromCurrentJre())
|
compileClasspath.addAll(0, PathUtil.getJdkClassesRootsFromCurrentJre())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -82,7 +93,7 @@ open class KaptWithoutKotlincTask @Inject constructor(private val workerExecutor
|
|||||||
}
|
}
|
||||||
|
|
||||||
val optionsForWorker = KaptOptionsForWorker(
|
val optionsForWorker = KaptOptionsForWorker(
|
||||||
project.projectDir,
|
projectDir,
|
||||||
compileClasspath,
|
compileClasspath,
|
||||||
javaSourceRoots.toList(),
|
javaSourceRoots.toList(),
|
||||||
|
|
||||||
@@ -108,25 +119,35 @@ open class KaptWithoutKotlincTask @Inject constructor(private val workerExecutor
|
|||||||
if (annotationProcessorFqNames.isEmpty() && kaptClasspath.isEmpty())
|
if (annotationProcessorFqNames.isEmpty() && kaptClasspath.isEmpty())
|
||||||
return
|
return
|
||||||
|
|
||||||
val kaptClasspath = kaptJars + findKotlinStdlibClasspath(project)
|
val kaptClasspath = kaptJars + kotlinStdlibClasspath
|
||||||
|
|
||||||
workerExecutor.submit(KaptExecution::class.java) { config ->
|
workerExecutor.submit(KaptExecution::class.java) { config ->
|
||||||
val isolationModeStr = project.findProperty("kapt.workers.isolation") as String? ?: "none"
|
//TODO for gradle < 6.5
|
||||||
|
val isolationModeStr = getValue("kapt.workers.isolation") ?: "none"
|
||||||
config.isolationMode = when (isolationModeStr.toLowerCase()) {
|
config.isolationMode = when (isolationModeStr.toLowerCase()) {
|
||||||
"process" -> IsolationMode.PROCESS
|
"process" -> IsolationMode.PROCESS
|
||||||
"none" -> IsolationMode.NONE
|
"none" -> IsolationMode.NONE
|
||||||
else -> IsolationMode.NONE
|
else -> IsolationMode.NONE
|
||||||
}
|
}
|
||||||
config.params(optionsForWorker, findToolsJar()?.toURI()?.toURL()?.toString().orEmpty(), kaptClasspath)
|
config.params(optionsForWorker, findToolsJar()?.toURI()?.toURL()?.toString().orEmpty(), kaptClasspath)
|
||||||
if (project.findProperty("kapt.workers.log.classloading") == "true") {
|
if (getValue("kapt.workers.log.classloading") == "true") {
|
||||||
// for tests
|
// for tests
|
||||||
config.forkOptions.jvmArgs("-verbose:class")
|
config.forkOptions.jvmArgs("-verbose:class")
|
||||||
}
|
}
|
||||||
logger.info("Kapt worker classpath: ${config.classpath}")
|
logger.info("Kapt worker classpath: ${config.classpath}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal fun getValue(propertyName: String): String? =
|
||||||
|
if (isGradleVersionAtLeast(6, 5)) {
|
||||||
|
providers.systemProperty(propertyName).forUseAtConfigurationTime().orNull
|
||||||
|
} else {
|
||||||
|
project.findProperty(propertyName) as String?
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private class KaptExecution @Inject constructor(
|
private class KaptExecution @Inject constructor(
|
||||||
val optionsForWorker: KaptOptionsForWorker,
|
val optionsForWorker: KaptOptionsForWorker,
|
||||||
val toolsJarURLSpec: String,
|
val toolsJarURLSpec: String,
|
||||||
|
|||||||
+1
-1
@@ -144,7 +144,7 @@ class KotlinModelBuilder(private val kotlinPluginVersion: String, private val an
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun AbstractKotlinCompile<*>.createExperimentalFeatures(): ExperimentalFeatures {
|
private fun AbstractKotlinCompile<*>.createExperimentalFeatures(): ExperimentalFeatures {
|
||||||
return ExperimentalFeaturesImpl(coroutinesStr)
|
return ExperimentalFeaturesImpl(coroutinesStr.get())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.gradle.plugin
|
||||||
|
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.build.event.BuildEventsListenerRegistry
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.isConfigurationCacheAvailable
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
open class BuildEventsListenerRegistryHolder @Inject constructor(val listenerRegistry: BuildEventsListenerRegistry?) {
|
||||||
|
companion object {
|
||||||
|
fun getInstance(project: Project) = run {
|
||||||
|
if (isConfigurationCacheAvailable(project.gradle)) {
|
||||||
|
project.objects.newInstance(BuildEventsListenerRegistryHolder::class.java)
|
||||||
|
} else {
|
||||||
|
BuildEventsListenerRegistryHolder(null)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+21
@@ -0,0 +1,21 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.gradle.plugin
|
||||||
|
|
||||||
|
import org.gradle.tooling.events.FinishEvent
|
||||||
|
import org.gradle.tooling.events.OperationCompletionListener
|
||||||
|
|
||||||
|
//Available since Gradle 6.1
|
||||||
|
class KotlinGradleBuildListener(
|
||||||
|
// val gradle: Gradle,
|
||||||
|
val services: KotlinGradleFinishBuildHandler
|
||||||
|
) : OperationCompletionListener {
|
||||||
|
|
||||||
|
override fun onFinish(event: FinishEvent) {
|
||||||
|
// services.buildFinished(gradle)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+46
-61
@@ -10,20 +10,18 @@ import org.gradle.BuildResult
|
|||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.invocation.Gradle
|
import org.gradle.api.invocation.Gradle
|
||||||
import org.gradle.api.logging.Logging
|
import org.gradle.api.logging.Logging
|
||||||
import org.jetbrains.kotlin.compilerRunner.DELETED_SESSION_FILE_PREFIX
|
|
||||||
import org.jetbrains.kotlin.compilerRunner.GradleCompilerRunner
|
|
||||||
import org.jetbrains.kotlin.gradle.logging.kotlinDebug
|
import org.jetbrains.kotlin.gradle.logging.kotlinDebug
|
||||||
import org.jetbrains.kotlin.gradle.plugin.internal.state.TaskExecutionResults
|
import org.jetbrains.kotlin.gradle.plugin.internal.state.TaskExecutionResults
|
||||||
import org.jetbrains.kotlin.gradle.plugin.internal.state.TaskLoggers
|
import org.jetbrains.kotlin.gradle.plugin.internal.state.TaskLoggers
|
||||||
import org.jetbrains.kotlin.gradle.report.configureBuildReporter
|
import org.jetbrains.kotlin.gradle.report.configureBuildReporter
|
||||||
import org.jetbrains.kotlin.gradle.utils.relativeToRoot
|
import org.jetbrains.kotlin.gradle.utils.isConfigurationCacheAvailable
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.sumByLong
|
|
||||||
import java.lang.management.ManagementFactory
|
|
||||||
import kotlin.math.max
|
|
||||||
|
|
||||||
|
|
||||||
|
//Support Gradle 6 and less. Move to
|
||||||
internal class KotlinGradleBuildServices private constructor(
|
internal class KotlinGradleBuildServices private constructor(
|
||||||
private val gradle: Gradle
|
private val gradle: Gradle
|
||||||
) : BuildAdapter() {
|
) : BuildAdapter() {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val CLASS_NAME = KotlinGradleBuildServices::class.java.simpleName
|
private val CLASS_NAME = KotlinGradleBuildServices::class.java.simpleName
|
||||||
const val FORCE_SYSTEM_GC_MESSAGE = "Forcing System.gc()"
|
const val FORCE_SYSTEM_GC_MESSAGE = "Forcing System.gc()"
|
||||||
@@ -34,36 +32,69 @@ internal class KotlinGradleBuildServices private constructor(
|
|||||||
val ALREADY_INITIALIZED_MESSAGE = "$CLASS_NAME is already initialized"
|
val ALREADY_INITIALIZED_MESSAGE = "$CLASS_NAME is already initialized"
|
||||||
|
|
||||||
@field:Volatile
|
@field:Volatile
|
||||||
private var instance: KotlinGradleBuildServices? = null
|
internal var instance: KotlinGradleBuildServices? = null
|
||||||
|
|
||||||
|
// @JvmStatic
|
||||||
|
// @Synchronized
|
||||||
|
// fun getInstance(gradle: Gradle): KotlinGradleBuildServices {
|
||||||
|
// val log = Logging.getLogger(KotlinGradleBuildServices::class.java)
|
||||||
|
//
|
||||||
|
// if (instance != null) {
|
||||||
|
// log.kotlinDebug(ALREADY_INITIALIZED_MESSAGE)
|
||||||
|
// return instance!!
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// val services = KotlinGradleBuildServices(gradle)
|
||||||
|
// instance = services
|
||||||
|
// if (!isGradleVersionAtLeast(6,1)) {
|
||||||
|
// gradle.addBuildListener(services)
|
||||||
|
// log.kotlinDebug(INIT_MESSAGE)
|
||||||
|
// } else {
|
||||||
|
// BuildEventsListenerRegistry.
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// services.buildStarted()
|
||||||
|
// return services
|
||||||
|
// }
|
||||||
|
|
||||||
|
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@Synchronized
|
@Synchronized
|
||||||
fun getInstance(gradle: Gradle): KotlinGradleBuildServices {
|
fun getInstance(project: Project, listenerRegistryHolder: BuildEventsListenerRegistryHolder): KotlinGradleBuildServices {
|
||||||
val log = Logging.getLogger(KotlinGradleBuildServices::class.java)
|
val log = Logging.getLogger(KotlinGradleBuildServices::class.java)
|
||||||
|
val kotlinGradleListenerProvider: org.gradle.api.provider.Provider<KotlinGradleBuildListener> = project.provider {
|
||||||
|
KotlinGradleBuildListener(KotlinGradleFinishBuildHandler())
|
||||||
|
}
|
||||||
|
|
||||||
if (instance != null) {
|
if (instance != null) {
|
||||||
log.kotlinDebug(ALREADY_INITIALIZED_MESSAGE)
|
log.kotlinDebug(ALREADY_INITIALIZED_MESSAGE)
|
||||||
return instance!!
|
return instance!!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
val gradle = project.gradle
|
||||||
val services = KotlinGradleBuildServices(gradle)
|
val services = KotlinGradleBuildServices(gradle)
|
||||||
gradle.addBuildListener(services)
|
if (isConfigurationCacheAvailable(gradle)) {
|
||||||
instance = services
|
listenerRegistryHolder.listenerRegistry!!.onTaskCompletion(kotlinGradleListenerProvider)
|
||||||
log.kotlinDebug(INIT_MESSAGE)
|
} else {
|
||||||
|
gradle.addBuildListener(services)
|
||||||
|
instance = services
|
||||||
|
log.kotlinDebug(INIT_MESSAGE)
|
||||||
|
}
|
||||||
|
|
||||||
services.buildStarted()
|
services.buildStarted()
|
||||||
return services
|
return services
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private val log = Logging.getLogger(this.javaClass)
|
private val log = Logging.getLogger(this.javaClass)
|
||||||
private var startMemory: Long? = null
|
private var buildHandler: KotlinGradleFinishBuildHandler? = null
|
||||||
private val shouldReportMemoryUsage = System.getProperty(SHOULD_REPORT_MEMORY_USAGE_PROPERTY) != null
|
|
||||||
|
|
||||||
// There is function with the same name in BuildAdapter,
|
// There is function with the same name in BuildAdapter,
|
||||||
// but it is called before any plugin can attach build listener
|
// but it is called before any plugin can attach build listener
|
||||||
fun buildStarted() {
|
fun buildStarted() {
|
||||||
startMemory = getUsedMemoryKb()
|
buildHandler = KotlinGradleFinishBuildHandler()
|
||||||
|
buildHandler!!.buildStart()
|
||||||
|
|
||||||
TaskLoggers.clear()
|
TaskLoggers.clear()
|
||||||
TaskExecutionResults.clear()
|
TaskExecutionResults.clear()
|
||||||
@@ -72,57 +103,11 @@ internal class KotlinGradleBuildServices private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun buildFinished(result: BuildResult) {
|
override fun buildFinished(result: BuildResult) {
|
||||||
TaskLoggers.clear()
|
buildHandler!!.buildFinished(result.gradle!!)
|
||||||
TaskExecutionResults.clear()
|
|
||||||
|
|
||||||
val gradle = result.gradle!!
|
|
||||||
GradleCompilerRunner.clearBuildModulesInfo()
|
|
||||||
|
|
||||||
val rootProject = gradle.rootProject
|
|
||||||
val sessionsDir = GradleCompilerRunner.sessionsDir(rootProject)
|
|
||||||
if (sessionsDir.exists()) {
|
|
||||||
val sessionFiles = sessionsDir.listFiles()
|
|
||||||
|
|
||||||
// it is expected that only one session file per build exists
|
|
||||||
// afaik is is not possible to run multiple gradle builds in one project since gradle locks some dirs
|
|
||||||
if (sessionFiles.size > 1) {
|
|
||||||
log.warn("w: Detected multiple Kotlin daemon sessions at ${sessionsDir.relativeToRoot(rootProject)}")
|
|
||||||
}
|
|
||||||
for (file in sessionFiles) {
|
|
||||||
file.delete()
|
|
||||||
log.kotlinDebug { DELETED_SESSION_FILE_PREFIX + file.relativeToRoot(rootProject) }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shouldReportMemoryUsage) {
|
|
||||||
val startMem = startMemory!!
|
|
||||||
val endMem = getUsedMemoryKb()!!
|
|
||||||
|
|
||||||
// the value reported here is not necessarily a leak, since it is calculated before collecting the plugin classes
|
|
||||||
// but on subsequent runs in the daemon it should be rather small, then the classes are actually reused by the daemon (see above)
|
|
||||||
log.lifecycle("[KOTLIN][PERF] Used memory after build: $endMem kb (difference since build start: ${"%+d".format(endMem - startMem)} kb)")
|
|
||||||
}
|
|
||||||
|
|
||||||
gradle.removeListener(this)
|
|
||||||
instance = null
|
instance = null
|
||||||
log.kotlinDebug(DISPOSE_MESSAGE)
|
log.kotlinDebug(DISPOSE_MESSAGE)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getUsedMemoryKb(): Long? {
|
|
||||||
if (!shouldReportMemoryUsage) return null
|
|
||||||
|
|
||||||
log.lifecycle(FORCE_SYSTEM_GC_MESSAGE)
|
|
||||||
val gcCountBefore = getGcCount()
|
|
||||||
System.gc()
|
|
||||||
while (getGcCount() == gcCountBefore) {
|
|
||||||
}
|
|
||||||
|
|
||||||
val rt = Runtime.getRuntime()
|
|
||||||
return (rt.totalMemory() - rt.freeMemory()) / 1024
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getGcCount(): Long =
|
|
||||||
ManagementFactory.getGarbageCollectorMXBeans().sumByLong { max(0, it.collectionCount) }
|
|
||||||
|
|
||||||
private val multipleProjectsHolder = KotlinPluginInMultipleProjectsHolder(
|
private val multipleProjectsHolder = KotlinPluginInMultipleProjectsHolder(
|
||||||
trackPluginVersionsSeparately = true
|
trackPluginVersionsSeparately = true
|
||||||
|
|||||||
+81
@@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.gradle.plugin
|
||||||
|
|
||||||
|
import org.gradle.api.invocation.Gradle
|
||||||
|
import org.gradle.api.logging.Logging
|
||||||
|
import org.jetbrains.kotlin.compilerRunner.DELETED_SESSION_FILE_PREFIX
|
||||||
|
import org.jetbrains.kotlin.compilerRunner.GradleCompilerRunner
|
||||||
|
import org.jetbrains.kotlin.gradle.logging.kotlinDebug
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.internal.state.TaskExecutionResults
|
||||||
|
import org.jetbrains.kotlin.gradle.plugin.internal.state.TaskLoggers
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.relativeToRoot
|
||||||
|
import org.jetbrains.kotlin.utils.addToStdlib.sumByLong
|
||||||
|
import java.lang.management.ManagementFactory
|
||||||
|
import kotlin.math.max
|
||||||
|
|
||||||
|
// move to KotlinGradleBuildListener when min supported version is 6.1
|
||||||
|
class KotlinGradleFinishBuildHandler {
|
||||||
|
|
||||||
|
private val log = Logging.getLogger(this.javaClass)
|
||||||
|
private var startMemory: Long? = null
|
||||||
|
private val shouldReportMemoryUsage = System.getProperty(KotlinGradleBuildServices.SHOULD_REPORT_MEMORY_USAGE_PROPERTY) != null
|
||||||
|
|
||||||
|
fun buildStart() {
|
||||||
|
startMemory = getUsedMemoryKb()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun buildFinished(gradle: Gradle) {
|
||||||
|
TaskLoggers.clear()
|
||||||
|
TaskExecutionResults.clear()
|
||||||
|
|
||||||
|
GradleCompilerRunner.clearBuildModulesInfo()
|
||||||
|
|
||||||
|
val rootProject = gradle.rootProject
|
||||||
|
val sessionsDir = GradleCompilerRunner.sessionsDir(rootProject)
|
||||||
|
if (sessionsDir.exists()) {
|
||||||
|
val sessionFiles = sessionsDir.listFiles()
|
||||||
|
|
||||||
|
// it is expected that only one session file per build exists
|
||||||
|
// afaik is is not possible to run multiple gradle builds in one project since gradle locks some dirs
|
||||||
|
if (sessionFiles.size > 1) {
|
||||||
|
log.warn("w: Detected multiple Kotlin daemon sessions at ${sessionsDir.relativeToRoot(rootProject)}")
|
||||||
|
}
|
||||||
|
for (file in sessionFiles) {
|
||||||
|
file.delete()
|
||||||
|
log.kotlinDebug { DELETED_SESSION_FILE_PREFIX + file.relativeToRoot(rootProject) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldReportMemoryUsage) {
|
||||||
|
val startMem = startMemory!!
|
||||||
|
val endMem = getUsedMemoryKb()!!
|
||||||
|
|
||||||
|
// the value reported here is not necessarily a leak, since it is calculated before collecting the plugin classes
|
||||||
|
// but on subsequent runs in the daemon it should be rather small, then the classes are actually reused by the daemon (see above)
|
||||||
|
log.lifecycle("[KOTLIN][PERF] Used memory after build: $endMem kb (difference since build start: ${"%+d".format(endMem - startMem)} kb)")
|
||||||
|
}
|
||||||
|
|
||||||
|
gradle.removeListener(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun getUsedMemoryKb(): Long? {
|
||||||
|
if (!shouldReportMemoryUsage) return null
|
||||||
|
|
||||||
|
log.lifecycle(KotlinGradleBuildServices.FORCE_SYSTEM_GC_MESSAGE)
|
||||||
|
val gcCountBefore = getGcCount()
|
||||||
|
System.gc()
|
||||||
|
while (getGcCount() == gcCountBefore) {
|
||||||
|
}
|
||||||
|
|
||||||
|
val rt = Runtime.getRuntime()
|
||||||
|
return (rt.totalMemory() - rt.freeMemory()) / 1024
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getGcCount(): Long =
|
||||||
|
ManagementFactory.getGarbageCollectorMXBeans().sumByLong { max(0, it.collectionCount) }
|
||||||
|
|
||||||
|
}
|
||||||
+1
@@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright 2010-2016 JetBrains s.r.o.
|
* Copyright 2010-2016 JetBrains s.r.o.
|
||||||
*
|
*
|
||||||
|
|||||||
+1
-1
@@ -103,7 +103,7 @@ internal abstract class KotlinSourceSetProcessor<T : AbstractKotlinCompile<*>>(
|
|||||||
|
|
||||||
private fun prepareKotlinCompileTask(): TaskProvider<out T> =
|
private fun prepareKotlinCompileTask(): TaskProvider<out T> =
|
||||||
registerKotlinCompileTask(register = ::doRegisterTask).also { task ->
|
registerKotlinCompileTask(register = ::doRegisterTask).also { task ->
|
||||||
kotlinCompilation.output.addClassesDir { project.files(task.map { it.destinationDir }) }
|
kotlinCompilation.output.addClassesDir { project.files(task.map { it.destinationDir }).builtBy(task) }
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun registerKotlinCompileTask(
|
protected fun registerKotlinCompileTask(
|
||||||
|
|||||||
+6
-2
@@ -24,6 +24,7 @@ import org.gradle.api.internal.FeaturePreviews
|
|||||||
import org.gradle.api.internal.file.FileResolver
|
import org.gradle.api.internal.file.FileResolver
|
||||||
import org.gradle.api.logging.Logger
|
import org.gradle.api.logging.Logger
|
||||||
import org.gradle.api.logging.Logging
|
import org.gradle.api.logging.Logging
|
||||||
|
import org.gradle.build.event.BuildEventsListenerRegistry
|
||||||
import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry
|
import org.gradle.tooling.provider.model.ToolingModelBuilderRegistry
|
||||||
import org.jetbrains.kotlin.gradle.dsl.*
|
import org.jetbrains.kotlin.gradle.dsl.*
|
||||||
import org.jetbrains.kotlin.gradle.logging.kotlinDebug
|
import org.jetbrains.kotlin.gradle.logging.kotlinDebug
|
||||||
@@ -49,6 +50,7 @@ import kotlin.reflect.KClass
|
|||||||
abstract class KotlinBasePluginWrapper(
|
abstract class KotlinBasePluginWrapper(
|
||||||
protected val fileResolver: FileResolver
|
protected val fileResolver: FileResolver
|
||||||
) : Plugin<Project> {
|
) : Plugin<Project> {
|
||||||
|
|
||||||
private val log = Logging.getLogger(this.javaClass)
|
private val log = Logging.getLogger(this.javaClass)
|
||||||
val kotlinPluginVersion = loadKotlinVersionFromResource(log)
|
val kotlinPluginVersion = loadKotlinVersionFromResource(log)
|
||||||
|
|
||||||
@@ -58,7 +60,8 @@ abstract class KotlinBasePluginWrapper(
|
|||||||
DefaultKotlinSourceSetFactory(project, fileResolver)
|
DefaultKotlinSourceSetFactory(project, fileResolver)
|
||||||
|
|
||||||
override fun apply(project: Project) {
|
override fun apply(project: Project) {
|
||||||
val statisticsReporter = KotlinBuildStatsService.getOrCreateInstance(project.gradle)
|
val listenerRegistryHolder = BuildEventsListenerRegistryHolder.getInstance(project)
|
||||||
|
val statisticsReporter = KotlinBuildStatsService.getOrCreateInstance(project, listenerRegistryHolder)
|
||||||
statisticsReporter?.report(StringMetrics.KOTLIN_COMPILER_VERSION, kotlinPluginVersion)
|
statisticsReporter?.report(StringMetrics.KOTLIN_COMPILER_VERSION, kotlinPluginVersion)
|
||||||
|
|
||||||
checkGradleCompatibility()
|
checkGradleCompatibility()
|
||||||
@@ -80,7 +83,8 @@ abstract class KotlinBasePluginWrapper(
|
|||||||
|
|
||||||
// TODO: consider only set if if daemon or parallel compilation are enabled, though this way it should be safe too
|
// TODO: consider only set if if daemon or parallel compilation are enabled, though this way it should be safe too
|
||||||
System.setProperty(org.jetbrains.kotlin.cli.common.KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY, "true")
|
System.setProperty(org.jetbrains.kotlin.cli.common.KOTLIN_COMPILER_ENVIRONMENT_KEEPALIVE_PROPERTY, "true")
|
||||||
val kotlinGradleBuildServices = KotlinGradleBuildServices.getInstance(project.gradle)
|
|
||||||
|
val kotlinGradleBuildServices = KotlinGradleBuildServices.getInstance(project, listenerRegistryHolder)
|
||||||
|
|
||||||
kotlinGradleBuildServices.detectKotlinPluginLoadedInMultipleProjects(project, kotlinPluginVersion)
|
kotlinGradleBuildServices.detectKotlinPluginLoadedInMultipleProjects(project, kotlinPluginVersion)
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -27,16 +27,16 @@ import java.io.File
|
|||||||
|
|
||||||
internal fun AbstractCompile.appendClasspathDynamically(file: File) {
|
internal fun AbstractCompile.appendClasspathDynamically(file: File) {
|
||||||
var added = false
|
var added = false
|
||||||
|
val objects = project.objects
|
||||||
doFirst {
|
doFirst {
|
||||||
if (file !in classpath) {
|
if (file !in classpath) {
|
||||||
classpath += project.files(file)
|
classpath += objects.fileCollection().from(file)
|
||||||
added = true
|
added = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
doLast {
|
doLast {
|
||||||
if (added) {
|
if (added) {
|
||||||
classpath -= project.files(file)
|
classpath -= objects.fileCollection().from(file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+112
-44
@@ -24,9 +24,14 @@ import java.util.zip.ZipOutputStream
|
|||||||
import javax.xml.parsers.DocumentBuilderFactory
|
import javax.xml.parsers.DocumentBuilderFactory
|
||||||
|
|
||||||
internal sealed class MetadataDependencyResolution(
|
internal sealed class MetadataDependencyResolution(
|
||||||
|
@field:Transient // can't be used with Gradle Instant Execution, but fortunately not needed when deserialized
|
||||||
val dependency: ResolvedComponentResult,
|
val dependency: ResolvedComponentResult,
|
||||||
|
@field:Transient
|
||||||
val projectDependency: Project?
|
val projectDependency: Project?
|
||||||
) {
|
) {
|
||||||
|
/** Evaluate and store the value, as the [dependency] will be lost during Gradle instant execution */
|
||||||
|
// val originalArtifactFiles: List<File> = dependency.dependents.flatMap { it.allModuleArtifacts } .map { it.file }
|
||||||
|
|
||||||
override fun toString(): String {
|
override fun toString(): String {
|
||||||
val verb = when (this) {
|
val verb = when (this) {
|
||||||
is KeepOriginalDependency -> "keep"
|
is KeepOriginalDependency -> "keep"
|
||||||
@@ -59,7 +64,10 @@ internal sealed class MetadataDependencyResolution(
|
|||||||
* If [doProcessFiles] is true, these temporary files are actually re-created during the call,
|
* If [doProcessFiles] is true, these temporary files are actually re-created during the call,
|
||||||
* otherwise only their paths are returned, while the files might be missing.
|
* otherwise only their paths are returned, while the files might be missing.
|
||||||
*/
|
*/
|
||||||
abstract fun getMetadataFilesBySourceSet(baseDir: File, doProcessFiles: Boolean): Map<String, FileCollection>
|
fun getMetadataFilesBySourceSet(baseDir: File, doProcessFiles: Boolean): Map<String, FileCollection> =
|
||||||
|
getExtractableMetadataFiles(baseDir).getMetadataFilesPerSourceSet(doProcessFiles)
|
||||||
|
|
||||||
|
abstract fun getExtractableMetadataFiles(baseDir: File): ExtractableMetadataFiles
|
||||||
|
|
||||||
override fun toString(): String =
|
override fun toString(): String =
|
||||||
super.toString() + ", sourceSets = " + allVisibleSourceSetNames.joinToString(", ", "[", "]") {
|
super.toString() + ", sourceSets = " + allVisibleSourceSetNames.joinToString(", ", "[", "]") {
|
||||||
@@ -183,6 +191,7 @@ internal class GranularMetadataTransformation(
|
|||||||
|
|
||||||
allModuleDependencies.forEach { resolvedDependency ->
|
allModuleDependencies.forEach { resolvedDependency ->
|
||||||
if (resolvedDependency.selected !in visitedDependencies) {
|
if (resolvedDependency.selected !in visitedDependencies) {
|
||||||
|
// val files = resolvedDependency.moduleArtifacts.map { it.file }
|
||||||
result.add(
|
result.add(
|
||||||
MetadataDependencyResolution.ExcludeAsUnrequested(
|
MetadataDependencyResolution.ExcludeAsUnrequested(
|
||||||
resolvedDependency.selected,
|
resolvedDependency.selected,
|
||||||
@@ -273,6 +282,20 @@ internal class GranularMetadataTransformation(
|
|||||||
module, resolvedToProject, projectStructureMetadata, allVisibleSourceSets, visibleSourceSetsExcludingDependsOn,
|
module, resolvedToProject, projectStructureMetadata, allVisibleSourceSets, visibleSourceSetsExcludingDependsOn,
|
||||||
transitiveDependenciesToVisit, mppDependencyMetadataExtractor
|
transitiveDependenciesToVisit, mppDependencyMetadataExtractor
|
||||||
)
|
)
|
||||||
|
/*
|
||||||
|
return object : MetadataDependencyResolution.ChooseVisibleSourceSets(
|
||||||
|
module,
|
||||||
|
projectDependency,
|
||||||
|
projectStructureMetadata,
|
||||||
|
allVisibleSourceSets,
|
||||||
|
visibleSourceSetsExcludingDependsOn,
|
||||||
|
transitiveDependenciesToVisit
|
||||||
|
) {
|
||||||
|
override fun getExtractableMetadataFiles(baseDir: File): ExtractableMetadataFiles =
|
||||||
|
mppDependencyMetadataExtractor.getExtractableMetadataFiles(visibleSourceSetsExcludingDependsOn, baseDir)
|
||||||
|
|
||||||
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ChooseVisibleSourceSetsImpl(
|
private class ChooseVisibleSourceSetsImpl(
|
||||||
@@ -291,18 +314,24 @@ internal class GranularMetadataTransformation(
|
|||||||
visibleSourceSetNamesExcludingDependsOn,
|
visibleSourceSetNamesExcludingDependsOn,
|
||||||
visibleTransitiveDependencies
|
visibleTransitiveDependencies
|
||||||
) {
|
) {
|
||||||
override fun getMetadataFilesBySourceSet(baseDir: File, doProcessFiles: Boolean): Map<String, FileCollection> =
|
override fun getExtractableMetadataFiles(baseDir: File): ExtractableMetadataFiles =
|
||||||
metadataExtractor.getVisibleSourceSetsMetadata(visibleSourceSetNamesExcludingDependsOn, baseDir, doProcessFiles)
|
object : ExtractableMetadataFiles() {
|
||||||
|
override fun getMetadataFilesPerSourceSet(doProcessFiles: Boolean) : Map<String, FileCollection>
|
||||||
|
= metadataExtractor.getExtractableMetadataFiles(visibleSourceSetNamesExcludingDependsOn, baseDir, doProcessFiles)
|
||||||
|
.getMetadataFilesPerSourceSet(doProcessFiles)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private abstract class MppDependencyMetadataExtractor(val project: Project, val dependency: ResolvedComponentResult) {
|
private abstract class MppDependencyMetadataExtractor(val project: Project, val dependency: ResolvedComponentResult) {
|
||||||
abstract fun getProjectStructureMetadata(): KotlinProjectStructureMetadata?
|
abstract fun getProjectStructureMetadata(): KotlinProjectStructureMetadata?
|
||||||
abstract fun getVisibleSourceSetsMetadata(
|
|
||||||
|
abstract fun getExtractableMetadataFiles(
|
||||||
visibleSourceSetNames: Set<String>,
|
visibleSourceSetNames: Set<String>,
|
||||||
baseDir: File,
|
baseDir: File,
|
||||||
doProcessFiles: Boolean
|
doProcessFiles: Boolean
|
||||||
): Map<String, FileCollection>
|
): ExtractableMetadataFiles
|
||||||
}
|
}
|
||||||
|
|
||||||
private class ProjectMppDependencyMetadataExtractor(
|
private class ProjectMppDependencyMetadataExtractor(
|
||||||
@@ -313,14 +342,19 @@ private class ProjectMppDependencyMetadataExtractor(
|
|||||||
override fun getProjectStructureMetadata(): KotlinProjectStructureMetadata? =
|
override fun getProjectStructureMetadata(): KotlinProjectStructureMetadata? =
|
||||||
buildKotlinProjectStructureMetadata(dependencyProject)
|
buildKotlinProjectStructureMetadata(dependencyProject)
|
||||||
|
|
||||||
override fun getVisibleSourceSetsMetadata(
|
override fun getExtractableMetadataFiles(
|
||||||
visibleSourceSetNames: Set<String>,
|
visibleSourceSetNames: Set<String>,
|
||||||
baseDir: File,
|
baseDir: File,
|
||||||
doProcessFiles: Boolean
|
doProcessFiles: Boolean
|
||||||
): Map<String, FileCollection> =
|
): ExtractableMetadataFiles {
|
||||||
dependencyProject.multiplatformExtension.targets.getByName(KotlinMultiplatformPlugin.METADATA_TARGET_NAME).compilations
|
val result = dependencyProject.multiplatformExtension.targets.getByName(KotlinMultiplatformPlugin.METADATA_TARGET_NAME).compilations
|
||||||
.filter { it.name in visibleSourceSetNames }
|
.filter { it.name in visibleSourceSetNames }
|
||||||
.associate { it.defaultSourceSet.name to it.output.classesDirs }
|
.associate { it.defaultSourceSet.name to it.output.classesDirs }
|
||||||
|
|
||||||
|
return object : ExtractableMetadataFiles() {
|
||||||
|
override fun getMetadataFilesPerSourceSet(doProcessFiles: Boolean): Map<String, FileCollection> = result
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class JarArtifactMppDependencyMetadataExtractor(
|
private class JarArtifactMppDependencyMetadataExtractor(
|
||||||
@@ -344,72 +378,106 @@ private class JarArtifactMppDependencyMetadataExtractor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getVisibleSourceSetsMetadata(
|
override fun getExtractableMetadataFiles(
|
||||||
visibleSourceSetNames: Set<String>,
|
visibleSourceSetNames: Set<String>,
|
||||||
baseDir: File,
|
baseDir: File,
|
||||||
doProcessFiles: Boolean
|
doProcessFiles: Boolean
|
||||||
): Map<String, FileCollection> {
|
): ExtractableMetadataFiles {
|
||||||
|
// val artifactFile = artifact.file
|
||||||
val primaryArtifact = primaryArtifact
|
val primaryArtifact = primaryArtifact
|
||||||
val moduleId = ModuleIds.fromComponent(project, dependency)
|
val moduleId = ModuleIds.fromComponent(project, dependency)
|
||||||
|
|
||||||
return extractSourceSetMetadataFromArtifacts(
|
// val jarArtifact = artifact
|
||||||
|
// ?: return object : ExtractableMetadataFiles() {
|
||||||
|
// override fun getMetadataFilesPerSourceSet(doProcessFiles: Boolean): Map<String, FileCollection> = emptyMap()
|
||||||
|
// }
|
||||||
|
|
||||||
|
return JarExtractableMetadataFiles(
|
||||||
moduleId,
|
moduleId,
|
||||||
|
project,
|
||||||
|
primaryArtifact,
|
||||||
|
// artifactJar,
|
||||||
|
// visibleSourceSetNames,
|
||||||
baseDir,
|
baseDir,
|
||||||
doProcessFiles,
|
doProcessFiles,
|
||||||
visibleSourceSetNames.associate { it to (metadataArtifactBySourceSet[it] ?: primaryArtifact) }
|
visibleSourceSetNames.associate { it to (metadataArtifactBySourceSet[it] ?: primaryArtifact) }
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun extractSourceSetMetadataFromArtifacts(
|
private class JarExtractableMetadataFiles(
|
||||||
module: ModuleDependencyIdentifier,
|
private val module: ModuleDependencyIdentifier,
|
||||||
baseDir: File,
|
private val project: Project,
|
||||||
|
private val primaryArtifact: File,
|
||||||
|
private val baseDir: File,
|
||||||
doProcessFiles: Boolean,
|
doProcessFiles: Boolean,
|
||||||
artifactBySourceSet: Map<String, File>
|
private val artifactBySourceSet: Map<String, File>
|
||||||
): Map<String, FileCollection> {
|
) : ExtractableMetadataFiles() {
|
||||||
val moduleString = "${module.groupId}-${module.moduleId}"
|
|
||||||
val transformedModuleRoot = run { baseDir.resolve(moduleString).also { it.mkdirs() } }
|
|
||||||
|
|
||||||
val resultFiles = mutableMapOf<String, FileCollection>()
|
//TODO its part of extractor. Move it
|
||||||
|
fun getProjectStructureMetadata(): KotlinProjectStructureMetadata? {
|
||||||
|
return ZipFile(primaryArtifact).use { zip ->
|
||||||
|
val metadata = zip.getEntry("META-INF/$MULTIPLATFORM_PROJECT_METADATA_FILE_NAME")
|
||||||
|
?: return null
|
||||||
|
|
||||||
val projectStructureMetadata = checkNotNull(getProjectStructureMetadata()) {
|
val metadataXmlDocument = zip.getInputStream(metadata).use { inputStream ->
|
||||||
"can't extract metadata from a module without project structure metadata"
|
DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(inputStream)
|
||||||
|
}
|
||||||
|
|
||||||
|
parseKotlinSourceSetMetadataFromXml(metadataXmlDocument)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
artifactBySourceSet.forEach { (sourceSetName, artifact) ->
|
override fun getMetadataFilesPerSourceSet(doProcessFiles: Boolean): Map<String, FileCollection> {
|
||||||
ZipFile(artifact).use { zip ->
|
val moduleString = "${module.groupId}-${module.moduleId}"
|
||||||
val entries = zip.entries().asSequence().filter { it.name.startsWith("$sourceSetName/") }.toList()
|
val transformedModuleRoot = run { baseDir.resolve(moduleString).also { it.mkdirs() } }
|
||||||
|
|
||||||
// TODO: once IJ supports non-JAR metadata dependencies, extract to a directory, not a JAR
|
val resultFiles = mutableMapOf<String, FileCollection>()
|
||||||
// Also, if both IJ and the CLI compiler can read metadata from a path inside a JAR, then no operations will be needed
|
val projectStructureMetadata = checkNotNull(getProjectStructureMetadata()) {
|
||||||
|
"can't extract metadata from a module without project structure metadata"
|
||||||
|
}
|
||||||
|
// val artifactJar :File= artifactBySourceSet.values().first()
|
||||||
|
artifactBySourceSet.forEach { (sourceSetName, artifact) ->
|
||||||
|
ZipFile(artifact).use { zip ->
|
||||||
|
val entries = zip.entries().asSequence().filter { it.name.startsWith("$sourceSetName/") }.toList()
|
||||||
|
|
||||||
if (entries.any()) {
|
// TODO: once IJ supports non-JAR metadata dependencies, extract to a directory, not a JAR
|
||||||
val extension = projectStructureMetadata.sourceSetBinaryLayout[sourceSetName]?.archiveExtension
|
// Also, if both IJ and the CLI compiler can read metadata from a path inside a JAR, then no operations will be needed
|
||||||
?: SourceSetMetadataLayout.METADATA.archiveExtension
|
|
||||||
|
|
||||||
val extractToJarFile = transformedModuleRoot.resolve("$moduleString-$sourceSetName.$extension")
|
if (entries.any()) {
|
||||||
resultFiles[sourceSetName] = project.files(extractToJarFile)
|
val extension = projectStructureMetadata.sourceSetBinaryLayout[sourceSetName]?.archiveExtension
|
||||||
|
?: SourceSetMetadataLayout.METADATA.archiveExtension
|
||||||
|
|
||||||
if (doProcessFiles) {
|
val extractToJarFile = transformedModuleRoot.resolve("$moduleString-$sourceSetName.$extension")
|
||||||
ZipOutputStream(extractToJarFile.outputStream()).use { resultZipOutput ->
|
resultFiles[sourceSetName] = project.files(extractToJarFile)
|
||||||
for (entry in entries) {
|
|
||||||
if (entry.isDirectory)
|
|
||||||
continue
|
|
||||||
|
|
||||||
// Drop the source set name from the entry path
|
if (doProcessFiles) {
|
||||||
val resultEntry = ZipEntry(entry.name.substringAfter("/"))
|
ZipOutputStream(extractToJarFile.outputStream()).use { resultZipOutput ->
|
||||||
|
for (entry in entries) {
|
||||||
|
if (entry.isDirectory)
|
||||||
|
continue
|
||||||
|
|
||||||
zip.getInputStream(entry).use { inputStream ->
|
// Drop the source set name from the entry path
|
||||||
resultZipOutput.putNextEntry(resultEntry)
|
val resultEntry = ZipEntry(entry.name.substringAfter("/"))
|
||||||
inputStream.copyTo(resultZipOutput)
|
|
||||||
resultZipOutput.closeEntry()
|
zip.getInputStream(entry).use { inputStream ->
|
||||||
|
resultZipOutput.putNextEntry(resultEntry)
|
||||||
|
inputStream.copyTo(resultZipOutput)
|
||||||
|
resultZipOutput.closeEntry()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return resultFiles
|
return resultFiles
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// This class is needed to encapsulate how we extract the files and point to them in a way that doesn't capture the Gradle project state
|
||||||
|
internal abstract class ExtractableMetadataFiles {
|
||||||
|
abstract fun getMetadataFilesPerSourceSet(doProcessFiles: Boolean): Map<String, FileCollection>
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
+47
-17
@@ -15,22 +15,28 @@ import org.jetbrains.kotlin.gradle.plugin.sources.KotlinDependencyScope.*
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.sources.getSourceSetHierarchy
|
import org.jetbrains.kotlin.gradle.plugin.sources.getSourceSetHierarchy
|
||||||
import org.jetbrains.kotlin.gradle.targets.metadata.ALL_COMPILE_METADATA_CONFIGURATION_NAME
|
import org.jetbrains.kotlin.gradle.targets.metadata.ALL_COMPILE_METADATA_CONFIGURATION_NAME
|
||||||
import org.jetbrains.kotlin.gradle.targets.metadata.KotlinMetadataTargetConfigurator
|
import org.jetbrains.kotlin.gradle.targets.metadata.KotlinMetadataTargetConfigurator
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.getValue
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
open class TransformKotlinGranularMetadata
|
open class TransformKotlinGranularMetadata
|
||||||
@Inject constructor(
|
@Inject constructor(
|
||||||
@get:Internal
|
@get:Internal
|
||||||
|
@field:Transient
|
||||||
val kotlinSourceSet: KotlinSourceSet
|
val kotlinSourceSet: KotlinSourceSet
|
||||||
) : DefaultTask() {
|
) : DefaultTask() {
|
||||||
|
|
||||||
@get:OutputDirectory
|
@get:OutputDirectory
|
||||||
val outputsDir: File = project.buildDir.resolve("kotlinSourceSetMetadata/${kotlinSourceSet.name}")
|
val outputsDir: File by project.provider {
|
||||||
|
project.buildDir.resolve("kotlinSourceSetMetadata/${kotlinSourceSet.name}")
|
||||||
|
}
|
||||||
|
|
||||||
@Suppress("unused") // Gradle input
|
@Suppress("unused") // Gradle input
|
||||||
@get:InputFiles
|
@get:InputFiles
|
||||||
@get:PathSensitive(PathSensitivity.RELATIVE)
|
@get:PathSensitive(PathSensitivity.RELATIVE)
|
||||||
internal val allSourceSetsMetadataConfiguration = project.configurations.getByName(ALL_COMPILE_METADATA_CONFIGURATION_NAME)
|
internal val allSourceSetsMetadataConfiguration: FileCollection by lazy {
|
||||||
|
project.files(project.configurations.getByName(ALL_COMPILE_METADATA_CONFIGURATION_NAME))
|
||||||
|
}
|
||||||
|
|
||||||
private val participatingSourceSets: Set<KotlinSourceSet>
|
private val participatingSourceSets: Set<KotlinSourceSet>
|
||||||
get() = transformation.kotlinSourceSet.getSourceSetHierarchy().toMutableSet().apply {
|
get() = transformation.kotlinSourceSet.getSourceSetHierarchy().toMutableSet().apply {
|
||||||
@@ -40,15 +46,14 @@ open class TransformKotlinGranularMetadata
|
|||||||
|
|
||||||
@Suppress("unused") // Gradle input
|
@Suppress("unused") // Gradle input
|
||||||
@get:Input
|
@get:Input
|
||||||
internal val inputSourceSetsAndCompilations: Map<String, Iterable<String>>
|
internal val inputSourceSetsAndCompilations: Map<String, Iterable<String>> by project.provider {
|
||||||
get() {
|
val sourceSets = participatingSourceSets
|
||||||
val sourceSets = participatingSourceSets
|
CompilationSourceSetUtil.compilationsBySourceSets(project)
|
||||||
return CompilationSourceSetUtil.compilationsBySourceSets(project)
|
.filterKeys { it in sourceSets }
|
||||||
.filterKeys { it in sourceSets }
|
.entries.associate { (sourceSet, compilations) ->
|
||||||
.entries.associate { (sourceSet, compilations) ->
|
sourceSet.name to compilations.map { it.name }.sorted()
|
||||||
sourceSet.name to compilations.map { it.name }.sorted()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private val participatingCompilations: Iterable<KotlinCompilation<*>>
|
private val participatingCompilations: Iterable<KotlinCompilation<*>>
|
||||||
get() {
|
get() {
|
||||||
@@ -58,13 +63,15 @@ open class TransformKotlinGranularMetadata
|
|||||||
|
|
||||||
@Suppress("unused") // Gradle input
|
@Suppress("unused") // Gradle input
|
||||||
@get:Input
|
@get:Input
|
||||||
internal val inputCompilationDependencies: Map<String, Set<List<String?>>>
|
internal val inputCompilationDependencies: Map<String, Set<List<String?>>> by project.provider {
|
||||||
get() = participatingCompilations.associate {
|
participatingCompilations.associate {
|
||||||
it.name to project.configurations.getByName(it.compileDependencyConfigurationName)
|
it.name to project.configurations.getByName(it.compileDependencyConfigurationName)
|
||||||
.allDependencies.map { listOf(it.group, it.name, it.version) }.toSet()
|
.allDependencies.map { listOf(it.group, it.name, it.version) }.toSet()
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@get:Internal
|
@get:Internal
|
||||||
|
@delegate:Transient
|
||||||
internal val transformation: GranularMetadataTransformation by lazy {
|
internal val transformation: GranularMetadataTransformation by lazy {
|
||||||
GranularMetadataTransformation(
|
GranularMetadataTransformation(
|
||||||
project,
|
project,
|
||||||
@@ -82,14 +89,39 @@ open class TransformKotlinGranularMetadata
|
|||||||
}
|
}
|
||||||
|
|
||||||
@get:Internal
|
@get:Internal
|
||||||
internal val metadataDependencyResolutions: Iterable<MetadataDependencyResolution>
|
@delegate:Transient // exclude from Gradle instant execution state
|
||||||
get() = transformation.metadataDependencyResolutions
|
internal val metadataDependencyResolutions: Iterable<MetadataDependencyResolution> by project.provider {
|
||||||
|
transformation.metadataDependencyResolutions
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO avoid using it
|
||||||
@get:Internal
|
@get:Internal
|
||||||
internal val filesByResolution: Map<out MetadataDependencyResolution, FileCollection>
|
internal val filesByResolution: Map<out MetadataDependencyResolution, FileCollection>
|
||||||
get() = metadataDependencyResolutions.filterIsInstance<MetadataDependencyResolution.ChooseVisibleSourceSets>()
|
get() = metadataDependencyResolutions.filterIsInstance<MetadataDependencyResolution.ChooseVisibleSourceSets>()
|
||||||
.associate { it to project.files(it.getMetadataFilesBySourceSet(outputsDir, doProcessFiles = false).values) }
|
.associate { it to project.files(it.getMetadataFilesBySourceSet(outputsDir, doProcessFiles = false).values) }
|
||||||
|
|
||||||
|
// @get:Internal
|
||||||
|
// internal val filesByOriginalFiles: Map<out Iterable<File>, FileCollection> by project.provider {
|
||||||
|
// metadataDependencyResolutions.associate {
|
||||||
|
// it.originalArtifactFiles to project.files(
|
||||||
|
// when (it) {
|
||||||
|
// is MetadataDependencyResolution.ChooseVisibleSourceSets ->
|
||||||
|
// it.getMetadataFilesBySourceSet(outputsDir, doProcessFiles = false).values
|
||||||
|
// is MetadataDependencyResolution.ExcludeAsUnrequested ->
|
||||||
|
// emptyList()
|
||||||
|
// is MetadataDependencyResolution.KeepOriginalDependency ->
|
||||||
|
// it.originalArtifactFiles
|
||||||
|
// }
|
||||||
|
// )
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
private val extractableFiles by project.provider {
|
||||||
|
transformation.metadataDependencyResolutions
|
||||||
|
.filterIsInstance<MetadataDependencyResolution.ChooseVisibleSourceSets>()
|
||||||
|
.map { it.getExtractableMetadataFiles(outputsDir) }
|
||||||
|
}
|
||||||
|
|
||||||
@TaskAction
|
@TaskAction
|
||||||
fun transformMetadata() {
|
fun transformMetadata() {
|
||||||
if (outputsDir.isDirectory) {
|
if (outputsDir.isDirectory) {
|
||||||
@@ -97,8 +129,6 @@ open class TransformKotlinGranularMetadata
|
|||||||
}
|
}
|
||||||
outputsDir.mkdirs()
|
outputsDir.mkdirs()
|
||||||
|
|
||||||
metadataDependencyResolutions
|
extractableFiles.forEach { it.getMetadataFilesPerSourceSet(doProcessFiles = true) }
|
||||||
.filterIsInstance<MetadataDependencyResolution.ChooseVisibleSourceSets>()
|
|
||||||
.forEach { it.getMetadataFilesBySourceSet(outputsDir, doProcessFiles = true) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
+3
-2
@@ -69,6 +69,7 @@ internal class DefaultLanguageSettingsBuilder : LanguageSettingsBuilder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* A Kotlin task that is responsible for code analysis of the owner of this language settings builder. */
|
/* A Kotlin task that is responsible for code analysis of the owner of this language settings builder. */
|
||||||
|
@Transient // not needed during Gradle Instant Execution
|
||||||
var compilerPluginOptionsTask: Lazy<AbstractCompile?> = lazyOf(null)
|
var compilerPluginOptionsTask: Lazy<AbstractCompile?> = lazyOf(null)
|
||||||
|
|
||||||
val compilerPluginArguments: List<String>?
|
val compilerPluginArguments: List<String>?
|
||||||
@@ -76,7 +77,7 @@ internal class DefaultLanguageSettingsBuilder : LanguageSettingsBuilder {
|
|||||||
val pluginOptionsTask = compilerPluginOptionsTask.value ?: return null
|
val pluginOptionsTask = compilerPluginOptionsTask.value ?: return null
|
||||||
return when (pluginOptionsTask) {
|
return when (pluginOptionsTask) {
|
||||||
is AbstractKotlinCompile<*> -> pluginOptionsTask.pluginOptions
|
is AbstractKotlinCompile<*> -> pluginOptionsTask.pluginOptions
|
||||||
is AbstractKotlinNativeCompile<*> -> pluginOptionsTask.compilerPluginOptions
|
is AbstractKotlinNativeCompile<*, *> -> pluginOptionsTask.compilerPluginOptions
|
||||||
else -> error("Unexpected task: $pluginOptionsTask")
|
else -> error("Unexpected task: $pluginOptionsTask")
|
||||||
}.arguments
|
}.arguments
|
||||||
}
|
}
|
||||||
@@ -86,7 +87,7 @@ internal class DefaultLanguageSettingsBuilder : LanguageSettingsBuilder {
|
|||||||
val pluginClasspathTask = compilerPluginOptionsTask.value ?: return null
|
val pluginClasspathTask = compilerPluginOptionsTask.value ?: return null
|
||||||
return when (pluginClasspathTask) {
|
return when (pluginClasspathTask) {
|
||||||
is AbstractKotlinCompile<*> -> pluginClasspathTask.pluginClasspath
|
is AbstractKotlinCompile<*> -> pluginClasspathTask.pluginClasspath
|
||||||
is AbstractKotlinNativeCompile<*> -> pluginClasspathTask.compilerPluginClasspath ?: pluginClasspathTask.project.files()
|
is AbstractKotlinNativeCompile<*, *> -> pluginClasspathTask.compilerPluginClasspath ?: pluginClasspathTask.project.files()
|
||||||
else -> error("Unexpected task: $pluginClasspathTask")
|
else -> error("Unexpected task: $pluginClasspathTask")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+215
@@ -0,0 +1,215 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.gradle.plugin.statistics
|
||||||
|
|
||||||
|
import org.gradle.api.Project
|
||||||
|
import org.gradle.api.artifacts.DependencySet
|
||||||
|
import org.gradle.api.invocation.Gradle
|
||||||
|
import org.gradle.api.logging.Logging
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.API
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.COMPILE
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.IMPLEMENTATION
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.RUNTIME
|
||||||
|
import org.jetbrains.kotlin.statistics.BuildSessionLogger
|
||||||
|
import org.jetbrains.kotlin.statistics.metrics.BooleanMetrics
|
||||||
|
import org.jetbrains.kotlin.statistics.metrics.NumericalMetrics
|
||||||
|
import org.jetbrains.kotlin.statistics.metrics.StringMetrics
|
||||||
|
import java.io.File
|
||||||
|
import java.lang.management.ManagementFactory
|
||||||
|
import javax.management.MBeanServer
|
||||||
|
import javax.management.ObjectName
|
||||||
|
import kotlin.system.measureTimeMillis
|
||||||
|
|
||||||
|
class KotlinBuildStatHandler {
|
||||||
|
companion object {
|
||||||
|
@JvmStatic
|
||||||
|
internal fun getLogger() = Logging.getLogger(KotlinBuildStatHandler::class.java)
|
||||||
|
|
||||||
|
internal fun <T> runSafe(methodName: String, action: () -> T?): T? {
|
||||||
|
return try {
|
||||||
|
getLogger().debug("Executing [$methodName]")
|
||||||
|
action.invoke()
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
logException("Could not execute [$methodName]", e)
|
||||||
|
null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun logException(description: String, e: Throwable) {
|
||||||
|
getLogger().info(description)
|
||||||
|
getLogger().debug(e.message, e)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun buildFinished(
|
||||||
|
gradle: Gradle?,
|
||||||
|
beanName: ObjectName,
|
||||||
|
sessionLogger: BuildSessionLogger,
|
||||||
|
action: String?,
|
||||||
|
failure: Throwable?
|
||||||
|
) {
|
||||||
|
runSafe("${KotlinBuildStatHandler::class.java}.buildFinished") {
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
if (gradle != null) reportGlobalMetrics(gradle, sessionLogger)
|
||||||
|
} finally {
|
||||||
|
sessionLogger.finishBuildSession(action, failure)
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
val mbs: MBeanServer = ManagementFactory.getPlatformMBeanServer()
|
||||||
|
if (mbs.isRegistered(beanName)) {
|
||||||
|
mbs.unregisterMBean(beanName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun reportGlobalMetrics(gradle: Gradle, sessionLogger: BuildSessionLogger) {
|
||||||
|
System.getProperty("os.name")?.also {
|
||||||
|
sessionLogger.report(StringMetrics.OS_TYPE, System.getProperty("os.name"))
|
||||||
|
}
|
||||||
|
sessionLogger.report(NumericalMetrics.CPU_NUMBER_OF_CORES, Runtime.getRuntime().availableProcessors().toLong())
|
||||||
|
sessionLogger.report(StringMetrics.GRADLE_VERSION, gradle.gradleVersion)
|
||||||
|
sessionLogger.report(BooleanMetrics.EXECUTED_FROM_IDEA, System.getProperty("idea.active") != null)
|
||||||
|
sessionLogger.report(NumericalMetrics.GRADLE_DAEMON_HEAP_SIZE, Runtime.getRuntime().maxMemory())
|
||||||
|
sessionLogger.report(
|
||||||
|
BooleanMetrics.KOTLIN_OFFICIAL_CODESTYLE,
|
||||||
|
gradle.rootProject.properties["kotlin.code.style"] == "official"
|
||||||
|
) // constants are saved in IDEA plugin and could not be accessed directly
|
||||||
|
|
||||||
|
gradle.taskGraph.whenReady() { taskExecutionGraph ->
|
||||||
|
val executedTaskNames = taskExecutionGraph.allTasks.map { it.name }.distinct()
|
||||||
|
report(sessionLogger, BooleanMetrics.COMPILATION_STARTED, executedTaskNames.contains("compileKotlin"), null)
|
||||||
|
report(sessionLogger, BooleanMetrics.TESTS_EXECUTED, executedTaskNames.contains("compileTestKotlin"), null)
|
||||||
|
report(sessionLogger, BooleanMetrics.MAVEN_PUBLISH_EXECUTED, executedTaskNames.contains("install"), null)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun buildSrcExists(project: Project) = File(project.projectDir, "buildSrc").exists()
|
||||||
|
if (buildSrcExists(gradle.rootProject)) {
|
||||||
|
sessionLogger.report(BooleanMetrics.BUILD_SRC_EXISTS, true)
|
||||||
|
}
|
||||||
|
val statisticOverhead = measureTimeMillis {
|
||||||
|
gradle.allprojects { project ->
|
||||||
|
for (configuration in project.configurations) {
|
||||||
|
val configurationName = configuration.name
|
||||||
|
val dependencies = configuration.dependencies
|
||||||
|
|
||||||
|
when (configurationName) {
|
||||||
|
"kapt" -> {
|
||||||
|
sessionLogger.report(BooleanMetrics.ENABLED_KAPT, true)
|
||||||
|
dependencies?.forEach { dependency ->
|
||||||
|
when (dependency.group) {
|
||||||
|
"com.google.dagger" -> sessionLogger.report(BooleanMetrics.ENABLED_DAGGER, true)
|
||||||
|
"com.android.databinding" -> sessionLogger.report(BooleanMetrics.ENABLED_DATABINDING, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
API -> {
|
||||||
|
sessionLogger.report(NumericalMetrics.CONFIGURATION_API_COUNT, 1)
|
||||||
|
reportLibrariesVersions(sessionLogger, dependencies)
|
||||||
|
}
|
||||||
|
IMPLEMENTATION -> {
|
||||||
|
sessionLogger.report(NumericalMetrics.CONFIGURATION_IMPLEMENTATION_COUNT, 1)
|
||||||
|
reportLibrariesVersions(sessionLogger, dependencies)
|
||||||
|
}
|
||||||
|
COMPILE -> {
|
||||||
|
sessionLogger.report(NumericalMetrics.CONFIGURATION_COMPILE_COUNT, 1)
|
||||||
|
reportLibrariesVersions(sessionLogger, dependencies)
|
||||||
|
}
|
||||||
|
RUNTIME -> {
|
||||||
|
sessionLogger.report(NumericalMetrics.CONFIGURATION_RUNTIME_COUNT, 1)
|
||||||
|
reportLibrariesVersions(sessionLogger, dependencies)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sessionLogger.report(NumericalMetrics.NUMBER_OF_SUBPROJECTS, 1)
|
||||||
|
sessionLogger.report(BooleanMetrics.KOTLIN_KTS_USED, project.buildscript.sourceFile?.name?.endsWith(".kts") ?: false)
|
||||||
|
sessionLogger.report(NumericalMetrics.GRADLE_NUMBER_OF_TASKS, project.tasks.names.size.toLong())
|
||||||
|
sessionLogger.report(
|
||||||
|
NumericalMetrics.GRADLE_NUMBER_OF_UNCONFIGURED_TASKS,
|
||||||
|
project.tasks.names.count { name ->
|
||||||
|
try {
|
||||||
|
project.tasks.named(name).javaClass.name.contains("TaskCreatingProvider")
|
||||||
|
} catch (_: Exception) {
|
||||||
|
true
|
||||||
|
}
|
||||||
|
}.toLong()
|
||||||
|
)
|
||||||
|
|
||||||
|
if (buildSrcExists(project)) {
|
||||||
|
sessionLogger.report(NumericalMetrics.BUILD_SRC_COUNT, 1)
|
||||||
|
sessionLogger.report(BooleanMetrics.BUILD_SRC_EXISTS, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sessionLogger.report(NumericalMetrics.STATISTICS_VISIT_ALL_PROJECTS_OVERHEAD, statisticOverhead)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun reportLibrariesVersions(sessionLogger: BuildSessionLogger, dependencies: DependencySet?) {
|
||||||
|
dependencies?.forEach { dependency ->
|
||||||
|
when {
|
||||||
|
dependency.group?.startsWith("org.springframework") ?: false -> sessionLogger.report(
|
||||||
|
StringMetrics.LIBRARY_SPRING_VERSION,
|
||||||
|
dependency.version ?: "0.0.0"
|
||||||
|
)
|
||||||
|
dependency.group?.startsWith("com.vaadin") ?: false -> sessionLogger.report(
|
||||||
|
StringMetrics.LIBRARY_VAADIN_VERSION,
|
||||||
|
dependency.version ?: "0.0.0"
|
||||||
|
)
|
||||||
|
dependency.group?.startsWith("com.google.gwt") ?: false -> sessionLogger.report(
|
||||||
|
StringMetrics.LIBRARY_GWT_VERSION,
|
||||||
|
dependency.version ?: "0.0.0"
|
||||||
|
)
|
||||||
|
dependency.group?.startsWith("org.hibernate") ?: false -> sessionLogger.report(
|
||||||
|
StringMetrics.LIBRARY_HIBERNATE_VERSION,
|
||||||
|
dependency.version ?: "0.0.0"
|
||||||
|
)
|
||||||
|
dependency.group == "org.jetbrains.kotlin" && dependency.name.startsWith("kotlin-stdlib") -> sessionLogger.report(
|
||||||
|
StringMetrics.KOTLIN_STDLIB_VERSION,
|
||||||
|
dependency.version ?: "0.0.0"
|
||||||
|
)
|
||||||
|
dependency.group == "org.jetbrains.kotlinx" && dependency.name == "kotlinx-coroutines" -> sessionLogger.report(
|
||||||
|
StringMetrics.KOTLIN_COROUTINES_VERSION,
|
||||||
|
dependency.version ?: "0.0.0"
|
||||||
|
)
|
||||||
|
dependency.group == "org.jetbrains.kotlin" && dependency.name == "kotlin-reflect" -> sessionLogger.report(
|
||||||
|
StringMetrics.KOTLIN_REFLECT_VERSION,
|
||||||
|
dependency.version ?: "0.0.0"
|
||||||
|
)
|
||||||
|
dependency.group == "org.jetbrains.kotlinx" && dependency.name
|
||||||
|
.startsWith("kotlinx-serialization-runtime") -> sessionLogger.report(
|
||||||
|
StringMetrics.KOTLIN_SERIALIZATION_VERSION,
|
||||||
|
dependency.version ?: "0.0.0"
|
||||||
|
)
|
||||||
|
dependency.group == "com.android.tools.build" && dependency.name.startsWith("gradle") -> sessionLogger.report(
|
||||||
|
StringMetrics.ANDROID_GRADLE_PLUGIN_VERSION,
|
||||||
|
dependency.version ?: "0.0.0"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun report(sessionLogger: BuildSessionLogger, metric: BooleanMetrics, value: Boolean, subprojectName: String?) {
|
||||||
|
runSafe("report metric ${metric.name}") {
|
||||||
|
sessionLogger.report(metric, value, subprojectName)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun report(sessionLogger: BuildSessionLogger, metric: NumericalMetrics, value: Long, subprojectName: String?) {
|
||||||
|
runSafe("report metric ${metric.name}") {
|
||||||
|
sessionLogger.report(metric, value, subprojectName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun report(sessionLogger: BuildSessionLogger, metric: StringMetrics, value: String, subprojectName: String?) {
|
||||||
|
runSafe("report metric ${metric.name}") {
|
||||||
|
sessionLogger.report(metric, value, subprojectName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+66
@@ -0,0 +1,66 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.gradle.plugin.statistics
|
||||||
|
|
||||||
|
import org.gradle.api.invocation.Gradle
|
||||||
|
import org.gradle.tooling.events.FinishEvent
|
||||||
|
import org.gradle.tooling.events.OperationCompletionListener
|
||||||
|
import org.gradle.tooling.events.configuration.ProjectConfigurationFinishEvent
|
||||||
|
import org.jetbrains.kotlin.statistics.BuildSessionLogger
|
||||||
|
import java.lang.management.ManagementFactory
|
||||||
|
import javax.management.MBeanServer
|
||||||
|
import javax.management.ObjectName
|
||||||
|
|
||||||
|
open class KotlinBuildStatListener(val beanName: ObjectName/*, val gradle: Gradle*/) : OperationCompletionListener, AutoCloseable {
|
||||||
|
|
||||||
|
private var projectEvaluatedTime: Long? = null
|
||||||
|
|
||||||
|
override fun onFinish(event: FinishEvent?) {
|
||||||
|
if (event is ProjectConfigurationFinishEvent) {
|
||||||
|
projectEvaluatedTime = event.eventTime
|
||||||
|
}
|
||||||
|
//todo is it any chance to get failure exception?
|
||||||
|
//todo nothing to do?
|
||||||
|
// KotlinBuildStatHandler.runSafe("${KotlinBuildStatListener::class.java}.onFinish") {
|
||||||
|
//
|
||||||
|
//
|
||||||
|
// try {
|
||||||
|
// val finishTime = event?.result?.endTime
|
||||||
|
// val startTime = event?.result?.startTime
|
||||||
|
// report(NumericalMetrics.GRADLE_BUILD_DURATION, finishTime - it.buildStartedTime)
|
||||||
|
// report(NumericalMetrics.GRADLE_EXECUTION_DURATION, finishTime - it.projectEvaluatedTime)
|
||||||
|
// report(NumericalMetrics.BUILD_FINISH_TIME, finishTime)
|
||||||
|
// } finally {
|
||||||
|
// val mbs: MBeanServer = ManagementFactory.getPlatformMBeanServer()
|
||||||
|
// if (mbs.isRegistered(beanName)) {
|
||||||
|
// mbs.unregisterMBean(beanName)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun close() {
|
||||||
|
// val sessionLogger = BuildSessionLogger(gradle.gradleUserHomeDir)
|
||||||
|
// KotlinBuildStatHandler.runSafe("${KotlinBuildStatListener::class.java}.close()") {
|
||||||
|
// try {
|
||||||
|
// try {
|
||||||
|
// KotlinBuildStatHandler().reportGlobalMetrics(gradle, sessionLogger)
|
||||||
|
// } finally {
|
||||||
|
//// report(NumericalMetrics.GRADLE_BUILD_DURATION, finishTime - it.buildStartedTime)
|
||||||
|
//// report(NumericalMetrics.GRADLE_EXECUTION_DURATION, finishTime - it.projectEvaluatedTime)
|
||||||
|
//// report(NumericalMetrics.BUILD_FINISH_TIME, finishTime)
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// } finally {
|
||||||
|
// val mbs: MBeanServer = ManagementFactory.getPlatformMBeanServer()
|
||||||
|
// if (mbs.isRegistered(beanName)) {
|
||||||
|
// mbs.unregisterMBean(beanName)
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
+17
-175
@@ -8,15 +8,13 @@ package org.jetbrains.kotlin.gradle.plugin.statistics
|
|||||||
import org.gradle.BuildAdapter
|
import org.gradle.BuildAdapter
|
||||||
import org.gradle.BuildResult
|
import org.gradle.BuildResult
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.artifacts.DependencySet
|
|
||||||
import org.gradle.api.invocation.Gradle
|
import org.gradle.api.invocation.Gradle
|
||||||
import org.gradle.api.logging.Logging
|
import org.gradle.api.logging.Logging
|
||||||
import org.gradle.initialization.BuildRequestMetaData
|
import org.gradle.initialization.BuildRequestMetaData
|
||||||
import org.gradle.invocation.DefaultGradle
|
import org.gradle.invocation.DefaultGradle
|
||||||
import org.jetbrains.kotlin.gradle.utils.API
|
import org.jetbrains.kotlin.gradle.plugin.BuildEventsListenerRegistryHolder
|
||||||
import org.jetbrains.kotlin.gradle.utils.COMPILE
|
import org.jetbrains.kotlin.gradle.plugin.statistics.KotlinBuildStatHandler.Companion.runSafe
|
||||||
import org.jetbrains.kotlin.gradle.utils.IMPLEMENTATION
|
import org.jetbrains.kotlin.gradle.utils.isConfigurationCacheAvailable
|
||||||
import org.jetbrains.kotlin.gradle.utils.RUNTIME
|
|
||||||
import org.jetbrains.kotlin.statistics.BuildSessionLogger
|
import org.jetbrains.kotlin.statistics.BuildSessionLogger
|
||||||
import org.jetbrains.kotlin.statistics.BuildSessionLogger.Companion.STATISTICS_FOLDER_NAME
|
import org.jetbrains.kotlin.statistics.BuildSessionLogger.Companion.STATISTICS_FOLDER_NAME
|
||||||
import org.jetbrains.kotlin.statistics.metrics.BooleanMetrics
|
import org.jetbrains.kotlin.statistics.metrics.BooleanMetrics
|
||||||
@@ -87,8 +85,10 @@ internal abstract class KotlinBuildStatsService internal constructor() : BuildAd
|
|||||||
*/
|
*/
|
||||||
@JvmStatic
|
@JvmStatic
|
||||||
@Synchronized
|
@Synchronized
|
||||||
internal fun getOrCreateInstance(gradle: Gradle): IStatisticsValuesConsumer? {
|
internal fun getOrCreateInstance(project: Project, listenerRegistryHolder: BuildEventsListenerRegistryHolder): IStatisticsValuesConsumer? {
|
||||||
|
|
||||||
return runSafe("${KotlinBuildStatsService::class.java}.getOrCreateInstance") {
|
return runSafe("${KotlinBuildStatsService::class.java}.getOrCreateInstance") {
|
||||||
|
val gradle = project.gradle
|
||||||
statisticsIsEnabled = statisticsIsEnabled ?: checkStatisticsEnabled(gradle)
|
statisticsIsEnabled = statisticsIsEnabled ?: checkStatisticsEnabled(gradle)
|
||||||
if (statisticsIsEnabled != true) {
|
if (statisticsIsEnabled != true) {
|
||||||
null
|
null
|
||||||
@@ -106,13 +106,17 @@ internal abstract class KotlinBuildStatsService internal constructor() : BuildAd
|
|||||||
)
|
)
|
||||||
instance = JMXKotlinBuildStatsService(mbs, beanName)
|
instance = JMXKotlinBuildStatsService(mbs, beanName)
|
||||||
} else {
|
} else {
|
||||||
|
val kotlinBuildStatProvider = project.provider{ KotlinBuildStatListener(beanName) }
|
||||||
val newInstance = DefaultKotlinBuildStatsService(gradle, beanName)
|
val newInstance = DefaultKotlinBuildStatsService(gradle, beanName)
|
||||||
|
|
||||||
instance = newInstance
|
instance = newInstance
|
||||||
log.debug("Instantiated ${KotlinBuildStatsService::class.java}: new instance $instance")
|
log.debug("Instantiated ${KotlinBuildStatsService::class.java}: new instance $instance")
|
||||||
mbs.registerMBean(StandardMBean(newInstance, KotlinBuildStatsMXBean::class.java), beanName)
|
mbs.registerMBean(StandardMBean(newInstance, KotlinBuildStatsMXBean::class.java), beanName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
gradle.addBuildListener(instance)
|
if (!isConfigurationCacheAvailable(gradle)) {
|
||||||
|
gradle.addBuildListener(instance)
|
||||||
|
}
|
||||||
instance
|
instance
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -130,7 +134,7 @@ internal abstract class KotlinBuildStatsService internal constructor() : BuildAd
|
|||||||
}
|
}
|
||||||
this.report(NumericalMetrics.STATISTICS_COLLECT_METRICS_OVERHEAD, duration)
|
this.report(NumericalMetrics.STATISTICS_COLLECT_METRICS_OVERHEAD, duration)
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
logException("Could collect statistics metrics", e)
|
KotlinBuildStatHandler.logException("Could collect statistics metrics", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -149,21 +153,6 @@ internal abstract class KotlinBuildStatsService internal constructor() : BuildAd
|
|||||||
gradle.rootProject.properties[ENABLE_STATISTICS_PROPERTY_NAME]?.toString()?.toBoolean() ?: DEFAULT_STATISTICS_STATE
|
gradle.rootProject.properties[ENABLE_STATISTICS_PROPERTY_NAME]?.toString()?.toBoolean() ?: DEFAULT_STATISTICS_STATE
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun logException(description: String, e: Throwable) {
|
|
||||||
getLogger().info(description)
|
|
||||||
getLogger().debug(e.message, e)
|
|
||||||
}
|
|
||||||
|
|
||||||
internal fun <T> runSafe(methodName: String, action: () -> T?): T? {
|
|
||||||
return try {
|
|
||||||
getLogger().debug("Executing [$methodName]")
|
|
||||||
action.invoke()
|
|
||||||
} catch (e: Throwable) {
|
|
||||||
logException("Could not execute [$methodName]", e)
|
|
||||||
null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,132 +201,6 @@ internal class DefaultKotlinBuildStatsService internal constructor(
|
|||||||
return (gradle as? DefaultGradle)?.services?.get(BuildRequestMetaData::class.java)?.startTime
|
return (gradle as? DefaultGradle)?.services?.get(BuildRequestMetaData::class.java)?.startTime
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun reportLibrariesVersions(dependencies: DependencySet?) {
|
|
||||||
dependencies?.forEach { dependency ->
|
|
||||||
when {
|
|
||||||
dependency.group?.startsWith("org.springframework") ?: false -> sessionLogger.report(
|
|
||||||
StringMetrics.LIBRARY_SPRING_VERSION,
|
|
||||||
dependency.version ?: "0.0.0"
|
|
||||||
)
|
|
||||||
dependency.group?.startsWith("com.vaadin") ?: false -> sessionLogger.report(
|
|
||||||
StringMetrics.LIBRARY_VAADIN_VERSION,
|
|
||||||
dependency.version ?: "0.0.0"
|
|
||||||
)
|
|
||||||
dependency.group?.startsWith("com.google.gwt") ?: false -> sessionLogger.report(
|
|
||||||
StringMetrics.LIBRARY_GWT_VERSION,
|
|
||||||
dependency.version ?: "0.0.0"
|
|
||||||
)
|
|
||||||
dependency.group?.startsWith("org.hibernate") ?: false -> sessionLogger.report(
|
|
||||||
StringMetrics.LIBRARY_HIBERNATE_VERSION,
|
|
||||||
dependency.version ?: "0.0.0"
|
|
||||||
)
|
|
||||||
dependency.group == "org.jetbrains.kotlin" && dependency.name.startsWith("kotlin-stdlib") -> sessionLogger.report(
|
|
||||||
StringMetrics.KOTLIN_STDLIB_VERSION,
|
|
||||||
dependency.version ?: "0.0.0"
|
|
||||||
)
|
|
||||||
dependency.group == "org.jetbrains.kotlinx" && dependency.name == "kotlinx-coroutines" -> sessionLogger.report(
|
|
||||||
StringMetrics.KOTLIN_COROUTINES_VERSION,
|
|
||||||
dependency.version ?: "0.0.0"
|
|
||||||
)
|
|
||||||
dependency.group == "org.jetbrains.kotlin" && dependency.name == "kotlin-reflect" -> sessionLogger.report(
|
|
||||||
StringMetrics.KOTLIN_REFLECT_VERSION,
|
|
||||||
dependency.version ?: "0.0.0"
|
|
||||||
)
|
|
||||||
dependency.group == "org.jetbrains.kotlinx" && dependency.name
|
|
||||||
.startsWith("kotlinx-serialization-runtime") -> sessionLogger.report(
|
|
||||||
StringMetrics.KOTLIN_SERIALIZATION_VERSION,
|
|
||||||
dependency.version ?: "0.0.0"
|
|
||||||
)
|
|
||||||
dependency.group == "com.android.tools.build" && dependency.name.startsWith("gradle") -> sessionLogger.report(
|
|
||||||
StringMetrics.ANDROID_GRADLE_PLUGIN_VERSION,
|
|
||||||
dependency.version ?: "0.0.0"
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun reportGlobalMetrics(gradle: Gradle) {
|
|
||||||
System.getProperty("os.name")?.also {
|
|
||||||
sessionLogger.report(StringMetrics.OS_TYPE, System.getProperty("os.name"))
|
|
||||||
}
|
|
||||||
sessionLogger.report(NumericalMetrics.CPU_NUMBER_OF_CORES, Runtime.getRuntime().availableProcessors().toLong())
|
|
||||||
sessionLogger.report(StringMetrics.GRADLE_VERSION, gradle.gradleVersion)
|
|
||||||
sessionLogger.report(BooleanMetrics.EXECUTED_FROM_IDEA, System.getProperty("idea.active") != null)
|
|
||||||
sessionLogger.report(NumericalMetrics.GRADLE_DAEMON_HEAP_SIZE, Runtime.getRuntime().maxMemory())
|
|
||||||
sessionLogger.report(
|
|
||||||
BooleanMetrics.KOTLIN_OFFICIAL_CODESTYLE,
|
|
||||||
gradle.rootProject.properties["kotlin.code.style"] == "official"
|
|
||||||
) // constants are saved in IDEA plugin and could not be accessed directly
|
|
||||||
|
|
||||||
gradle.taskGraph.whenReady() { taskExecutionGraph ->
|
|
||||||
val executedTaskNames = taskExecutionGraph.allTasks.map { it.name }.distinct()
|
|
||||||
report(BooleanMetrics.COMPILATION_STARTED, executedTaskNames.contains("compileKotlin"))
|
|
||||||
report(BooleanMetrics.TESTS_EXECUTED, executedTaskNames.contains("compileTestKotlin"))
|
|
||||||
report(BooleanMetrics.MAVEN_PUBLISH_EXECUTED, executedTaskNames.contains("install"))
|
|
||||||
}
|
|
||||||
|
|
||||||
fun buildSrcExists(project: Project) = File(project.projectDir, "buildSrc").exists()
|
|
||||||
if (buildSrcExists(gradle.rootProject)) {
|
|
||||||
sessionLogger.report(BooleanMetrics.BUILD_SRC_EXISTS, true)
|
|
||||||
}
|
|
||||||
val statisticOverhead = measureTimeMillis {
|
|
||||||
gradle.allprojects { project ->
|
|
||||||
for (configuration in project.configurations) {
|
|
||||||
val configurationName = configuration.name
|
|
||||||
val dependencies = configuration.dependencies
|
|
||||||
|
|
||||||
when (configurationName) {
|
|
||||||
"kapt" -> {
|
|
||||||
sessionLogger.report(BooleanMetrics.ENABLED_KAPT, true)
|
|
||||||
dependencies?.forEach { dependency ->
|
|
||||||
when (dependency.group) {
|
|
||||||
"com.google.dagger" -> sessionLogger.report(BooleanMetrics.ENABLED_DAGGER, true)
|
|
||||||
"com.android.databinding" -> sessionLogger.report(BooleanMetrics.ENABLED_DATABINDING, true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
API -> {
|
|
||||||
sessionLogger.report(NumericalMetrics.CONFIGURATION_API_COUNT, 1)
|
|
||||||
reportLibrariesVersions(dependencies)
|
|
||||||
}
|
|
||||||
IMPLEMENTATION -> {
|
|
||||||
sessionLogger.report(NumericalMetrics.CONFIGURATION_IMPLEMENTATION_COUNT, 1)
|
|
||||||
reportLibrariesVersions(dependencies)
|
|
||||||
}
|
|
||||||
COMPILE -> {
|
|
||||||
sessionLogger.report(NumericalMetrics.CONFIGURATION_COMPILE_COUNT, 1)
|
|
||||||
reportLibrariesVersions(dependencies)
|
|
||||||
}
|
|
||||||
RUNTIME -> {
|
|
||||||
sessionLogger.report(NumericalMetrics.CONFIGURATION_RUNTIME_COUNT, 1)
|
|
||||||
reportLibrariesVersions(dependencies)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sessionLogger.report(NumericalMetrics.NUMBER_OF_SUBPROJECTS, 1)
|
|
||||||
sessionLogger.report(BooleanMetrics.KOTLIN_KTS_USED, project.buildscript.sourceFile?.name?.endsWith(".kts") ?: false)
|
|
||||||
sessionLogger.report(NumericalMetrics.GRADLE_NUMBER_OF_TASKS, project.tasks.names.size.toLong())
|
|
||||||
sessionLogger.report(
|
|
||||||
NumericalMetrics.GRADLE_NUMBER_OF_UNCONFIGURED_TASKS,
|
|
||||||
project.tasks.names.count { name ->
|
|
||||||
try {
|
|
||||||
project.tasks.named(name).javaClass.name.contains("TaskCreatingProvider")
|
|
||||||
} catch (_: Exception) {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
}.toLong()
|
|
||||||
)
|
|
||||||
|
|
||||||
if (buildSrcExists(project)) {
|
|
||||||
sessionLogger.report(NumericalMetrics.BUILD_SRC_COUNT, 1)
|
|
||||||
sessionLogger.report(BooleanMetrics.BUILD_SRC_EXISTS, true)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sessionLogger.report(NumericalMetrics.STATISTICS_VISIT_ALL_PROJECTS_OVERHEAD, statisticOverhead)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun projectsEvaluated(gradle: Gradle) {
|
override fun projectsEvaluated(gradle: Gradle) {
|
||||||
runSafe("${DefaultKotlinBuildStatsService::class.java}.projectEvaluated") {
|
runSafe("${DefaultKotlinBuildStatsService::class.java}.projectEvaluated") {
|
||||||
if (!sessionLogger.isBuildSessionStarted()) {
|
if (!sessionLogger.isBuildSessionStarted()) {
|
||||||
@@ -351,41 +214,20 @@ internal class DefaultKotlinBuildStatsService internal constructor(
|
|||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun buildFinished(result: BuildResult) {
|
override fun buildFinished(result: BuildResult) {
|
||||||
runSafe("${DefaultKotlinBuildStatsService::class.java}.buildFinished") {
|
KotlinBuildStatHandler().buildFinished(result.gradle, beanName, sessionLogger, result.action, result.failure)
|
||||||
try {
|
instance = null
|
||||||
try {
|
|
||||||
val gradle = result.gradle
|
|
||||||
if (gradle != null) reportGlobalMetrics(gradle)
|
|
||||||
} finally {
|
|
||||||
sessionLogger.finishBuildSession(result.action, result.failure)
|
|
||||||
}
|
|
||||||
} finally {
|
|
||||||
val mbs: MBeanServer = ManagementFactory.getPlatformMBeanServer()
|
|
||||||
if (mbs.isRegistered(beanName)) {
|
|
||||||
mbs.unregisterMBean(beanName)
|
|
||||||
}
|
|
||||||
instance = null
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun report(metric: BooleanMetrics, value: Boolean, subprojectName: String?) {
|
override fun report(metric: BooleanMetrics, value: Boolean, subprojectName: String?) {
|
||||||
runSafe("report metric ${metric.name}") {
|
KotlinBuildStatHandler().report(sessionLogger, metric, value, subprojectName)
|
||||||
sessionLogger.report(metric, value, subprojectName)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun report(metric: NumericalMetrics, value: Long, subprojectName: String?) {
|
override fun report(metric: NumericalMetrics, value: Long, subprojectName: String?) {
|
||||||
runSafe("report metric ${metric.name}") {
|
KotlinBuildStatHandler().report(sessionLogger, metric, value, subprojectName)
|
||||||
sessionLogger.report(metric, value, subprojectName)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun report(metric: StringMetrics, value: String, subprojectName: String?) {
|
override fun report(metric: StringMetrics, value: String, subprojectName: String?) {
|
||||||
runSafe("report metric ${metric.name}") {
|
KotlinBuildStatHandler().report(sessionLogger, metric, value, subprojectName)
|
||||||
sessionLogger.report(metric, value, subprojectName)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun reportBoolean(name: String, value: Boolean, subprojectName: String?) {
|
override fun reportBoolean(name: String, value: Boolean, subprojectName: String?) {
|
||||||
|
|||||||
+7
-92
@@ -16,11 +16,10 @@ import org.jetbrains.kotlin.gradle.logging.kotlinDebug
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
|
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
|
||||||
import org.jetbrains.kotlin.gradle.plugin.internal.state.TaskExecutionResults
|
import org.jetbrains.kotlin.gradle.plugin.internal.state.TaskExecutionResults
|
||||||
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile
|
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.isConfigurationCacheAvailable
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.lang.StringBuilder
|
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.math.max
|
|
||||||
|
|
||||||
internal fun configureBuildReporter(gradle: Gradle, log: Logger) {
|
internal fun configureBuildReporter(gradle: Gradle, log: Logger) {
|
||||||
val rootProject = gradle.rootProject
|
val rootProject = gradle.rootProject
|
||||||
@@ -40,8 +39,11 @@ internal fun configureBuildReporter(gradle: Gradle, log: Logger) {
|
|||||||
val ts = SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(Calendar.getInstance().time)
|
val ts = SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(Calendar.getInstance().time)
|
||||||
|
|
||||||
val perfReportFile = perfLogDir.resolve("${gradle.rootProject.name}-build-$ts.txt")
|
val perfReportFile = perfLogDir.resolve("${gradle.rootProject.name}-build-$ts.txt")
|
||||||
val reporter = KotlinBuildReporter(gradle, perfReportFile)
|
|
||||||
gradle.addBuildListener(reporter)
|
if (!isConfigurationCacheAvailable(gradle)) {
|
||||||
|
val reporter = KotlinBuildReporter(gradle, perfReportFile)
|
||||||
|
gradle.addBuildListener(reporter)
|
||||||
|
}
|
||||||
|
|
||||||
val buildReportMode = if (properties.buildReportVerbose) BuildReportMode.VERBOSE else BuildReportMode.SIMPLE
|
val buildReportMode = if (properties.buildReportVerbose) BuildReportMode.VERBOSE else BuildReportMode.SIMPLE
|
||||||
|
|
||||||
@@ -112,94 +114,7 @@ internal class KotlinBuildReporter(
|
|||||||
|
|
||||||
@Synchronized
|
@Synchronized
|
||||||
override fun buildFinished(result: BuildResult) {
|
override fun buildFinished(result: BuildResult) {
|
||||||
val logger = result.gradle?.rootProject?.logger
|
KotlinBuildReporterHandler().buildFinished(gradle, perfReportFile, kotlinTaskTimeNs.mapKeys{it.key.path}, allTasksTimeNs, result.failure)
|
||||||
try {
|
|
||||||
perfReportFile.writeText(buildInfo(result) + taskOverview() + tasksSb.toString())
|
|
||||||
logger?.lifecycle("Kotlin build report is written to ${perfReportFile.canonicalPath}")
|
|
||||||
} catch (e: Throwable) {
|
|
||||||
logger?.error("Could not write Kotlin build report to ${perfReportFile.canonicalPath}", e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun buildInfo(result: BuildResult): String {
|
|
||||||
val startParams = arrayListOf<String>()
|
|
||||||
gradle.startParameter.apply {
|
|
||||||
startParams.add("tasks = ${taskRequests.joinToString { it.args.toString() }}")
|
|
||||||
startParams.add("excluded tasks = $excludedTaskNames")
|
|
||||||
startParams.add("current dir = $currentDir")
|
|
||||||
startParams.add("project properties args = $projectProperties")
|
|
||||||
startParams.add("system properties args = $systemPropertiesArgs")
|
|
||||||
}
|
|
||||||
|
|
||||||
return buildString {
|
|
||||||
appendln("Gradle start parameters:")
|
|
||||||
startParams.forEach {
|
|
||||||
appendln(" $it")
|
|
||||||
}
|
|
||||||
if (result.failure != null) {
|
|
||||||
appendln("Build failed: ${result.failure}")
|
|
||||||
}
|
|
||||||
appendln()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun taskOverview(): String {
|
|
||||||
if (kotlinTaskTimeNs.isEmpty()) return buildString { appendln("No Kotlin task was run") }
|
|
||||||
|
|
||||||
val sb = StringBuilder()
|
|
||||||
val kotlinTotalTimeNs = kotlinTaskTimeNs.values.sum()
|
|
||||||
val ktTaskPercent = (kotlinTotalTimeNs.toDouble() / allTasksTimeNs * 100).asString(1)
|
|
||||||
|
|
||||||
sb.appendln("Total time for Kotlin tasks: ${formatTime(kotlinTotalTimeNs)} ($ktTaskPercent % of all tasks time)")
|
|
||||||
|
|
||||||
val table = TextTable("Time", "% of Kotlin time", "Task")
|
|
||||||
kotlinTaskTimeNs.entries
|
|
||||||
.sortedByDescending { (_, timeNs) -> timeNs }
|
|
||||||
.forEach { (task, timeNs) ->
|
|
||||||
val percent = (timeNs.toDouble() / kotlinTotalTimeNs * 100).asString(1)
|
|
||||||
table.addRow(formatTime(timeNs), "$percent %", task.path)
|
|
||||||
}
|
|
||||||
table.printTo(sb)
|
|
||||||
sb.appendln()
|
|
||||||
return sb.toString()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun formatTime(ns: Long): String {
|
|
||||||
val seconds = ns.toDouble() / 1_000_000_000
|
|
||||||
return seconds.asString(2) + " s"
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun Double.asString(decPoints: Int): String =
|
|
||||||
String.format("%.${decPoints}f", this)
|
|
||||||
|
|
||||||
private class TextTable(vararg columnNames: String) {
|
|
||||||
private val rows = ArrayList<List<String>>()
|
|
||||||
private val columnsCount = columnNames.size
|
|
||||||
private val maxLengths = IntArray(columnsCount) { columnNames[it].length }
|
|
||||||
|
|
||||||
init {
|
|
||||||
rows.add(columnNames.toList())
|
|
||||||
}
|
|
||||||
|
|
||||||
fun addRow(vararg row: String) {
|
|
||||||
check(row.size == columnsCount) { "Row size ${row.size} differs from columns count $columnsCount" }
|
|
||||||
rows.add(row.toList())
|
|
||||||
|
|
||||||
for ((i, col) in row.withIndex()) {
|
|
||||||
maxLengths[i] = max(maxLengths[i], col.length)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun printTo(sb: StringBuilder) {
|
|
||||||
for (row in rows) {
|
|
||||||
sb.appendln()
|
|
||||||
for ((i, col) in row.withIndex()) {
|
|
||||||
if (i > 0) sb.append("|")
|
|
||||||
|
|
||||||
sb.append(col.padEnd(maxLengths[i], ' '))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+110
@@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.gradle.report
|
||||||
|
|
||||||
|
import org.gradle.api.invocation.Gradle
|
||||||
|
import java.io.File
|
||||||
|
import java.util.*
|
||||||
|
import kotlin.math.max
|
||||||
|
|
||||||
|
class KotlinBuildReporterHandler {
|
||||||
|
fun buildFinished(
|
||||||
|
gradle: Gradle,
|
||||||
|
perfReportFile: File,
|
||||||
|
kotlinTaskTimeNs: Map<String, Long>,
|
||||||
|
allTasksTimeNs: Long,
|
||||||
|
failure: Throwable? = null
|
||||||
|
) {
|
||||||
|
val logger = gradle.rootProject.logger
|
||||||
|
try {
|
||||||
|
perfReportFile.writeText(buildInfo(gradle, failure) + taskOverview(kotlinTaskTimeNs, allTasksTimeNs))
|
||||||
|
logger.lifecycle("Kotlin build report is written to ${perfReportFile.canonicalPath}")
|
||||||
|
} catch (e: Throwable) {
|
||||||
|
logger.error("Could not write Kotlin build report to ${perfReportFile.canonicalPath}", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun buildInfo(gradle: Gradle, failure: Throwable?): String {
|
||||||
|
val startParams = arrayListOf<String>()
|
||||||
|
gradle.startParameter.apply {
|
||||||
|
startParams.add("tasks = ${taskRequests.joinToString { it.args.toString() }}")
|
||||||
|
startParams.add("excluded tasks = $excludedTaskNames")
|
||||||
|
startParams.add("current dir = $currentDir")
|
||||||
|
startParams.add("project properties args = $projectProperties")
|
||||||
|
startParams.add("system properties args = $systemPropertiesArgs")
|
||||||
|
}
|
||||||
|
|
||||||
|
return buildString {
|
||||||
|
appendln("Gradle start parameters:")
|
||||||
|
startParams.forEach {
|
||||||
|
appendln(" $it")
|
||||||
|
}
|
||||||
|
if (failure != null) {
|
||||||
|
appendln("Build failed: ${failure}")
|
||||||
|
}
|
||||||
|
appendln()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun taskOverview(kotlinTaskTimeNs: Map<String, Long>, allTasksTimeNs: Long): String {
|
||||||
|
if (kotlinTaskTimeNs.isEmpty()) return buildString { appendln("No Kotlin task was run") }
|
||||||
|
|
||||||
|
val sb = StringBuilder()
|
||||||
|
val kotlinTotalTimeNs = kotlinTaskTimeNs.values.sum()
|
||||||
|
val ktTaskPercent = (kotlinTotalTimeNs.toDouble() / allTasksTimeNs * 100).asString(1)
|
||||||
|
|
||||||
|
sb.appendln("Total time for Kotlin tasks: ${formatTime(kotlinTotalTimeNs)} ($ktTaskPercent % of all tasks time)")
|
||||||
|
|
||||||
|
val table = TextTable("Time", "% of Kotlin time", "Task")
|
||||||
|
kotlinTaskTimeNs.entries
|
||||||
|
.sortedByDescending { (_, timeNs) -> timeNs }
|
||||||
|
.forEach { (taskPath, timeNs) ->
|
||||||
|
val percent = (timeNs.toDouble() / kotlinTotalTimeNs * 100).asString(1)
|
||||||
|
table.addRow(formatTime(timeNs), "$percent %", taskPath)
|
||||||
|
}
|
||||||
|
table.printTo(sb)
|
||||||
|
sb.appendln()
|
||||||
|
return sb.toString()
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class TextTable(vararg columnNames: String) {
|
||||||
|
private val rows = ArrayList<List<String>>()
|
||||||
|
private val columnsCount = columnNames.size
|
||||||
|
private val maxLengths = IntArray(columnsCount) { columnNames[it].length }
|
||||||
|
|
||||||
|
init {
|
||||||
|
rows.add(columnNames.toList())
|
||||||
|
}
|
||||||
|
|
||||||
|
fun addRow(vararg row: String) {
|
||||||
|
check(row.size == columnsCount) { "Row size ${row.size} differs from columns count $columnsCount" }
|
||||||
|
rows.add(row.toList())
|
||||||
|
|
||||||
|
for ((i, col) in row.withIndex()) {
|
||||||
|
maxLengths[i] = max(maxLengths[i], col.length)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun printTo(sb: StringBuilder) {
|
||||||
|
for (row in rows) {
|
||||||
|
sb.appendln()
|
||||||
|
for ((i, col) in row.withIndex()) {
|
||||||
|
if (i > 0) sb.append("|")
|
||||||
|
|
||||||
|
sb.append(col.padEnd(maxLengths[i], ' '))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun formatTime(ns: Long): String {
|
||||||
|
val seconds = ns.toDouble() / 1_000_000_000
|
||||||
|
return seconds.asString(2) + " s"
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun Double.asString(decPoints: Int): String =
|
||||||
|
String.format("%.${decPoints}f", this)
|
||||||
+34
@@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.gradle.report
|
||||||
|
|
||||||
|
import com.intellij.util.text.DateFormatUtil.formatTime
|
||||||
|
import org.gradle.api.invocation.Gradle
|
||||||
|
import org.gradle.tooling.events.FinishEvent
|
||||||
|
import org.gradle.tooling.events.OperationCompletionListener
|
||||||
|
import org.gradle.tooling.events.task.TaskOperationDescriptor
|
||||||
|
import java.io.File
|
||||||
|
import java.util.*
|
||||||
|
|
||||||
|
class KotlinBuildReporterListener(val gradle: Gradle, val perfReportFile: File) : OperationCompletionListener, AutoCloseable {
|
||||||
|
|
||||||
|
private val kotlinTaskTimeNs = HashMap<String, Long>()
|
||||||
|
internal var allTasksTimeNs: Long = 0L
|
||||||
|
|
||||||
|
override fun onFinish(event: FinishEvent?) {
|
||||||
|
val descriptor = event?.descriptor
|
||||||
|
if (descriptor is TaskOperationDescriptor) {
|
||||||
|
val taskPath = descriptor.taskPath
|
||||||
|
val executionTime = event.result.endTime - event.result.startTime
|
||||||
|
allTasksTimeNs += executionTime
|
||||||
|
kotlinTaskTimeNs[taskPath] = executionTime
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun close() {
|
||||||
|
KotlinBuildReporterHandler().buildFinished(gradle, perfReportFile, kotlinTaskTimeNs, allTasksTimeNs)
|
||||||
|
}
|
||||||
|
}
|
||||||
+2
-1
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.gradle.targets.js.ir
|
|||||||
import org.gradle.api.tasks.CacheableTask
|
import org.gradle.api.tasks.CacheableTask
|
||||||
import org.gradle.workers.WorkerExecutor
|
import org.gradle.workers.WorkerExecutor
|
||||||
import org.jetbrains.kotlin.compilerRunner.GradleCompilerRunnerWithWorkers
|
import org.jetbrains.kotlin.compilerRunner.GradleCompilerRunnerWithWorkers
|
||||||
|
import org.jetbrains.kotlin.gradle.tasks.GradleCompileTaskProvider
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@CacheableTask
|
@CacheableTask
|
||||||
@@ -16,5 +17,5 @@ internal open class KotlinJsIrLinkWithWorkers
|
|||||||
constructor(
|
constructor(
|
||||||
private val workerExecutor: WorkerExecutor
|
private val workerExecutor: WorkerExecutor
|
||||||
) : KotlinJsIrLink() {
|
) : KotlinJsIrLink() {
|
||||||
override fun compilerRunner() = GradleCompilerRunnerWithWorkers(this, workerExecutor)
|
override fun compilerRunner() = GradleCompilerRunnerWithWorkers(GradleCompileTaskProvider(this), workerExecutor)
|
||||||
}
|
}
|
||||||
+6
-3
@@ -10,6 +10,7 @@ import org.gradle.api.NamedDomainObjectContainer
|
|||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.artifacts.Dependency
|
import org.gradle.api.artifacts.Dependency
|
||||||
import org.gradle.api.plugins.JavaPlugin
|
import org.gradle.api.plugins.JavaPlugin
|
||||||
|
import org.gradle.api.provider.Provider
|
||||||
import org.gradle.jvm.tasks.Jar
|
import org.gradle.jvm.tasks.Jar
|
||||||
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
|
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
|
||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
|
import org.jetbrains.kotlin.gradle.plugin.KotlinPlatformType
|
||||||
@@ -44,10 +45,12 @@ open class KotlinWithJavaTarget<KotlinOptionsType : KotlinCommonOptions>(
|
|||||||
KotlinWithJavaCompilationFactory(project, this, kotlinOptionsFactory)
|
KotlinWithJavaCompilationFactory(project, this, kotlinOptionsFactory)
|
||||||
)
|
)
|
||||||
|
|
||||||
internal val defaultArtifactClassesListFile: File
|
private val layout = project.layout
|
||||||
get() {
|
|
||||||
|
internal val defaultArtifactClassesListFile: Provider<File> =
|
||||||
|
layout.buildDirectory.dir(KOTLIN_BUILD_DIR_NAME).map {
|
||||||
val jarTask = project.tasks.getByName(artifactsTaskName) as Jar
|
val jarTask = project.tasks.getByName(artifactsTaskName) as Jar
|
||||||
return File(File(project.buildDir, KOTLIN_BUILD_DIR_NAME), "${sanitizeFileName(jarTask.archiveFileName.get())}-classes.txt")
|
it.file("${sanitizeFileName(jarTask.archiveFileName.get())}-classes.txt").asFile
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+25
@@ -457,6 +457,31 @@ class KotlinMetadataTargetConfigurator(kotlinPluginVersion: String) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
/*
|
||||||
|
val transformedFilesByOriginalFiles = project.provider {
|
||||||
|
transformationTaskHolders
|
||||||
|
.flatMap { it.get().filesByOriginalFiles.toList() }
|
||||||
|
.groupBy({ it.first }, valueTransform = { it.second })
|
||||||
|
}
|
||||||
|
|
||||||
|
val builtBySet = mutableSetOf<FileCollection>()
|
||||||
|
val resultFiles = project.files(Callable {
|
||||||
|
val originalFiles = fromFiles.toSet()
|
||||||
|
val filesToAdd = mutableSetOf<File>()
|
||||||
|
val filesToExclude = mutableSetOf<File>()
|
||||||
|
|
||||||
|
transformedFilesByOriginalFiles.get().forEach { (original, replacement) ->
|
||||||
|
if (original.all { it in originalFiles }) {
|
||||||
|
builtBySet.addAll(replacement)
|
||||||
|
filesToAdd += replacement.flatMap { it.files }
|
||||||
|
filesToExclude += original
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
originalFiles - filesToExclude + filesToAdd
|
||||||
|
})
|
||||||
|
return resultFiles.builtBy(builtBySet)
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createCommonMainElementsConfiguration(target: KotlinMetadataTarget) {
|
private fun createCommonMainElementsConfiguration(target: KotlinMetadataTarget) {
|
||||||
|
|||||||
-2
@@ -10,9 +10,7 @@ import groovy.lang.Closure
|
|||||||
import org.gradle.api.Action
|
import org.gradle.api.Action
|
||||||
import org.gradle.api.NamedDomainObjectContainer
|
import org.gradle.api.NamedDomainObjectContainer
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.file.ConfigurableFileCollection
|
|
||||||
import org.gradle.api.file.FileCollection
|
import org.gradle.api.file.FileCollection
|
||||||
import org.gradle.api.file.SourceDirectorySet
|
|
||||||
import org.gradle.api.tasks.TaskProvider
|
import org.gradle.api.tasks.TaskProvider
|
||||||
import org.gradle.util.ConfigureUtil
|
import org.gradle.util.ConfigureUtil
|
||||||
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
|
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
|
||||||
|
|||||||
+1
-1
@@ -156,7 +156,7 @@ open class KotlinNativeTargetConfigurator<T : KotlinNativeTarget>(
|
|||||||
val compileTaskProvider = registerTask<KotlinNativeCompile>(
|
val compileTaskProvider = registerTask<KotlinNativeCompile>(
|
||||||
compilation.compileKotlinTaskName
|
compilation.compileKotlinTaskName
|
||||||
) {
|
) {
|
||||||
it.compilation = compilation
|
it.compilation.set(compilation)
|
||||||
it.group = BasePlugin.BUILD_GROUP
|
it.group = BasePlugin.BUILD_GROUP
|
||||||
it.description = "Compiles a klibrary from the '${compilation.name}' " +
|
it.description = "Compiles a klibrary from the '${compilation.name}' " +
|
||||||
"compilation for target '${compilation.platformType.name}'."
|
"compilation for target '${compilation.platformType.name}'."
|
||||||
|
|||||||
+4
-5
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.gradle.targets.native.internal.PlatformLibrariesGene
|
|||||||
import org.jetbrains.kotlin.gradle.targets.native.internal.setUpKotlinNativePlatformDependencies
|
import org.jetbrains.kotlin.gradle.targets.native.internal.setUpKotlinNativePlatformDependencies
|
||||||
import org.jetbrains.kotlin.gradle.utils.NativeCompilerDownloader
|
import org.jetbrains.kotlin.gradle.utils.NativeCompilerDownloader
|
||||||
import org.jetbrains.kotlin.gradle.utils.SingleActionPerProject
|
import org.jetbrains.kotlin.gradle.utils.SingleActionPerProject
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.isConfigurationCacheAvailable
|
||||||
import org.jetbrains.kotlin.konan.CompilerVersion
|
import org.jetbrains.kotlin.konan.CompilerVersion
|
||||||
import org.jetbrains.kotlin.konan.target.HostManager
|
import org.jetbrains.kotlin.konan.target.HostManager
|
||||||
import org.jetbrains.kotlin.konan.target.KonanTarget
|
import org.jetbrains.kotlin.konan.target.KonanTarget
|
||||||
@@ -89,11 +90,9 @@ abstract class AbstractKotlinNativeTargetPreset<T : KotlinNativeTarget>(
|
|||||||
createTargetConfigurator().configureTarget(result)
|
createTargetConfigurator().configureTarget(result)
|
||||||
|
|
||||||
SingleActionPerProject.run(project, "setUpKotlinNativePlatformDependencies") {
|
SingleActionPerProject.run(project, "setUpKotlinNativePlatformDependencies") {
|
||||||
project.gradle.addListener(object : BuildAdapter() {
|
project.gradle.projectsEvaluated {
|
||||||
override fun projectsEvaluated(gradle: Gradle) {
|
project.setUpKotlinNativePlatformDependencies()
|
||||||
project.setUpKotlinNativePlatformDependencies()
|
}
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!konanTarget.enabledOnCurrentHost) {
|
if (!konanTarget.enabledOnCurrentHost) {
|
||||||
|
|||||||
+1
-6
@@ -8,11 +8,9 @@ package org.jetbrains.kotlin.gradle.plugin.cocoapods
|
|||||||
|
|
||||||
import org.gradle.api.Plugin
|
import org.gradle.api.Plugin
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.Task
|
|
||||||
import org.gradle.api.provider.Provider
|
import org.gradle.api.provider.Provider
|
||||||
import org.gradle.api.tasks.Sync
|
import org.gradle.api.tasks.Sync
|
||||||
import org.gradle.api.tasks.TaskProvider
|
import org.gradle.api.tasks.TaskProvider
|
||||||
import org.jetbrains.kotlin.gradle.tasks.registerTask
|
|
||||||
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
|
import org.jetbrains.kotlin.gradle.dsl.KotlinMultiplatformExtension
|
||||||
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
|
import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension
|
||||||
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
|
||||||
@@ -20,10 +18,7 @@ import org.jetbrains.kotlin.gradle.plugin.addExtension
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
|
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget
|
||||||
import org.jetbrains.kotlin.gradle.plugin.whenEvaluated
|
import org.jetbrains.kotlin.gradle.plugin.whenEvaluated
|
||||||
import org.jetbrains.kotlin.gradle.targets.native.tasks.*
|
import org.jetbrains.kotlin.gradle.targets.native.tasks.*
|
||||||
import org.jetbrains.kotlin.gradle.tasks.DefFileTask
|
import org.jetbrains.kotlin.gradle.tasks.*
|
||||||
import org.jetbrains.kotlin.gradle.tasks.DummyFrameworkTask
|
|
||||||
import org.jetbrains.kotlin.gradle.tasks.FatFrameworkTask
|
|
||||||
import org.jetbrains.kotlin.gradle.tasks.PodspecTask
|
|
||||||
import org.jetbrains.kotlin.gradle.utils.asValidTaskName
|
import org.jetbrains.kotlin.gradle.utils.asValidTaskName
|
||||||
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
||||||
import org.jetbrains.kotlin.konan.target.HostManager
|
import org.jetbrains.kotlin.konan.target.HostManager
|
||||||
|
|||||||
+20
-11
@@ -16,8 +16,8 @@ import org.jetbrains.kotlin.gradle.plugin.addExtension
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.disambiguateName
|
import org.jetbrains.kotlin.gradle.plugin.mpp.disambiguateName
|
||||||
import org.jetbrains.kotlin.gradle.targets.native.tasks.NativePerformanceReport
|
import org.jetbrains.kotlin.gradle.targets.native.tasks.NativePerformanceReport
|
||||||
import org.jetbrains.kotlin.gradle.tasks.registerTask
|
import org.jetbrains.kotlin.gradle.tasks.registerTask
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.isConfigurationCacheAvailable
|
||||||
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
|
||||||
import java.io.File
|
|
||||||
import java.util.concurrent.ConcurrentHashMap
|
import java.util.concurrent.ConcurrentHashMap
|
||||||
|
|
||||||
class TaskTime(val startTime: Long) {
|
class TaskTime(val startTime: Long) {
|
||||||
@@ -66,17 +66,26 @@ open class KotlinPerformancePlugin : Plugin<Project> {
|
|||||||
|
|
||||||
private fun configureTasks(project: Project, performanceExtension: PerformanceExtension) {
|
private fun configureTasks(project: Project, performanceExtension: PerformanceExtension) {
|
||||||
// Add time listener.
|
// Add time listener.
|
||||||
val timeListener = TaskTimerListener(project)
|
if (!isConfigurationCacheAvailable(project.gradle)) {
|
||||||
project.gradle.addListener(timeListener)
|
val timeListener = TaskTimerListener(project)
|
||||||
performanceExtension.trackedBinaries.forEach { binary ->
|
project.gradle.addListener(timeListener)
|
||||||
val perfReport = project.registerTask<NativePerformanceReport>(binary.target.disambiguateName(lowerCamelCaseName("perfReport", binary.name))) {
|
performanceExtension.trackedBinaries.forEach { binary ->
|
||||||
it.binary = binary
|
val perfReport = project.registerTask<NativePerformanceReport>(
|
||||||
it.settings = performanceExtension
|
binary.target.disambiguateName(
|
||||||
it.timeListener = timeListener
|
lowerCamelCaseName(
|
||||||
it.group = TASK_GROUP
|
"perfReport",
|
||||||
it.description = "Report performance measurement results for binary '${binary.name}' of target '${binary.target.name}'."
|
binary.name
|
||||||
|
)
|
||||||
|
)
|
||||||
|
) {
|
||||||
|
it.binary = binary
|
||||||
|
it.settings = performanceExtension
|
||||||
|
it.timeListener = timeListener
|
||||||
|
it.group = TASK_GROUP
|
||||||
|
it.description = "Report performance measurement results for binary '${binary.name}' of target '${binary.target.name}'."
|
||||||
|
}
|
||||||
|
binary.linkTaskProvider.configure { linkTask -> linkTask.finalizedBy(perfReport) }
|
||||||
}
|
}
|
||||||
binary.linkTaskProvider.configure { linkTask -> linkTask.finalizedBy(perfReport) }
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+3
-3
@@ -70,15 +70,15 @@ open class NativePerformanceReport : DefaultTask() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getPerformanceCompilerOptions() =
|
private fun getPerformanceCompilerOptions() =
|
||||||
(compilerFlagsFromBinary() + binary.linkTask.compilation.kotlinOptions.freeCompilerArgs)
|
(compilerFlagsFromBinary() + binary.linkTask.compilation.get().kotlinOptions.freeCompilerArgs)
|
||||||
.filter { it in listOf("-g", "-opt", "-Xg0") }.map { "\"$it\"" }
|
.filter { it in listOf("-g", "-opt", "-Xg0") }.map { "\"$it\"" }
|
||||||
|
|
||||||
@TaskAction
|
@TaskAction
|
||||||
fun generate() {
|
fun generate() {
|
||||||
val compileTasks = if (settings.includeAssociatedTasks)
|
val compileTasks = if (settings.includeAssociatedTasks)
|
||||||
getAllExecutedTasks(binary.linkTask.compilation)
|
getAllExecutedTasks(binary.linkTask.compilation.get())
|
||||||
else
|
else
|
||||||
listOf(binary.linkTask.compilation.compileKotlinTask)
|
listOf(binary.linkTask.compilation.get().compileKotlinTask)
|
||||||
val allExecutedTasks = listOf(binary.linkTask) + compileTasks
|
val allExecutedTasks = listOf(binary.linkTask) + compileTasks
|
||||||
val upToDateTasks = allExecutedTasks.filter { it.state.upToDate }.map { it.name }
|
val upToDateTasks = allExecutedTasks.filter { it.state.upToDate }.map { it.name }
|
||||||
if (upToDateTasks.isNotEmpty()) {
|
if (upToDateTasks.isNotEmpty()) {
|
||||||
|
|||||||
+87
-65
@@ -13,8 +13,8 @@ import org.gradle.api.artifacts.*
|
|||||||
import org.gradle.api.file.ConfigurableFileCollection
|
import org.gradle.api.file.ConfigurableFileCollection
|
||||||
import org.gradle.api.file.FileCollection
|
import org.gradle.api.file.FileCollection
|
||||||
import org.gradle.api.file.FileTree
|
import org.gradle.api.file.FileTree
|
||||||
import org.gradle.api.file.SourceDirectorySet
|
|
||||||
import org.gradle.api.logging.Logger
|
import org.gradle.api.logging.Logger
|
||||||
|
import org.gradle.api.provider.Property
|
||||||
import org.gradle.api.provider.Provider
|
import org.gradle.api.provider.Provider
|
||||||
import org.gradle.api.tasks.*
|
import org.gradle.api.tasks.*
|
||||||
import org.gradle.api.tasks.compile.AbstractCompile
|
import org.gradle.api.tasks.compile.AbstractCompile
|
||||||
@@ -26,12 +26,12 @@ import org.jetbrains.kotlin.gradle.dsl.NativeCacheKind
|
|||||||
import org.jetbrains.kotlin.gradle.internal.ensureParentDirsCreated
|
import org.jetbrains.kotlin.gradle.internal.ensureParentDirsCreated
|
||||||
import org.jetbrains.kotlin.gradle.plugin.LanguageSettingsBuilder
|
import org.jetbrains.kotlin.gradle.plugin.LanguageSettingsBuilder
|
||||||
import org.jetbrains.kotlin.gradle.plugin.cocoapods.asValidFrameworkName
|
import org.jetbrains.kotlin.gradle.plugin.cocoapods.asValidFrameworkName
|
||||||
import org.jetbrains.kotlin.gradle.plugin.getKotlinPluginVersion
|
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
import org.jetbrains.kotlin.gradle.plugin.mpp.*
|
||||||
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultLanguageSettingsBuilder
|
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultLanguageSettingsBuilder
|
||||||
import org.jetbrains.kotlin.gradle.targets.native.internal.isAllowCommonizer
|
import org.jetbrains.kotlin.gradle.targets.native.internal.isAllowCommonizer
|
||||||
import org.jetbrains.kotlin.gradle.utils.getValue
|
import org.jetbrains.kotlin.gradle.utils.getValue
|
||||||
import org.jetbrains.kotlin.gradle.utils.klibModuleName
|
import org.jetbrains.kotlin.gradle.utils.klibModuleName
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.newProperty
|
||||||
import org.jetbrains.kotlin.gradle.utils.listFilesOrEmpty
|
import org.jetbrains.kotlin.gradle.utils.listFilesOrEmpty
|
||||||
import org.jetbrains.kotlin.konan.library.KLIB_INTEROP_IR_PROVIDER_IDENTIFIER
|
import org.jetbrains.kotlin.konan.library.KLIB_INTEROP_IR_PROVIDER_IDENTIFIER
|
||||||
import org.jetbrains.kotlin.konan.properties.saveToFile
|
import org.jetbrains.kotlin.konan.properties.saveToFile
|
||||||
@@ -112,7 +112,7 @@ private fun Collection<File>.filterKlibsPassedToCompiler(project: Project) = fil
|
|||||||
}
|
}
|
||||||
|
|
||||||
// endregion
|
// endregion
|
||||||
abstract class AbstractKotlinNativeCompile<T : KotlinCommonToolOptions> : AbstractCompile() {
|
abstract class AbstractKotlinNativeCompile<T : KotlinCommonToolOptions, K : AbstractKotlinNativeCompilation> : AbstractCompile() {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
sourceCompatibility = "1.6"
|
sourceCompatibility = "1.6"
|
||||||
@@ -120,7 +120,7 @@ abstract class AbstractKotlinNativeCompile<T : KotlinCommonToolOptions> : Abstra
|
|||||||
}
|
}
|
||||||
|
|
||||||
@get:Internal
|
@get:Internal
|
||||||
abstract val compilation: AbstractKotlinNativeCompilation
|
abstract val compilation: Provider<K>
|
||||||
|
|
||||||
// region inputs/outputs
|
// region inputs/outputs
|
||||||
@get:Input
|
@get:Input
|
||||||
@@ -136,20 +136,21 @@ abstract class AbstractKotlinNativeCompile<T : KotlinCommonToolOptions> : Abstra
|
|||||||
abstract val baseName: String
|
abstract val baseName: String
|
||||||
|
|
||||||
// Inputs and outputs
|
// Inputs and outputs
|
||||||
val libraries: FileCollection
|
@get:InputFiles
|
||||||
@InputFiles get() =
|
val libraries: FileCollection by project.provider {
|
||||||
// Avoid resolving these dependencies during task graph construction when we can't build the target:
|
// Avoid resolving these dependencies during task graph construction when we can't build the target:
|
||||||
if (compilation.konanTarget.enabledOnCurrentHost)
|
if (compilation.get().konanTarget.enabledOnCurrentHost)
|
||||||
compilation.compileDependencyFiles.filterOutPublishableInteropLibs(project)
|
compilation.get().compileDependencyFiles.filterOutPublishableInteropLibs(project)
|
||||||
else project.files()
|
else project.files()
|
||||||
|
}
|
||||||
|
|
||||||
override fun getClasspath(): FileCollection = libraries
|
override fun getClasspath(): FileCollection = libraries
|
||||||
override fun setClasspath(configuration: FileCollection?) {
|
override fun setClasspath(configuration: FileCollection?) {
|
||||||
throw UnsupportedOperationException("Setting classpath directly is unsupported.")
|
throw UnsupportedOperationException("Setting classpath directly is unsupported.")
|
||||||
}
|
}
|
||||||
|
|
||||||
val target: String
|
@get:Input
|
||||||
@Input get() = compilation.konanTarget.name
|
val target: String by project.provider { compilation.get().konanTarget.name }
|
||||||
|
|
||||||
// region Compiler options.
|
// region Compiler options.
|
||||||
@get:Internal
|
@get:Internal
|
||||||
@@ -158,11 +159,12 @@ abstract class AbstractKotlinNativeCompile<T : KotlinCommonToolOptions> : Abstra
|
|||||||
abstract fun kotlinOptions(fn: Closure<*>)
|
abstract fun kotlinOptions(fn: Closure<*>)
|
||||||
|
|
||||||
@get:Input
|
@get:Input
|
||||||
abstract val additionalCompilerOptions: Collection<String>
|
abstract val additionalCompilerOptions: Provider<Collection<String>>
|
||||||
|
|
||||||
@get:Internal
|
@get:Internal
|
||||||
val languageSettings: LanguageSettingsBuilder
|
val languageSettings: LanguageSettingsBuilder by lazy {
|
||||||
get() = compilation.defaultSourceSet.languageSettings
|
compilation.get().defaultSourceSet.languageSettings
|
||||||
|
}
|
||||||
|
|
||||||
@get:Input
|
@get:Input
|
||||||
val progressiveMode: Boolean
|
val progressiveMode: Boolean
|
||||||
@@ -170,8 +172,8 @@ abstract class AbstractKotlinNativeCompile<T : KotlinCommonToolOptions> : Abstra
|
|||||||
// endregion.
|
// endregion.
|
||||||
|
|
||||||
@get:Input
|
@get:Input
|
||||||
val enableEndorsedLibs: Boolean
|
val enableEndorsedLibs by
|
||||||
get() = compilation.enableEndorsedLibs
|
project.provider { compilation.map { it.enableEndorsedLibs }.get() }
|
||||||
|
|
||||||
val kotlinNativeVersion: String
|
val kotlinNativeVersion: String
|
||||||
@Input get() = project.konanVersion.toString()
|
@Input get() = project.konanVersion.toString()
|
||||||
@@ -179,11 +181,11 @@ abstract class AbstractKotlinNativeCompile<T : KotlinCommonToolOptions> : Abstra
|
|||||||
// OutputFile is located under the destinationDir, so there is no need to register it as a separate output.
|
// OutputFile is located under the destinationDir, so there is no need to register it as a separate output.
|
||||||
@Internal
|
@Internal
|
||||||
val outputFile: Provider<File> = project.provider {
|
val outputFile: Provider<File> = project.provider {
|
||||||
val konanTarget = compilation.konanTarget
|
val konanTarget = compilation.get().konanTarget
|
||||||
|
|
||||||
val prefix = outputKind.prefix(konanTarget)
|
val prefix = outputKind.prefix(konanTarget)
|
||||||
val suffix = outputKind.suffix(konanTarget)
|
val suffix = outputKind.suffix(konanTarget)
|
||||||
val filename = "$prefix$baseName$suffix".let {
|
val filename = "$prefix${baseName}$suffix".let {
|
||||||
when {
|
when {
|
||||||
outputKind == FRAMEWORK ->
|
outputKind == FRAMEWORK ->
|
||||||
it.asValidFrameworkName()
|
it.asValidFrameworkName()
|
||||||
@@ -241,10 +243,10 @@ abstract class AbstractKotlinNativeCompile<T : KotlinCommonToolOptions> : Abstra
|
|||||||
addKey("-progressive", progressiveMode)
|
addKey("-progressive", progressiveMode)
|
||||||
|
|
||||||
if (!defaultsOnly) {
|
if (!defaultsOnly) {
|
||||||
addAll(additionalCompilerOptions)
|
addAll(additionalCompilerOptions.get())
|
||||||
}
|
}
|
||||||
|
|
||||||
(compilation.defaultSourceSet.languageSettings as? DefaultLanguageSettingsBuilder)?.run {
|
(compilation.get().defaultSourceSet.languageSettings as? DefaultLanguageSettingsBuilder)?.run {
|
||||||
addAll(freeCompilerArgs)
|
addAll(freeCompilerArgs)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -274,7 +276,7 @@ abstract class AbstractKotlinNativeCompile<T : KotlinCommonToolOptions> : Abstra
|
|||||||
addArg("-target", target)
|
addArg("-target", target)
|
||||||
addArg("-p", outputKind.name.toLowerCase())
|
addArg("-p", outputKind.name.toLowerCase())
|
||||||
|
|
||||||
if (compilation is KotlinSharedNativeCompilation) {
|
if (compilation.get() is KotlinSharedNativeCompilation) {
|
||||||
add("-Xexpect-actual-linker")
|
add("-Xexpect-actual-linker")
|
||||||
add("-Xmetadata-klib")
|
add("-Xmetadata-klib")
|
||||||
addArg("-manifest", manifestFile.get().absolutePath)
|
addArg("-manifest", manifestFile.get().absolutePath)
|
||||||
@@ -301,7 +303,7 @@ abstract class AbstractKotlinNativeCompile<T : KotlinCommonToolOptions> : Abstra
|
|||||||
val output = outputFile.get()
|
val output = outputFile.get()
|
||||||
output.parentFile.mkdirs()
|
output.parentFile.mkdirs()
|
||||||
|
|
||||||
if (compilation is KotlinSharedNativeCompilation) {
|
if (compilation.get() is KotlinSharedNativeCompilation) {
|
||||||
val manifestFile: File = manifestFile.get()
|
val manifestFile: File = manifestFile.get()
|
||||||
manifestFile.ensureParentDirsCreated()
|
manifestFile.ensureParentDirsCreated()
|
||||||
val properties = java.util.Properties()
|
val properties = java.util.Properties()
|
||||||
@@ -316,9 +318,12 @@ abstract class AbstractKotlinNativeCompile<T : KotlinCommonToolOptions> : Abstra
|
|||||||
/**
|
/**
|
||||||
* A task producing a klibrary from a compilation.
|
* A task producing a klibrary from a compilation.
|
||||||
*/
|
*/
|
||||||
open class KotlinNativeCompile : AbstractKotlinNativeCompile<KotlinCommonOptions>(), KotlinCompile<KotlinCommonOptions> {
|
open class KotlinNativeCompile : AbstractKotlinNativeCompile<KotlinCommonOptions, AbstractKotlinNativeCompilation>(),
|
||||||
|
KotlinCompile<KotlinCommonOptions> {
|
||||||
@Internal
|
@Internal
|
||||||
final override lateinit var compilation: AbstractKotlinNativeCompilation
|
@Transient // can't be serialized for Gradle configuration avoidance
|
||||||
|
final override val compilation: Property<AbstractKotlinNativeCompilation> =
|
||||||
|
project.newProperty()
|
||||||
|
|
||||||
@get:Input
|
@get:Input
|
||||||
override val outputKind = LIBRARY
|
override val outputKind = LIBRARY
|
||||||
@@ -330,8 +335,11 @@ open class KotlinNativeCompile : AbstractKotlinNativeCompile<KotlinCommonOptions
|
|||||||
override val debuggable = true
|
override val debuggable = true
|
||||||
|
|
||||||
@get:Internal
|
@get:Internal
|
||||||
override val baseName: String
|
override val baseName: String by
|
||||||
get() = if (compilation.isMain()) project.name else "${project.name}_${compilation.name}"
|
compilation.map { if (it.isMain()) project.name else "${project.name}_${it.name}" }
|
||||||
|
|
||||||
|
// Store as an explicit provider in order to allow Gradle Instant Execution to capture the state
|
||||||
|
// private val allSourceProvider = compilation.map { project.files(it.allSources).asFileTree }
|
||||||
|
|
||||||
@get:Input
|
@get:Input
|
||||||
val moduleName: String by project.provider {
|
val moduleName: String by project.provider {
|
||||||
@@ -347,13 +355,21 @@ open class KotlinNativeCompile : AbstractKotlinNativeCompile<KotlinCommonOptions
|
|||||||
@get:Internal // these sources are normally a subset of `source` ones which are already tracked
|
@get:Internal // these sources are normally a subset of `source` ones which are already tracked
|
||||||
val commonSources: ConfigurableFileCollection = project.files()
|
val commonSources: ConfigurableFileCollection = project.files()
|
||||||
|
|
||||||
|
// private val commonSources: FileCollection by lazy {
|
||||||
|
// // Already taken into account in getSources method.
|
||||||
|
// project.files(compilation.map { it.commonSources }).asFileTree
|
||||||
|
// }
|
||||||
|
|
||||||
private val commonSourcesTree: FileTree
|
private val commonSourcesTree: FileTree
|
||||||
get() = commonSources.asFileTree
|
get() = commonSources.asFileTree
|
||||||
|
|
||||||
private val friendModule: FileCollection?
|
|
||||||
get() = project.files(
|
private val friendModule: FileCollection by compilation.map { compilationInstance ->
|
||||||
project.provider { compilation.associateWithTransitiveClosure.map { it.output.allOutputs } + compilation.friendArtifacts }
|
project.files(
|
||||||
|
compilationInstance.associateWithTransitiveClosure.map { it.output.allOutputs },
|
||||||
|
compilationInstance.friendArtifacts
|
||||||
)
|
)
|
||||||
|
}
|
||||||
// endregion.
|
// endregion.
|
||||||
|
|
||||||
// region Language settings imported from a SourceSet.
|
// region Language settings imported from a SourceSet.
|
||||||
@@ -372,11 +388,12 @@ open class KotlinNativeCompile : AbstractKotlinNativeCompile<KotlinCommonOptions
|
|||||||
|
|
||||||
// region Kotlin options.
|
// region Kotlin options.
|
||||||
override val kotlinOptions: KotlinCommonOptions
|
override val kotlinOptions: KotlinCommonOptions
|
||||||
get() = compilation.kotlinOptions
|
get() = compilation.get().kotlinOptions
|
||||||
|
|
||||||
@get:Input
|
@get:Input
|
||||||
override val additionalCompilerOptions: Collection<String>
|
override val additionalCompilerOptions: Provider<Collection<String>> = project.provider {
|
||||||
get() = kotlinOptions.freeCompilerArgs
|
kotlinOptions.freeCompilerArgs
|
||||||
|
}
|
||||||
|
|
||||||
override fun kotlinOptions(fn: KotlinCommonOptions.() -> Unit) {
|
override fun kotlinOptions(fn: KotlinCommonOptions.() -> Unit) {
|
||||||
kotlinOptions.fn()
|
kotlinOptions.fn()
|
||||||
@@ -409,7 +426,7 @@ open class KotlinNativeCompile : AbstractKotlinNativeCompile<KotlinCommonOptions
|
|||||||
// Configure FQ module name to avoid cyclic dependencies in klib manifests (see KT-36721).
|
// Configure FQ module name to avoid cyclic dependencies in klib manifests (see KT-36721).
|
||||||
addArg("-module-name", moduleName)
|
addArg("-module-name", moduleName)
|
||||||
add("-Xshort-module-name=$shortModuleName")
|
add("-Xshort-module-name=$shortModuleName")
|
||||||
val friends = friendModule?.files
|
val friends = friendModule.files
|
||||||
if (friends != null && friends.isNotEmpty()) {
|
if (friends != null && friends.isNotEmpty()) {
|
||||||
addArg("-friend-modules", friends.map { it.absolutePath }.joinToString(File.pathSeparator))
|
addArg("-friend-modules", friends.map { it.absolutePath }.joinToString(File.pathSeparator))
|
||||||
}
|
}
|
||||||
@@ -427,22 +444,23 @@ open class KotlinNativeCompile : AbstractKotlinNativeCompile<KotlinCommonOptions
|
|||||||
/**
|
/**
|
||||||
* A task producing a final binary from a compilation.
|
* A task producing a final binary from a compilation.
|
||||||
*/
|
*/
|
||||||
open class KotlinNativeLink : AbstractKotlinNativeCompile<KotlinCommonToolOptions>() {
|
open class KotlinNativeLink : AbstractKotlinNativeCompile<KotlinCommonToolOptions, KotlinNativeCompilation>() {
|
||||||
|
|
||||||
|
@get:Internal
|
||||||
|
@Transient // can't be serialized for Gradle configuration avoidance
|
||||||
|
final override val compilation: Property<KotlinNativeCompilation> = project.newProperty() { binary.compilation }
|
||||||
|
|
||||||
init {
|
init {
|
||||||
dependsOn(project.provider { compilation.compileKotlinTask })
|
dependsOn(project.provider { compilation.get().compileKotlinTask })
|
||||||
}
|
}
|
||||||
|
|
||||||
@Internal
|
@Internal
|
||||||
|
@Transient
|
||||||
lateinit var binary: NativeBinary
|
lateinit var binary: NativeBinary
|
||||||
|
|
||||||
@get:Internal
|
|
||||||
override val compilation: KotlinNativeCompilation
|
|
||||||
get() = binary.compilation
|
|
||||||
|
|
||||||
@Internal // Taken into account by getSources().
|
@Internal // Taken into account by getSources().
|
||||||
val intermediateLibrary: Provider<File> = project.provider {
|
val intermediateLibrary: Provider<File> = compilation.map { compilationInstance ->
|
||||||
compilation.compileKotlinTask.outputFile.get()
|
compilationInstance.compileKotlinTask.outputFile.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
@InputFiles
|
@InputFiles
|
||||||
@@ -459,27 +477,23 @@ open class KotlinNativeLink : AbstractKotlinNativeCompile<KotlinCommonToolOption
|
|||||||
binary.outputDirectory = destinationDir
|
binary.outputDirectory = destinationDir
|
||||||
}
|
}
|
||||||
|
|
||||||
@get:Input
|
|
||||||
override val outputKind: CompilerOutputKind
|
override val outputKind: CompilerOutputKind
|
||||||
get() = binary.outputKind.compilerOutputKind
|
@Input get() = binary.outputKind.compilerOutputKind
|
||||||
|
|
||||||
@get:Input
|
|
||||||
override val optimized: Boolean
|
override val optimized: Boolean
|
||||||
get() = binary.optimized
|
@Input get() = binary.optimized
|
||||||
|
|
||||||
@get:Input
|
|
||||||
override val debuggable: Boolean
|
override val debuggable: Boolean
|
||||||
get() = binary.debuggable
|
@Input get() = binary.debuggable
|
||||||
|
|
||||||
@get:Internal
|
|
||||||
override val baseName: String
|
override val baseName: String
|
||||||
get() = binary.baseName
|
@Input get() = binary.baseName
|
||||||
|
|
||||||
@get:Input
|
@get:Input
|
||||||
protected val konanCacheKind: NativeCacheKind
|
protected val konanCacheKind: NativeCacheKind
|
||||||
get() = project.konanCacheKind
|
get() = project.konanCacheKind
|
||||||
|
|
||||||
inner class NativeLinkOptions: KotlinCommonToolOptions {
|
inner class NativeLinkOptions : KotlinCommonToolOptions {
|
||||||
override var allWarningsAsErrors: Boolean = false
|
override var allWarningsAsErrors: Boolean = false
|
||||||
override var suppressWarnings: Boolean = false
|
override var suppressWarnings: Boolean = false
|
||||||
override var verbose: Boolean = false
|
override var verbose: Boolean = false
|
||||||
@@ -488,8 +502,9 @@ open class KotlinNativeLink : AbstractKotlinNativeCompile<KotlinCommonToolOption
|
|||||||
|
|
||||||
// We propagate compilation free args to the link task for now (see KT-33717).
|
// We propagate compilation free args to the link task for now (see KT-33717).
|
||||||
@get:Input
|
@get:Input
|
||||||
override val additionalCompilerOptions: Collection<String>
|
override val additionalCompilerOptions: Provider<Collection<String>> = compilation.map { compilationInstance ->
|
||||||
get() = kotlinOptions.freeCompilerArgs + compilation.kotlinOptions.freeCompilerArgs
|
kotlinOptions.freeCompilerArgs + compilationInstance.kotlinOptions.freeCompilerArgs
|
||||||
|
}
|
||||||
|
|
||||||
override val kotlinOptions: KotlinCommonToolOptions = NativeLinkOptions()
|
override val kotlinOptions: KotlinCommonToolOptions = NativeLinkOptions()
|
||||||
|
|
||||||
@@ -503,18 +518,16 @@ open class KotlinNativeLink : AbstractKotlinNativeCompile<KotlinCommonToolOption
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Binary-specific options.
|
// Binary-specific options.
|
||||||
@get:Optional
|
|
||||||
@get:Input
|
|
||||||
val entryPoint: String?
|
val entryPoint: String?
|
||||||
|
@Input
|
||||||
|
@Optional
|
||||||
get() = (binary as? Executable)?.entryPoint
|
get() = (binary as? Executable)?.entryPoint
|
||||||
|
|
||||||
@get:Input
|
|
||||||
val linkerOpts: List<String>
|
val linkerOpts: List<String>
|
||||||
get() = binary.linkerOpts
|
@Input get() = binary.linkerOpts
|
||||||
|
|
||||||
@get:Input
|
|
||||||
val processTests: Boolean
|
val processTests: Boolean
|
||||||
get() = binary is TestExecutable
|
@Input get() = binary is TestExecutable
|
||||||
|
|
||||||
@get:InputFiles
|
@get:InputFiles
|
||||||
val exportLibraries: FileCollection
|
val exportLibraries: FileCollection
|
||||||
@@ -527,12 +540,14 @@ open class KotlinNativeLink : AbstractKotlinNativeCompile<KotlinCommonToolOption
|
|||||||
}
|
}
|
||||||
|
|
||||||
@get:Input
|
@get:Input
|
||||||
val isStaticFramework: Boolean
|
val isStaticFramework: Boolean by project.provider {
|
||||||
get() = binary.let { it is Framework && it.isStatic }
|
binary.let { it is Framework && it.isStatic }
|
||||||
|
}
|
||||||
|
|
||||||
@get:Input
|
@get:Input
|
||||||
val embedBitcode: Framework.BitcodeEmbeddingMode
|
val embedBitcode: Framework.BitcodeEmbeddingMode by project.provider {
|
||||||
get() = (binary as? Framework)?.embedBitcode ?: Framework.BitcodeEmbeddingMode.DISABLE
|
(binary as? Framework)?.embedBitcode ?: Framework.BitcodeEmbeddingMode.DISABLE
|
||||||
|
}
|
||||||
|
|
||||||
override fun buildCompilerArgs(): List<String> = mutableListOf<String>().apply {
|
override fun buildCompilerArgs(): List<String> = mutableListOf<String>().apply {
|
||||||
addAll(super.buildCompilerArgs())
|
addAll(super.buildCompilerArgs())
|
||||||
@@ -569,9 +584,12 @@ open class KotlinNativeLink : AbstractKotlinNativeCompile<KotlinCommonToolOption
|
|||||||
override fun buildSourceArgs(): List<String> =
|
override fun buildSourceArgs(): List<String> =
|
||||||
listOf("-Xinclude=${intermediateLibrary.get().absolutePath}")
|
listOf("-Xinclude=${intermediateLibrary.get().absolutePath}")
|
||||||
|
|
||||||
|
@get:Internal
|
||||||
|
val apiFilesProvider = compilation.map {project.configurations.getByName(it.apiConfigurationName).files.filterKlibsPassedToCompiler(project)}
|
||||||
|
|
||||||
private fun validatedExportedLibraries() {
|
private fun validatedExportedLibraries() {
|
||||||
val exportConfiguration = exportLibraries as? Configuration ?: return
|
val exportConfiguration = exportLibraries as? Configuration ?: return
|
||||||
val apiFiles = project.configurations.getByName(compilation.apiConfigurationName).files.filterKlibsPassedToCompiler(project)
|
val apiFiles = apiFilesProvider.get()
|
||||||
|
|
||||||
val failed = mutableSetOf<Dependency>()
|
val failed = mutableSetOf<Dependency>()
|
||||||
exportConfiguration.allDependencies.forEach {
|
exportConfiguration.allDependencies.forEach {
|
||||||
@@ -765,7 +783,11 @@ internal class CacheBuilder(val project: Project, val binary: NativeBinary) {
|
|||||||
private val String.cachedName
|
private val String.cachedName
|
||||||
get() = getCacheFileName(this, konanCacheKind)
|
get() = getCacheFileName(this, konanCacheKind)
|
||||||
|
|
||||||
private fun ensureCompilerProvidedLibPrecached(platformLibName: String, platformLibs: Map<String, File>, visitedLibs: MutableSet<String>) {
|
private fun ensureCompilerProvidedLibPrecached(
|
||||||
|
platformLibName: String,
|
||||||
|
platformLibs: Map<String, File>,
|
||||||
|
visitedLibs: MutableSet<String>
|
||||||
|
) {
|
||||||
if (platformLibName in visitedLibs)
|
if (platformLibName in visitedLibs)
|
||||||
return
|
return
|
||||||
visitedLibs += platformLibName
|
visitedLibs += platformLibName
|
||||||
|
|||||||
+24
-6
@@ -11,6 +11,7 @@ import org.gradle.api.plugins.JavaPluginConvention
|
|||||||
import org.gradle.api.tasks.*
|
import org.gradle.api.tasks.*
|
||||||
import org.jetbrains.kotlin.gradle.dsl.KotlinSingleJavaTargetExtension
|
import org.jetbrains.kotlin.gradle.dsl.KotlinSingleJavaTargetExtension
|
||||||
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
import org.jetbrains.kotlin.gradle.dsl.kotlinExtension
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.isGradleVersionAtLeast
|
||||||
import org.jetbrains.kotlin.gradle.utils.newProperty
|
import org.jetbrains.kotlin.gradle.utils.newProperty
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
@@ -27,18 +28,35 @@ internal open class InspectClassesForMultiModuleIC : DefaultTask() {
|
|||||||
@Suppress("MemberVisibilityCanBePrivate")
|
@Suppress("MemberVisibilityCanBePrivate")
|
||||||
@get:OutputFile
|
@get:OutputFile
|
||||||
internal val classesListFile: File by lazy {
|
internal val classesListFile: File by lazy {
|
||||||
(project.kotlinExtension as KotlinSingleJavaTargetExtension).target.defaultArtifactClassesListFile
|
(project.kotlinExtension as KotlinSingleJavaTargetExtension).target.defaultArtifactClassesListFile.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@get:InputFiles
|
||||||
|
internal val sourceSetOutputClassesDir by lazy {
|
||||||
|
project.convention.findPlugin(JavaPluginConvention::class.java)?.sourceSets?.findByName(sourceSetName)?.output?.classesDirs
|
||||||
|
}
|
||||||
|
|
||||||
|
@get:Internal
|
||||||
|
internal val fileTrees
|
||||||
|
get() = sourceSetOutputClassesDir?.map {
|
||||||
|
if (isGradleVersionAtLeast(6, 0)) {
|
||||||
|
objects.fileTree().from(it).include("**/*.class")
|
||||||
|
} else {
|
||||||
|
project.fileTree(it).include("**/*.class")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@get:Internal
|
||||||
|
internal val objects = project.objects
|
||||||
|
|
||||||
@Suppress("MemberVisibilityCanBePrivate")
|
@Suppress("MemberVisibilityCanBePrivate")
|
||||||
@get:InputFiles
|
@get:InputFiles
|
||||||
internal val classFiles: FileCollection
|
internal val classFiles: FileCollection
|
||||||
get() {
|
get() {
|
||||||
val convention = project.convention.findPlugin(JavaPluginConvention::class.java)
|
if (sourceSetOutputClassesDir != null) {
|
||||||
val sourceSet = convention?.sourceSets?.findByName(sourceSetName) ?: return project.files()
|
return objects.fileCollection().from(fileTrees)
|
||||||
|
}
|
||||||
val fileTrees = sourceSet.output.classesDirs.map { project.fileTree(it).include("**/*.class") }
|
return objects.fileCollection()
|
||||||
return project.files(fileTrees)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@TaskAction
|
@TaskAction
|
||||||
|
|||||||
+1
-1
@@ -96,7 +96,7 @@ open class KotlinCompileCommon : AbstractKotlinCompile<K2MetadataCompilerArgumen
|
|||||||
override fun callCompilerAsync(args: K2MetadataCompilerArguments, sourceRoots: SourceRoots, changedFiles: ChangedFiles) {
|
override fun callCompilerAsync(args: K2MetadataCompilerArguments, sourceRoots: SourceRoots, changedFiles: ChangedFiles) {
|
||||||
val messageCollector = GradlePrintingMessageCollector(logger, args.allWarningsAsErrors)
|
val messageCollector = GradlePrintingMessageCollector(logger, args.allWarningsAsErrors)
|
||||||
val outputItemCollector = OutputItemsCollectorImpl()
|
val outputItemCollector = OutputItemsCollectorImpl()
|
||||||
val compilerRunner = compilerRunner()
|
val compilerRunner = compilerRunner
|
||||||
val environment = GradleCompilerEnvironment(
|
val environment = GradleCompilerEnvironment(
|
||||||
computedCompilerClasspath, messageCollector, outputItemCollector,
|
computedCompilerClasspath, messageCollector, outputItemCollector,
|
||||||
buildReportMode = buildReportMode,
|
buildReportMode = buildReportMode,
|
||||||
|
|||||||
+154
-63
@@ -8,6 +8,7 @@ package org.jetbrains.kotlin.gradle.tasks
|
|||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.Task
|
import org.gradle.api.Task
|
||||||
import org.gradle.api.file.FileCollection
|
import org.gradle.api.file.FileCollection
|
||||||
|
import org.gradle.api.logging.Logger
|
||||||
import org.gradle.api.provider.Provider
|
import org.gradle.api.provider.Provider
|
||||||
import org.gradle.api.tasks.*
|
import org.gradle.api.tasks.*
|
||||||
import org.gradle.api.tasks.compile.AbstractCompile
|
import org.gradle.api.tasks.compile.AbstractCompile
|
||||||
@@ -20,6 +21,7 @@ import org.jetbrains.kotlin.cli.common.arguments.CommonToolArguments
|
|||||||
import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments
|
import org.jetbrains.kotlin.cli.common.arguments.K2JSCompilerArguments
|
||||||
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
|
import org.jetbrains.kotlin.cli.common.arguments.K2JVMCompilerArguments
|
||||||
import org.jetbrains.kotlin.compilerRunner.*
|
import org.jetbrains.kotlin.compilerRunner.*
|
||||||
|
import org.jetbrains.kotlin.compilerRunner.GradleCompilerRunner.Companion.normalizeForFlagFile
|
||||||
import org.jetbrains.kotlin.daemon.common.MultiModuleICSettings
|
import org.jetbrains.kotlin.daemon.common.MultiModuleICSettings
|
||||||
import org.jetbrains.kotlin.gradle.dsl.*
|
import org.jetbrains.kotlin.gradle.dsl.*
|
||||||
import org.jetbrains.kotlin.gradle.incremental.ChangedFiles
|
import org.jetbrains.kotlin.gradle.incremental.ChangedFiles
|
||||||
@@ -35,8 +37,12 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.AbstractKotlinCompilation
|
|||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.associateWithTransitiveClosure
|
import org.jetbrains.kotlin.gradle.plugin.mpp.associateWithTransitiveClosure
|
||||||
import org.jetbrains.kotlin.gradle.plugin.mpp.ownModuleName
|
import org.jetbrains.kotlin.gradle.plugin.mpp.ownModuleName
|
||||||
import org.jetbrains.kotlin.gradle.report.BuildReportMode
|
import org.jetbrains.kotlin.gradle.report.BuildReportMode
|
||||||
import org.jetbrains.kotlin.gradle.utils.*
|
import org.jetbrains.kotlin.gradle.utils.getValue
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.isParentOf
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.pathsAsStringRelativeTo
|
||||||
|
import org.jetbrains.kotlin.gradle.utils.toSortedPathsArray
|
||||||
import org.jetbrains.kotlin.incremental.ChangedFiles
|
import org.jetbrains.kotlin.incremental.ChangedFiles
|
||||||
|
import org.jetbrains.kotlin.incremental.IncrementalModuleInfo
|
||||||
import org.jetbrains.kotlin.library.impl.isKotlinLibrary
|
import org.jetbrains.kotlin.library.impl.isKotlinLibrary
|
||||||
import org.jetbrains.kotlin.utils.JsLibraryUtils
|
import org.jetbrains.kotlin.utils.JsLibraryUtils
|
||||||
import java.io.File
|
import java.io.File
|
||||||
@@ -87,7 +93,7 @@ abstract class AbstractKotlinCompileTool<T : CommonToolArguments>
|
|||||||
|
|
||||||
@get:Classpath
|
@get:Classpath
|
||||||
@get:InputFiles
|
@get:InputFiles
|
||||||
internal val computedCompilerClasspath: List<File> by project.provider {
|
internal val computedCompilerClasspath: List<File> by lazy {
|
||||||
compilerClasspath?.takeIf { it.isNotEmpty() }
|
compilerClasspath?.takeIf { it.isNotEmpty() }
|
||||||
?: compilerJarFile?.let {
|
?: compilerJarFile?.let {
|
||||||
// a hack to remove compiler jar from the cp, will be dropped when compilerJarFile will be removed
|
// a hack to remove compiler jar from the cp, will be dropped when compilerJarFile will be removed
|
||||||
@@ -113,19 +119,51 @@ abstract class AbstractKotlinCompileTool<T : CommonToolArguments>
|
|||||||
protected abstract fun findKotlinCompilerClasspath(project: Project): List<File>
|
protected abstract fun findKotlinCompilerClasspath(project: Project): List<File>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class GradleCompileTaskProvider {
|
||||||
|
|
||||||
|
constructor(task: Task) {
|
||||||
|
buildDir = task.project.buildDir
|
||||||
|
projectDir = task.project.rootProject.projectDir
|
||||||
|
rootDir = task.project.rootProject.rootDir
|
||||||
|
sessionsDir = GradleCompilerRunner.sessionsDir(task.project)
|
||||||
|
projectName = task.project.rootProject.name.normalizeForFlagFile()
|
||||||
|
buildModulesInfo = GradleCompilerRunner.buildModulesInfo(task.project.gradle)
|
||||||
|
path = task.path
|
||||||
|
logger = task.logger
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
val path: String
|
||||||
|
val logger: Logger
|
||||||
|
val buildDir: File /*= project.buildDir*/
|
||||||
|
val projectDir: File /*= project.rootProject.projectDir*/
|
||||||
|
val rootDir: File /*= project.rootProject.rootDir*/
|
||||||
|
val sessionsDir: File/* = GradleCompilerRunner.sessionsDir(project)*/
|
||||||
|
val projectName: String /*= project.rootProject.name.normalizeForFlagFile()*/
|
||||||
|
val buildModulesInfo: IncrementalModuleInfo /*= GradleCompilerRunner.buildModulesInfo(project.gradle)*/
|
||||||
|
}
|
||||||
|
|
||||||
abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractKotlinCompileTool<T>() {
|
abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractKotlinCompileTool<T>() {
|
||||||
|
|
||||||
init {
|
init {
|
||||||
cacheOnlyIfEnabledForKotlin()
|
cacheOnlyIfEnabledForKotlin()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@get:Internal
|
||||||
|
private val layout = project.layout
|
||||||
|
|
||||||
// avoid creating directory in getter: this can lead to failure in parallel build
|
// avoid creating directory in getter: this can lead to failure in parallel build
|
||||||
@get:LocalState
|
@get:LocalState
|
||||||
internal val taskBuildDirectory: File by project.provider {
|
internal val taskBuildDirectory: File by layout.buildDirectory.dir(KOTLIN_BUILD_DIR_NAME).map { it.file(name).asFile }
|
||||||
File(File(project.buildDir, KOTLIN_BUILD_DIR_NAME), name)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun localStateDirectories(): FileCollection = project.files(taskBuildDirectory)
|
|
||||||
|
@get:Internal
|
||||||
|
internal val projectObjects = project.objects
|
||||||
|
|
||||||
|
@get:LocalState
|
||||||
|
internal val localStateDirectoriesProvider: FileCollection = projectObjects.fileCollection().from(taskBuildDirectory)
|
||||||
|
|
||||||
|
override fun localStateDirectories(): FileCollection = localStateDirectoriesProvider
|
||||||
|
|
||||||
// indicates that task should compile kotlin incrementally if possible
|
// indicates that task should compile kotlin incrementally if possible
|
||||||
// it's not possible when IncrementalTaskInputs#isIncremental returns false (i.e first build)
|
// it's not possible when IncrementalTaskInputs#isIncremental returns false (i.e first build)
|
||||||
@@ -147,9 +185,7 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractKo
|
|||||||
internal var buildReportMode: BuildReportMode? = null
|
internal var buildReportMode: BuildReportMode? = null
|
||||||
|
|
||||||
@get:Internal
|
@get:Internal
|
||||||
internal val taskData: KotlinCompileTaskData by project.provider {
|
internal val taskData: KotlinCompileTaskData = KotlinCompileTaskData.get(project, name)
|
||||||
KotlinCompileTaskData.get(project, name)
|
|
||||||
}
|
|
||||||
|
|
||||||
@get:Input
|
@get:Input
|
||||||
internal open var useModuleDetection: Boolean
|
internal open var useModuleDetection: Boolean
|
||||||
@@ -162,11 +198,9 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractKo
|
|||||||
protected val multiModuleICSettings: MultiModuleICSettings
|
protected val multiModuleICSettings: MultiModuleICSettings
|
||||||
get() = MultiModuleICSettings(taskData.buildHistoryFile, useModuleDetection)
|
get() = MultiModuleICSettings(taskData.buildHistoryFile, useModuleDetection)
|
||||||
|
|
||||||
@get:Classpath
|
|
||||||
@get:InputFiles
|
@get:InputFiles
|
||||||
val pluginClasspath: FileCollection by project.provider {
|
@get:Classpath
|
||||||
project.configurations.getByName(PLUGIN_CLASSPATH_CONFIGURATION_NAME)
|
val pluginClasspath: FileCollection = project.configurations.getByName(PLUGIN_CLASSPATH_CONFIGURATION_NAME)
|
||||||
}
|
|
||||||
|
|
||||||
@get:Internal
|
@get:Internal
|
||||||
internal val pluginOptions = CompilerPluginOptions()
|
internal val pluginOptions = CompilerPluginOptions()
|
||||||
@@ -175,10 +209,13 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractKo
|
|||||||
@get:InputFiles
|
@get:InputFiles
|
||||||
protected val additionalClasspath = arrayListOf<File>()
|
protected val additionalClasspath = arrayListOf<File>()
|
||||||
|
|
||||||
|
@get:Internal
|
||||||
|
internal val objects = project.objects
|
||||||
|
|
||||||
// Store this file collection before it is filtered by File::exists to ensure that Gradle Instant execution doesn't serialize the
|
// Store this file collection before it is filtered by File::exists to ensure that Gradle Instant execution doesn't serialize the
|
||||||
// filtered files, losing those that don't exist yet and will only be created during build
|
// filtered files, losing those that don't exist yet and will only be created during build
|
||||||
private val compileClasspathImpl by project.provider {
|
private val compileClasspathImpl by project.provider {
|
||||||
classpath + project.files(additionalClasspath)
|
classpath + objects.fileCollection().from(additionalClasspath)
|
||||||
}
|
}
|
||||||
|
|
||||||
@get:Internal // classpath already participates in the checks
|
@get:Internal // classpath already participates in the checks
|
||||||
@@ -197,8 +234,9 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractKo
|
|||||||
sourceFilesExtensionsSources.add(extensions)
|
sourceFilesExtensionsSources.add(extensions)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val kotlinExt: KotlinProjectExtension
|
@get:Internal
|
||||||
get() = project.extensions.findByType(KotlinProjectExtension::class.java)!!
|
@field:Transient
|
||||||
|
internal val kotlinExtProvider: KotlinProjectExtension = project.extensions.findByType(KotlinProjectExtension::class.java)!!
|
||||||
|
|
||||||
override fun getDestinationDir(): File =
|
override fun getDestinationDir(): File =
|
||||||
taskData.destinationDir.get()
|
taskData.destinationDir.get()
|
||||||
@@ -218,13 +256,13 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractKo
|
|||||||
@get:Internal
|
@get:Internal
|
||||||
internal var coroutinesFromGradleProperties: Coroutines? = null
|
internal var coroutinesFromGradleProperties: Coroutines? = null
|
||||||
// Input is needed to force rebuild even if source files are not changed
|
// Input is needed to force rebuild even if source files are not changed
|
||||||
@get:Input
|
|
||||||
internal val coroutinesStr: String
|
|
||||||
get() = coroutines.name
|
|
||||||
|
|
||||||
@get:Internal
|
@get:Input
|
||||||
internal val coroutines: Coroutines by project.provider {
|
internal val coroutinesStr: Provider<String> = project.provider {coroutines.get().name}
|
||||||
kotlinExt.experimental.coroutines
|
|
||||||
|
@get:Input
|
||||||
|
internal val coroutines: Provider<Coroutines> = project.provider {
|
||||||
|
kotlinExtProvider.experimental.coroutines
|
||||||
?: coroutinesFromGradleProperties
|
?: coroutinesFromGradleProperties
|
||||||
?: Coroutines.DEFAULT
|
?: Coroutines.DEFAULT
|
||||||
}
|
}
|
||||||
@@ -242,7 +280,7 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractKo
|
|||||||
|
|
||||||
@get:InputFiles
|
@get:InputFiles
|
||||||
@get:PathSensitive(PathSensitivity.RELATIVE)
|
@get:PathSensitive(PathSensitivity.RELATIVE)
|
||||||
internal var commonSourceSet: FileCollection = project.files()
|
internal var commonSourceSet: FileCollection = project.files() //TODO
|
||||||
|
|
||||||
@get:Input
|
@get:Input
|
||||||
internal val moduleName: String by project.provider {
|
internal val moduleName: String by project.provider {
|
||||||
@@ -262,8 +300,10 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractKo
|
|||||||
|
|
||||||
private val kotlinLogger by lazy { GradleKotlinLogger(logger) }
|
private val kotlinLogger by lazy { GradleKotlinLogger(logger) }
|
||||||
|
|
||||||
internal open fun compilerRunner(): GradleCompilerRunner =
|
@get:Internal
|
||||||
GradleCompilerRunner(this)
|
internal val compilerRunner by lazy { compilerRunner() }
|
||||||
|
|
||||||
|
internal open fun compilerRunner(): GradleCompilerRunner = GradleCompilerRunner(GradleCompileTaskProvider(this))
|
||||||
|
|
||||||
@TaskAction
|
@TaskAction
|
||||||
fun execute(inputs: IncrementalTaskInputs) {
|
fun execute(inputs: IncrementalTaskInputs) {
|
||||||
@@ -297,6 +337,9 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractKo
|
|||||||
return !inputs.isIncremental && getSourceRoots().kotlinSourceFiles.isEmpty()
|
return !inputs.isIncremental && getSourceRoots().kotlinSourceFiles.isEmpty()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@get:Internal
|
||||||
|
private val projectDir = project.rootProject.projectDir
|
||||||
|
|
||||||
private fun executeImpl(inputs: IncrementalTaskInputs) {
|
private fun executeImpl(inputs: IncrementalTaskInputs) {
|
||||||
// Check that the JDK tools are available in Gradle (fail-fast, instead of a fail during the compiler run):
|
// Check that the JDK tools are available in Gradle (fail-fast, instead of a fail during the compiler run):
|
||||||
findToolsJar()
|
findToolsJar()
|
||||||
@@ -304,7 +347,7 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractKo
|
|||||||
val sourceRoots = getSourceRoots()
|
val sourceRoots = getSourceRoots()
|
||||||
val allKotlinSources = sourceRoots.kotlinSourceFiles
|
val allKotlinSources = sourceRoots.kotlinSourceFiles
|
||||||
|
|
||||||
logger.kotlinDebug { "All kotlin sources: ${allKotlinSources.pathsAsStringRelativeTo(project.rootProject.projectDir)}" }
|
logger.kotlinDebug { "All kotlin sources: ${allKotlinSources.pathsAsStringRelativeTo(projectDir)}" }
|
||||||
|
|
||||||
if (skipCondition(inputs)) {
|
if (skipCondition(inputs)) {
|
||||||
// Skip running only if non-incremental run. Otherwise, we may need to do some cleanup.
|
// Skip running only if non-incremental run. Otherwise, we may need to do some cleanup.
|
||||||
@@ -327,13 +370,14 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractKo
|
|||||||
*/
|
*/
|
||||||
internal abstract fun callCompilerAsync(args: T, sourceRoots: SourceRoots, changedFiles: ChangedFiles)
|
internal abstract fun callCompilerAsync(args: T, sourceRoots: SourceRoots, changedFiles: ChangedFiles)
|
||||||
|
|
||||||
|
@get:Input
|
||||||
|
internal val isMultiplatform: Boolean by lazy { project.plugins.any { it is KotlinPlatformPluginBase || it is KotlinMultiplatformPluginWrapper } }
|
||||||
|
|
||||||
@get:Internal
|
@get:Internal
|
||||||
internal val isMultiplatform: Boolean by project.provider {
|
internal val abstractKotlinCompileArgumentsContributor by lazy { AbstractKotlinCompileArgumentsContributor(KotlinCompileArgumentsProvider(this)) }
|
||||||
project.plugins.any { it is KotlinPlatformPluginBase || it is KotlinMultiplatformPluginWrapper }
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setupCompilerArgs(args: T, defaultsOnly: Boolean, ignoreClasspathResolutionErrors: Boolean) {
|
override fun setupCompilerArgs(args: T, defaultsOnly: Boolean, ignoreClasspathResolutionErrors: Boolean) {
|
||||||
AbstractKotlinCompileArgumentsContributor(thisTaskProvider).contributeArguments(
|
abstractKotlinCompileArgumentsContributor.contributeArguments(
|
||||||
args,
|
args,
|
||||||
compilerArgumentsConfigurationFlags(defaultsOnly, ignoreClasspathResolutionErrors)
|
compilerArgumentsConfigurationFlags(defaultsOnly, ignoreClasspathResolutionErrors)
|
||||||
)
|
)
|
||||||
@@ -350,6 +394,45 @@ abstract class AbstractKotlinCompile<T : CommonCompilerArguments>() : AbstractKo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
open class KotlinCompileArgumentsProvider<T : AbstractKotlinCompile<out CommonCompilerArguments>>(taskProvider: T) {
|
||||||
|
|
||||||
|
val coroutines: Provider<Coroutines>
|
||||||
|
val logger: Logger
|
||||||
|
val isMultiplatform: Boolean
|
||||||
|
val pluginClasspath: FileCollection
|
||||||
|
val pluginOptions: CompilerPluginOptions
|
||||||
|
|
||||||
|
init {
|
||||||
|
coroutines = taskProvider.coroutines
|
||||||
|
logger = taskProvider.logger
|
||||||
|
isMultiplatform = taskProvider.isMultiplatform
|
||||||
|
pluginClasspath = taskProvider.pluginClasspath
|
||||||
|
pluginOptions = taskProvider.pluginOptions
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class KotlinJvmCompilerArgumentsProvider
|
||||||
|
(taskProvider: KotlinCompile) : KotlinCompileArgumentsProvider<KotlinCompile>(taskProvider) {
|
||||||
|
|
||||||
|
val moduleName: String
|
||||||
|
val friendPaths: Array<String>
|
||||||
|
val compileClasspath: Iterable<File>
|
||||||
|
val destinationDir: File
|
||||||
|
internal val kotlinOptions: List<KotlinJvmOptionsImpl?>
|
||||||
|
|
||||||
|
init {
|
||||||
|
// super(taskProvider)
|
||||||
|
moduleName = taskProvider.moduleName
|
||||||
|
friendPaths = taskProvider.friendPaths
|
||||||
|
compileClasspath = taskProvider.compileClasspath
|
||||||
|
destinationDir = taskProvider.destinationDir
|
||||||
|
kotlinOptions = listOfNotNull(
|
||||||
|
taskProvider.parentKotlinOptionsImpl as KotlinJvmOptionsImpl?,
|
||||||
|
taskProvider.kotlinOptions as KotlinJvmOptionsImpl
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal inline val <reified T : Task> T.thisTaskProvider: TaskProvider<out T>
|
internal inline val <reified T : Task> T.thisTaskProvider: TaskProvider<out T>
|
||||||
get() = checkNotNull(project.locateTask<T>(name))
|
get() = checkNotNull(project.locateTask<T>(name))
|
||||||
|
|
||||||
@@ -397,8 +480,8 @@ open class KotlinCompile : AbstractKotlinCompile<K2JVMCompilerArguments>(), Kotl
|
|||||||
}
|
}
|
||||||
|
|
||||||
@get:Internal
|
@get:Internal
|
||||||
internal val compilerArgumentsContributor: CompilerArgumentsContributor<K2JVMCompilerArguments> by project.provider {
|
internal val compilerArgumentsContributor: CompilerArgumentsContributor<K2JVMCompilerArguments> by lazy {
|
||||||
KotlinJvmCompilerArgumentsContributor(thisTaskProvider)
|
KotlinJvmCompilerArgumentsContributor(KotlinJvmCompilerArgumentsProvider(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
@Internal
|
@Internal
|
||||||
@@ -409,7 +492,7 @@ open class KotlinCompile : AbstractKotlinCompile<K2JVMCompilerArguments>(), Kotl
|
|||||||
|
|
||||||
val messageCollector = GradlePrintingMessageCollector(logger, args.allWarningsAsErrors)
|
val messageCollector = GradlePrintingMessageCollector(logger, args.allWarningsAsErrors)
|
||||||
val outputItemCollector = OutputItemsCollectorImpl()
|
val outputItemCollector = OutputItemsCollectorImpl()
|
||||||
val compilerRunner = compilerRunner()
|
val compilerRunner = compilerRunner
|
||||||
|
|
||||||
val icEnv = if (isIncrementalCompilationEnabled()) {
|
val icEnv = if (isIncrementalCompilationEnabled()) {
|
||||||
logger.info(USING_JVM_INCREMENTAL_COMPILATION_MESSAGE)
|
logger.info(USING_JVM_INCREMENTAL_COMPILATION_MESSAGE)
|
||||||
@@ -417,7 +500,7 @@ open class KotlinCompile : AbstractKotlinCompile<K2JVMCompilerArguments>(), Kotl
|
|||||||
if (hasFilesInTaskBuildDirectory()) changedFiles else ChangedFiles.Unknown(),
|
if (hasFilesInTaskBuildDirectory()) changedFiles else ChangedFiles.Unknown(),
|
||||||
taskBuildDirectory,
|
taskBuildDirectory,
|
||||||
usePreciseJavaTracking = usePreciseJavaTracking,
|
usePreciseJavaTracking = usePreciseJavaTracking,
|
||||||
disableMultiModuleIC = disableMultiModuleIC(),
|
disableMultiModuleIC = disableMultiModuleIC,
|
||||||
multiModuleICSettings = multiModuleICSettings
|
multiModuleICSettings = multiModuleICSettings
|
||||||
)
|
)
|
||||||
} else null
|
} else null
|
||||||
@@ -439,31 +522,32 @@ open class KotlinCompile : AbstractKotlinCompile<K2JVMCompilerArguments>(), Kotl
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun disableMultiModuleIC(): Boolean {
|
@get:Input
|
||||||
if (!isIncrementalCompilationEnabled() || javaOutputDir == null) return false
|
val disableMultiModuleIC: Boolean by lazy {
|
||||||
|
if (!isIncrementalCompilationEnabled() || javaOutputDir == null) {
|
||||||
|
false
|
||||||
|
} else {
|
||||||
|
|
||||||
var illegalTaskOrNull: AbstractCompile? = null
|
var illegalTaskOrNull: AbstractCompile? = null
|
||||||
|
project.tasks.configureEach {
|
||||||
project.tasks.configureEach {
|
if (it is AbstractCompile &&
|
||||||
if (it is AbstractCompile &&
|
it !is JavaCompile &&
|
||||||
it !is JavaCompile &&
|
it !is AbstractKotlinCompile<*> &&
|
||||||
it !is AbstractKotlinCompile<*> &&
|
javaOutputDir!!.isParentOf(it.destinationDir)
|
||||||
javaOutputDir!!.isParentOf(it.destinationDir)
|
) {
|
||||||
) {
|
illegalTaskOrNull = illegalTaskOrNull ?: it
|
||||||
illegalTaskOrNull = illegalTaskOrNull ?: it
|
}
|
||||||
}
|
}
|
||||||
|
if (illegalTaskOrNull != null) {
|
||||||
|
val illegalTask = illegalTaskOrNull!!
|
||||||
|
logger.info(
|
||||||
|
"Kotlin inter-project IC is disabled: " +
|
||||||
|
"unknown task '$illegalTask' destination dir ${illegalTask.destinationDir} " +
|
||||||
|
"intersects with java destination dir $javaOutputDir"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
illegalTaskOrNull != null
|
||||||
}
|
}
|
||||||
|
|
||||||
illegalTaskOrNull?.let { illegalTask ->
|
|
||||||
logger.info(
|
|
||||||
"Kotlin inter-project IC is disabled: " +
|
|
||||||
"unknown task '$illegalTask' destination dir ${illegalTask.destinationDir} " +
|
|
||||||
"intersects with java destination dir $javaOutputDir"
|
|
||||||
)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// override setSource to track source directory sets and files (for generated android folders)
|
// override setSource to track source directory sets and files (for generated android folders)
|
||||||
@@ -483,21 +567,26 @@ open class KotlinCompile : AbstractKotlinCompile<K2JVMCompilerArguments>(), Kotl
|
|||||||
internal open class KotlinCompileWithWorkers @Inject constructor(
|
internal open class KotlinCompileWithWorkers @Inject constructor(
|
||||||
private val workerExecutor: WorkerExecutor
|
private val workerExecutor: WorkerExecutor
|
||||||
) : KotlinCompile() {
|
) : KotlinCompile() {
|
||||||
override fun compilerRunner() = GradleCompilerRunnerWithWorkers(this, workerExecutor)
|
|
||||||
|
@get:Internal
|
||||||
|
val compilerRunnerValue = GradleCompilerRunnerWithWorkers(GradleCompileTaskProvider(this), workerExecutor)
|
||||||
|
|
||||||
|
override fun compilerRunner() = compilerRunnerValue
|
||||||
}
|
}
|
||||||
|
|
||||||
@CacheableTask
|
@CacheableTask
|
||||||
internal open class Kotlin2JsCompileWithWorkers @Inject constructor(
|
internal open class Kotlin2JsCompileWithWorkers @Inject constructor(
|
||||||
private val workerExecutor: WorkerExecutor
|
private val workerExecutor: WorkerExecutor
|
||||||
) : Kotlin2JsCompile() {
|
) : Kotlin2JsCompile() {
|
||||||
override fun compilerRunner() = GradleCompilerRunnerWithWorkers(this, workerExecutor)
|
|
||||||
|
override fun compilerRunner() = GradleCompilerRunnerWithWorkers(GradleCompileTaskProvider(this), workerExecutor)
|
||||||
}
|
}
|
||||||
|
|
||||||
@CacheableTask
|
@CacheableTask
|
||||||
internal open class KotlinCompileCommonWithWorkers @Inject constructor(
|
internal open class KotlinCompileCommonWithWorkers @Inject constructor(
|
||||||
private val workerExecutor: WorkerExecutor
|
private val workerExecutor: WorkerExecutor
|
||||||
) : KotlinCompileCommon() {
|
) : KotlinCompileCommon() {
|
||||||
override fun compilerRunner() = GradleCompilerRunnerWithWorkers(this, workerExecutor)
|
override fun compilerRunner() = GradleCompilerRunnerWithWorkers(GradleCompileTaskProvider(this), workerExecutor)
|
||||||
}
|
}
|
||||||
|
|
||||||
@CacheableTask
|
@CacheableTask
|
||||||
@@ -507,8 +596,7 @@ open class Kotlin2JsCompile : AbstractKotlinCompile<K2JSCompilerArguments>(), Ko
|
|||||||
incremental = true
|
incremental = true
|
||||||
}
|
}
|
||||||
|
|
||||||
override val kotlinOptions: KotlinJsOptions
|
override val kotlinOptions = taskData.compilation.kotlinOptions as KotlinJsOptions
|
||||||
get() = taskData.compilation.kotlinOptions as KotlinJsOptions
|
|
||||||
|
|
||||||
@get:Internal
|
@get:Internal
|
||||||
protected val defaultOutputFile: File
|
protected val defaultOutputFile: File
|
||||||
@@ -601,6 +689,9 @@ open class Kotlin2JsCompile : AbstractKotlinCompile<K2JSCompilerArguments>(), Ko
|
|||||||
JsLibraryUtils::isKotlinJavascriptLibrary
|
JsLibraryUtils::isKotlinJavascriptLibrary
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@get:Internal
|
||||||
|
internal val absolutePathProvider = project.projectDir.absolutePath
|
||||||
|
|
||||||
override fun callCompilerAsync(args: K2JSCompilerArguments, sourceRoots: SourceRoots, changedFiles: ChangedFiles) {
|
override fun callCompilerAsync(args: K2JSCompilerArguments, sourceRoots: SourceRoots, changedFiles: ChangedFiles) {
|
||||||
sourceRoots as SourceRoots.KotlinOnly
|
sourceRoots as SourceRoots.KotlinOnly
|
||||||
|
|
||||||
@@ -624,14 +715,14 @@ open class Kotlin2JsCompile : AbstractKotlinCompile<K2JSCompilerArguments>(), Ko
|
|||||||
args.friendModules = friendDependencies.joinToString(File.pathSeparator)
|
args.friendModules = friendDependencies.joinToString(File.pathSeparator)
|
||||||
|
|
||||||
if (args.sourceMapBaseDirs == null && !args.sourceMapPrefix.isNullOrEmpty()) {
|
if (args.sourceMapBaseDirs == null && !args.sourceMapPrefix.isNullOrEmpty()) {
|
||||||
args.sourceMapBaseDirs = project.projectDir.absolutePath
|
args.sourceMapBaseDirs = absolutePathProvider
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.kotlinDebug("compiling with args ${ArgumentUtils.convertArgumentsToStringList(args)}")
|
logger.kotlinDebug("compiling with args ${ArgumentUtils.convertArgumentsToStringList(args)}")
|
||||||
|
|
||||||
val messageCollector = GradlePrintingMessageCollector(logger, args.allWarningsAsErrors)
|
val messageCollector = GradlePrintingMessageCollector(logger, args.allWarningsAsErrors)
|
||||||
val outputItemCollector = OutputItemsCollectorImpl()
|
val outputItemCollector = OutputItemsCollectorImpl()
|
||||||
val compilerRunner = compilerRunner()
|
val compilerRunner = compilerRunner
|
||||||
|
|
||||||
val icEnv = if (isIncrementalCompilationEnabled()) {
|
val icEnv = if (isIncrementalCompilationEnabled()) {
|
||||||
logger.info(USING_JS_INCREMENTAL_COMPILATION_MESSAGE)
|
logger.info(USING_JS_INCREMENTAL_COMPILATION_MESSAGE)
|
||||||
|
|||||||
+10
-1
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.gradle.utils
|
package org.jetbrains.kotlin.gradle.utils
|
||||||
|
|
||||||
|
import org.gradle.api.invocation.Gradle
|
||||||
import org.gradle.util.GradleVersion
|
import org.gradle.util.GradleVersion
|
||||||
|
|
||||||
internal data class ParsedGradleVersion(val major: Int, val minor: Int) : Comparable<ParsedGradleVersion> {
|
internal data class ParsedGradleVersion(val major: Int, val minor: Int) : Comparable<ParsedGradleVersion> {
|
||||||
@@ -56,4 +57,12 @@ internal data class ParsedGradleVersion(val major: Int, val minor: Int) : Compar
|
|||||||
|
|
||||||
fun isGradleVersionAtLeast(major: Int, minor: Int) =
|
fun isGradleVersionAtLeast(major: Int, minor: Int) =
|
||||||
ParsedGradleVersion.parse(GradleVersion.current().version)
|
ParsedGradleVersion.parse(GradleVersion.current().version)
|
||||||
?.let { it >= ParsedGradleVersion(major, minor) } ?: false
|
?.let { it >= ParsedGradleVersion(major, minor) } ?: false
|
||||||
|
|
||||||
|
fun isConfigurationCacheAvailable(gradle: Gradle) =
|
||||||
|
try {
|
||||||
|
val startParameters = gradle.startParameter
|
||||||
|
startParameters.javaClass.getMethod("isConfigurationCache").invoke(startParameters) as? Boolean
|
||||||
|
} catch (_: Exception) {
|
||||||
|
null
|
||||||
|
} ?: false
|
||||||
|
|||||||
+7
-9
@@ -6,7 +6,6 @@
|
|||||||
package org.jetbrains.kotlin.gradle.utils
|
package org.jetbrains.kotlin.gradle.utils
|
||||||
|
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.file.RegularFile
|
|
||||||
import org.gradle.api.file.RegularFileProperty
|
import org.gradle.api.file.RegularFileProperty
|
||||||
import org.gradle.api.provider.Property
|
import org.gradle.api.provider.Property
|
||||||
import org.gradle.api.provider.Provider
|
import org.gradle.api.provider.Provider
|
||||||
@@ -20,14 +19,6 @@ internal operator fun <T> Property<T>.setValue(thisRef: Any?, property: KPropert
|
|||||||
set(value)
|
set(value)
|
||||||
}
|
}
|
||||||
|
|
||||||
internal fun <T : Any> Project.newProperty(initialize: (() -> T)? = null): Property<T> =
|
|
||||||
@Suppress("UNCHECKED_CAST")
|
|
||||||
// use Any and not T::class to allow using lists and maps as the property type, which is otherwise not allowed
|
|
||||||
(project.objects.property(Any::class.java) as Property<T>).apply {
|
|
||||||
if (initialize != null)
|
|
||||||
set(provider(initialize))
|
|
||||||
}
|
|
||||||
|
|
||||||
private class OptionalProviderDelegate<T>(private val provider: Provider<T?>) : ReadOnlyProperty<Any?, T?> {
|
private class OptionalProviderDelegate<T>(private val provider: Provider<T?>) : ReadOnlyProperty<Any?, T?> {
|
||||||
override fun getValue(thisRef: Any?, property: KProperty<*>): T? =
|
override fun getValue(thisRef: Any?, property: KProperty<*>): T? =
|
||||||
if (provider.isPresent)
|
if (provider.isPresent)
|
||||||
@@ -38,6 +29,13 @@ private class OptionalProviderDelegate<T>(private val provider: Provider<T?>) :
|
|||||||
internal fun <T> Project.optionalProvider(initialize: () -> T?): ReadOnlyProperty<Any?, T?> =
|
internal fun <T> Project.optionalProvider(initialize: () -> T?): ReadOnlyProperty<Any?, T?> =
|
||||||
OptionalProviderDelegate(provider(initialize))
|
OptionalProviderDelegate(provider(initialize))
|
||||||
|
|
||||||
|
internal fun <T : Any> Project.newProperty(initialize: (() -> T)? = null): Property<T> =
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
(project.objects.property(Any::class.java) as Property<T>).apply {
|
||||||
|
if (initialize != null)
|
||||||
|
set(provider(initialize))
|
||||||
|
}
|
||||||
|
|
||||||
// Before 5.0 fileProperty is created via ProjectLayout
|
// Before 5.0 fileProperty is created via ProjectLayout
|
||||||
// https://docs.gradle.org/current/javadoc/org/gradle/api/model/ObjectFactory.html#fileProperty--
|
// https://docs.gradle.org/current/javadoc/org/gradle/api/model/ObjectFactory.html#fileProperty--
|
||||||
internal fun Project.newFileProperty(initialize: (() -> File)? = null): RegularFileProperty {
|
internal fun Project.newFileProperty(initialize: (() -> File)? = null): RegularFileProperty {
|
||||||
|
|||||||
Reference in New Issue
Block a user