[Gradle, K/N] Prefer injection over lateinit vars for task configuration

#KT-45801 Fixed
This commit is contained in:
Alexander Likhachev
2021-04-06 18:45:13 +03:00
parent b530427bb2
commit 6f96c225d7
6 changed files with 65 additions and 62 deletions
@@ -15,6 +15,11 @@ repositories {
mavenCentral() mavenCentral()
} }
// KT-45801
tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinNativeCompile).configureEach {
kotlinOptions
}
kotlin { kotlin {
sourceSets { sourceSets {
commonMain { commonMain {
@@ -7,6 +7,11 @@ repositories {
mavenCentral() mavenCentral()
} }
// KT-45801
tasks.withType<org.jetbrains.kotlin.gradle.tasks.KotlinNativeCompile>().configureEach {
kotlinOptions
}
kotlin { kotlin {
sourceSets["commonMain"].apply { sourceSets["commonMain"].apply {
dependencies { dependencies {
@@ -56,7 +56,6 @@ abstract class AbstractKotlinNativeCompilation(
override val compileKotlinTask: KotlinNativeCompile override val compileKotlinTask: KotlinNativeCompile
get() = super.compileKotlinTask as KotlinNativeCompile get() = super.compileKotlinTask as KotlinNativeCompile
// A collection containing all source sets used by this compilation
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
override val compileKotlinTaskProvider: TaskProvider<out KotlinNativeCompile> override val compileKotlinTaskProvider: TaskProvider<out KotlinNativeCompile>
get() = super.compileKotlinTaskProvider as TaskProvider<out KotlinNativeCompile> get() = super.compileKotlinTaskProvider as TaskProvider<out KotlinNativeCompile>
@@ -130,10 +130,9 @@ open class KotlinNativeTargetConfigurator<T : KotlinNativeTarget>(
// region Task creation. // region Task creation.
private fun Project.createLinkTask(binary: NativeBinary) { private fun Project.createLinkTask(binary: NativeBinary) {
val result = registerTask<KotlinNativeLink>( val result = registerTask<KotlinNativeLink>(
binary.linkTaskName binary.linkTaskName, listOf(binary)
) { ) {
val target = binary.target val target = binary.target
it.binary = binary
it.group = BasePlugin.BUILD_GROUP it.group = BasePlugin.BUILD_GROUP
it.description = "Links ${binary.outputKind.description} '${binary.name}' for a target '${target.name}'." it.description = "Links ${binary.outputKind.description} '${binary.name}' for a target '${target.name}'."
it.enabled = binary.konanTarget.enabledOnCurrentHost it.enabled = binary.konanTarget.enabledOnCurrentHost
@@ -261,9 +260,8 @@ open class KotlinNativeTargetConfigurator<T : KotlinNativeTarget>(
internal fun Project.createKlibCompilationTask(compilation: AbstractKotlinNativeCompilation): TaskProvider<KotlinNativeCompile> { internal fun Project.createKlibCompilationTask(compilation: AbstractKotlinNativeCompilation): TaskProvider<KotlinNativeCompile> {
val compileTaskProvider = registerTask<KotlinNativeCompile>( val compileTaskProvider = registerTask<KotlinNativeCompile>(
compilation.compileKotlinTaskName compilation.compileKotlinTaskName, listOf(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}'."
@@ -70,15 +70,15 @@ open class NativePerformanceReport : DefaultTask() {
} }
private fun getPerformanceCompilerOptions() = private fun getPerformanceCompilerOptions() =
(compilerFlagsFromBinary() + binary.linkTask.compilation.get().kotlinOptions.freeCompilerArgs) (compilerFlagsFromBinary() + binary.linkTask.compilation.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.get()) getAllExecutedTasks(binary.linkTask.compilation)
else else
listOf(binary.linkTask.compilation.get().compileKotlinTask) listOf(binary.linkTask.compilation.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()) {
@@ -14,7 +14,6 @@ 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.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
@@ -31,7 +30,6 @@ 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.resolvablePropertyList import org.jetbrains.kotlin.konan.properties.resolvablePropertyList
@@ -117,12 +115,7 @@ private fun Collection<File>.filterKlibsPassedToCompiler(project: Project) = fil
// endregion // endregion
abstract class AbstractKotlinNativeCompile<T : KotlinCommonToolOptions, K : AbstractKotlinNativeCompilation> : AbstractCompile() { abstract class AbstractKotlinNativeCompile<T : KotlinCommonToolOptions, K : AbstractKotlinNativeCompilation> : AbstractCompile() {
@get:Internal @get:Internal
abstract val compilation: Provider<K> abstract val compilation: K
@get:Internal
internal val compilationIsShared by lazy {
compilation.get() is KotlinSharedNativeCompilation
}
// region inputs/outputs // region inputs/outputs
@get:Input @get:Input
@@ -138,11 +131,15 @@ abstract class AbstractKotlinNativeCompile<T : KotlinCommonToolOptions, K : Abst
abstract val baseName: String abstract val baseName: String
@get:Internal @get:Internal
internal val objects = project.objects protected val objects = project.objects
@get:Internal @get:Internal
internal val konanTarget by lazy { protected val konanTarget by project.provider {
compilation.get().konanTarget compilation.konanTarget
}
private val isSharedCompilation by project.provider {
compilation is KotlinSharedNativeCompilation
} }
// Inputs and outputs // Inputs and outputs
@@ -157,7 +154,7 @@ abstract class AbstractKotlinNativeCompile<T : KotlinCommonToolOptions, K : Abst
val libraries: FileCollection by project.provider { 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 (konanTarget.enabledOnCurrentHost) if (konanTarget.enabledOnCurrentHost)
compilation.get().compileDependencyFiles.filterOutPublishableInteropLibs(project) compilation.compileDependencyFiles.filterOutPublishableInteropLibs(project)
else objects.fileCollection() else objects.fileCollection()
} }
@@ -168,7 +165,7 @@ abstract class AbstractKotlinNativeCompile<T : KotlinCommonToolOptions, K : Abst
} }
@get:Input @get:Input
val target: String by project.provider { compilation.get().konanTarget.name } val target: String by project.provider { compilation.konanTarget.name }
// region Compiler options. // region Compiler options.
@get:Internal @get:Internal
@@ -180,8 +177,8 @@ abstract class AbstractKotlinNativeCompile<T : KotlinCommonToolOptions, K : Abst
abstract val additionalCompilerOptions: Provider<Collection<String>> abstract val additionalCompilerOptions: Provider<Collection<String>>
@get:Internal @get:Internal
val languageSettings: LanguageSettingsBuilder by lazy { val languageSettings: LanguageSettingsBuilder by project.provider {
compilation.get().defaultSourceSet.languageSettings compilation.defaultSourceSet.languageSettings
} }
@get:Input @get:Input
@@ -190,7 +187,7 @@ abstract class AbstractKotlinNativeCompile<T : KotlinCommonToolOptions, K : Abst
// endregion. // endregion.
@get:Input @get:Input
val enableEndorsedLibs: Boolean by project.provider { compilation.map { it.enableEndorsedLibs }.get() } val enableEndorsedLibs: Boolean by project.provider { compilation.enableEndorsedLibs }
@get:Input @get:Input
val kotlinNativeVersion: String val kotlinNativeVersion: String
@@ -235,9 +232,8 @@ abstract class AbstractKotlinNativeCompile<T : KotlinCommonToolOptions, K : Abst
val defaultSerializedCompilerArguments: List<String> val defaultSerializedCompilerArguments: List<String>
get() = buildCommonArgs(true) get() = buildCommonArgs(true)
@get:Internal private val languageSettingsBuilder by project.provider {
internal val languageSettingsBuilder by lazy { compilation.defaultSourceSet.languageSettings
compilation.get().defaultSourceSet.languageSettings
} }
// Args used by both the compiler and IDEA. // Args used by both the compiler and IDEA.
@@ -299,7 +295,7 @@ abstract class AbstractKotlinNativeCompile<T : KotlinCommonToolOptions, K : Abst
addArg("-target", konanTarget.name) addArg("-target", konanTarget.name)
addArg("-p", outputKind.name.toLowerCase()) addArg("-p", outputKind.name.toLowerCase())
if (compilationIsShared) { if (isSharedCompilation) {
add("-Xexpect-actual-linker") add("-Xexpect-actual-linker")
add("-Xmetadata-klib") add("-Xmetadata-klib")
addArg("-manifest", manifestFile.get().absolutePath) addArg("-manifest", manifestFile.get().absolutePath)
@@ -326,7 +322,7 @@ abstract class AbstractKotlinNativeCompile<T : KotlinCommonToolOptions, K : Abst
val output = outputFile.get() val output = outputFile.get()
output.parentFile.mkdirs() output.parentFile.mkdirs()
if (compilationIsShared) { if (isSharedCompilation) {
val manifestFile: File = manifestFile.get() val manifestFile: File = manifestFile.get()
manifestFile.ensureParentDirsCreated() manifestFile.ensureParentDirsCreated()
val properties = java.util.Properties() val properties = java.util.Properties()
@@ -342,12 +338,14 @@ abstract class AbstractKotlinNativeCompile<T : KotlinCommonToolOptions, K : Abst
* A task producing a klibrary from a compilation. * A task producing a klibrary from a compilation.
*/ */
@CacheableTask @CacheableTask
open class KotlinNativeCompile : AbstractKotlinNativeCompile<KotlinCommonOptions, AbstractKotlinNativeCompilation>(), open class KotlinNativeCompile
KotlinCompile<KotlinCommonOptions> { @Inject
constructor(
@Internal @Internal
@Transient // can't be serialized for Gradle configuration avoidance @Transient // can't be serialized for Gradle configuration cache
final override val compilation: Property<AbstractKotlinNativeCompilation> = final override val compilation: AbstractKotlinNativeCompilation
project.newProperty() ) : AbstractKotlinNativeCompile<KotlinCommonOptions, AbstractKotlinNativeCompilation>(),
KotlinCompile<KotlinCommonOptions> {
@get:Input @get:Input
override val outputKind = LIBRARY override val outputKind = LIBRARY
@@ -359,8 +357,7 @@ open class KotlinNativeCompile : AbstractKotlinNativeCompile<KotlinCommonOptions
override val debuggable = true override val debuggable = true
@get:Internal @get:Internal
override val baseName: String by override val baseName: String by project.provider { 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 // 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 } // private val allSourceProvider = compilation.map { project.files(it.allSources).asFileTree }
@@ -392,10 +389,10 @@ open class KotlinNativeCompile : AbstractKotlinNativeCompile<KotlinCommonOptions
get() = commonSources.asFileTree get() = commonSources.asFileTree
private val friendModule: FileCollection by compilation.map { compilationInstance -> private val friendModule: FileCollection by project.provider {
project.files( project.files(
compilationInstance.associateWithTransitiveClosure.map { it.output.allOutputs }, compilation.associateWithTransitiveClosure.map { it.output.allOutputs },
compilationInstance.friendArtifacts compilation.friendArtifacts
) )
} }
// endregion. // endregion.
@@ -415,8 +412,8 @@ open class KotlinNativeCompile : AbstractKotlinNativeCompile<KotlinCommonOptions
// endregion. // endregion.
// region Kotlin options. // region Kotlin options.
override val kotlinOptions: KotlinCommonOptions by lazy { override val kotlinOptions: KotlinCommonOptions by project.provider {
compilation.get().kotlinOptions compilation.kotlinOptions
} }
@get:Input @get:Input
@@ -474,31 +471,30 @@ open class KotlinNativeCompile : AbstractKotlinNativeCompile<KotlinCommonOptions
* A task producing a final binary from a compilation. * A task producing a final binary from a compilation.
*/ */
@CacheableTask @CacheableTask
open class KotlinNativeLink : AbstractKotlinNativeCompile<KotlinCommonToolOptions, KotlinNativeCompilation>() { open class KotlinNativeLink
@Inject
constructor(
@Internal
val binary: NativeBinary
) : AbstractKotlinNativeCompile<KotlinCommonToolOptions, KotlinNativeCompilation>() {
@get:Internal @get:Internal
@Transient // can't be serialized for Gradle configuration avoidance final override val compilation: KotlinNativeCompilation
final override val compilation: Property<KotlinNativeCompilation> = project.newProperty() { binary.compilation } get() = binary.compilation
init { init {
dependsOn(project.provider { compilation.get().compileKotlinTask }) dependsOn(project.provider { compilation.compileKotlinTaskProvider })
// Frameworks actively uses symlinks. // Frameworks actively uses symlinks.
// Gradle build cache transforms symlinks into regular files https://guides.gradle.org/using-build-cache/#symbolic_links // Gradle build cache transforms symlinks into regular files https://guides.gradle.org/using-build-cache/#symbolic_links
outputs.cacheIf { outputKind != FRAMEWORK } outputs.cacheIf { outputKind != FRAMEWORK }
} }
@Internal
lateinit var binary: NativeBinary
@Internal // Taken into account by getSources(). @Internal // Taken into account by getSources().
val intermediateLibrary: Provider<File> = compilation.map { compilationInstance -> val intermediateLibrary: Provider<File> = project.provider { compilation.compileKotlinTask.outputFile.get() }
compilationInstance.compileKotlinTask.outputFile.get()
}
@InputFiles @InputFiles
@SkipWhenEmpty @SkipWhenEmpty
override fun getSource(): FileTree = override fun getSource(): FileTree =
objects.fileCollection().from(intermediateLibrary.get()).asFileTree objects.fileCollection().from(intermediateLibrary).asFileTree
@OutputDirectory @OutputDirectory
override fun getDestinationDir(): File { override fun getDestinationDir(): File {
@@ -522,7 +518,7 @@ open class KotlinNativeLink : AbstractKotlinNativeCompile<KotlinCommonToolOption
@Input get() = binary.baseName @Input get() = binary.baseName
@get:Input @get:Input
protected val konanCacheKind: NativeCacheKind by lazy { protected val konanCacheKind: NativeCacheKind by project.provider {
project.getKonanCacheKind(konanTarget) project.getKonanCacheKind(konanTarget)
} }
@@ -535,8 +531,8 @@ 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: Provider<Collection<String>> = compilation.map { compilationInstance -> override val additionalCompilerOptions: Provider<Collection<String>> = project.provider {
kotlinOptions.freeCompilerArgs + compilationInstance.kotlinOptions.freeCompilerArgs kotlinOptions.freeCompilerArgs + compilation.kotlinOptions.freeCompilerArgs
} }
override val kotlinOptions: KotlinCommonToolOptions = NativeLinkOptions() override val kotlinOptions: KotlinCommonToolOptions = NativeLinkOptions()
@@ -563,7 +559,7 @@ open class KotlinNativeLink : AbstractKotlinNativeCompile<KotlinCommonToolOption
@Input get() = binary is TestExecutable @Input get() = binary is TestExecutable
@get:Classpath @get:Classpath
val exportLibraries: FileCollection by lazy { val exportLibraries: FileCollection by project.provider {
binary.let { binary.let {
if (it is AbstractNativeLibrary) { if (it is AbstractNativeLibrary) {
project.configurations.getByName(it.exportConfigurationName) project.configurations.getByName(it.exportConfigurationName)
@@ -620,8 +616,9 @@ open class KotlinNativeLink : AbstractKotlinNativeCompile<KotlinCommonToolOption
listOf("-Xinclude=${intermediateLibrary.get().absolutePath}") listOf("-Xinclude=${intermediateLibrary.get().absolutePath}")
@get:Internal @get:Internal
val apiFilesProvider = val apiFilesProvider = project.provider {
compilation.map { project.configurations.getByName(it.apiConfigurationName).files.filterKlibsPassedToCompiler(project) } project.configurations.getByName(compilation.apiConfigurationName).files.filterKlibsPassedToCompiler(project)
}
private fun validatedExportedLibraries() { private fun validatedExportedLibraries() {
val exportConfiguration = exportLibraries as? Configuration ?: return val exportConfiguration = exportLibraries as? Configuration ?: return
@@ -689,7 +686,7 @@ internal class CacheBuilder(val project: Project, val binary: NativeBinary, val
private val target: String private val target: String
get() = konanTarget.name get() = konanTarget.name
private val rootCacheDirectory by lazy { private val rootCacheDirectory by project.provider {
getRootCacheDirectory(File(project.konanHome), konanTarget, debuggable, konanCacheKind) getRootCacheDirectory(File(project.konanHome), konanTarget, debuggable, konanCacheKind)
} }
@@ -957,8 +954,7 @@ open class CInteropProcess @Inject constructor(@get:Internal val settings: Defau
// Inputs and outputs. // Inputs and outputs.
@OutputFile @OutputFile
val outputFileProvider: Provider<File> = val outputFileProvider: Provider<File> = project.provider { destinationDir.get().resolve(outputFileName) }
project.provider { destinationDir.get().resolve(outputFileName) }
@get:InputFile @get:InputFile
@get:PathSensitive(PathSensitivity.RELATIVE) @get:PathSensitive(PathSensitivity.RELATIVE)