[K/N][Gradle] Use build service to read konan.properties

Also pass additionalCacheFlags when compiling compiler caches.
This commit is contained in:
Sergey Bogolepov
2021-08-31 16:19:16 +07:00
committed by TeamCityServer
parent 84e7b53926
commit 708931b404
5 changed files with 118 additions and 58 deletions
@@ -11,10 +11,9 @@ import org.jetbrains.kotlin.gradle.dsl.NativeCacheKind
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
import org.jetbrains.kotlin.gradle.plugin.mpp.isAtLeast
import org.jetbrains.kotlin.gradle.plugin.mpp.nativeUseEmbeddableCompilerJar
import org.jetbrains.kotlin.gradle.tasks.CacheBuilder
import org.jetbrains.kotlin.gradle.targets.native.KonanPropertiesBuildService
import org.jetbrains.kotlin.gradle.utils.NativeCompilerDownloader
import org.jetbrains.kotlin.konan.CompilerVersion
import org.jetbrains.kotlin.konan.file.File
import org.jetbrains.kotlin.konan.properties.resolvablePropertyString
import org.jetbrains.kotlin.konan.target.HostManager
import org.jetbrains.kotlin.konan.target.KonanTarget
@@ -42,7 +41,7 @@ internal fun Project.getKonanCacheKind(target: KonanTarget): NativeCacheKind {
return when {
targetCacheKind != null -> targetCacheKind
commonCacheKind != null -> commonCacheKind
else -> CacheBuilder.defaultCacheKindForTarget(target)
else -> KonanPropertiesBuildService.registerIfAbsent(gradle).get().defaultCacheKindForTarget(target)
}
}
@@ -0,0 +1,72 @@
/*
* Copyright 2010-2021 JetBrains s.r.o. and Kotlin Programming Language contributors.
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
*/
package org.jetbrains.kotlin.gradle.targets.native
import org.gradle.api.invocation.Gradle
import org.gradle.api.provider.Property
import org.gradle.api.provider.Provider
import org.gradle.api.services.BuildService
import org.gradle.api.services.BuildServiceParameters
import org.jetbrains.kotlin.compilerRunner.konanHome
import org.jetbrains.kotlin.gradle.dsl.NativeCacheKind
import org.jetbrains.kotlin.konan.properties.resolvablePropertyList
import org.jetbrains.kotlin.konan.target.Distribution
import org.jetbrains.kotlin.konan.target.HostManager
import org.jetbrains.kotlin.konan.target.KonanTarget
import java.util.*
abstract class KonanPropertiesBuildService : BuildService<KonanPropertiesBuildService.Parameters> {
internal interface Parameters : BuildServiceParameters {
val konanHome: Property<String>
}
private val properties: Properties by lazy {
Distribution(parameters.konanHome.get()).properties
}
private val cacheableTargets: List<KonanTarget> by lazy {
properties
.resolvablePropertyList("cacheableTargets", HostManager.hostName)
.map { KonanTarget.predefinedTargets.getValue(it) }
}
private val targetsWithOptInStaticCaches: List<KonanTarget> by lazy {
properties
.resolvablePropertyList("optInCacheableTargets", HostManager.hostName)
.map { KonanTarget.predefinedTargets.getValue(it) }
}
internal fun defaultCacheKindForTarget(target: KonanTarget): NativeCacheKind =
if (target in cacheableTargets && target !in targetsWithOptInStaticCaches) {
NativeCacheKind.STATIC
} else {
NativeCacheKind.NONE
}
internal fun cacheWorksFor(target: KonanTarget): Boolean =
target in cacheableTargets
internal fun additionalCacheFlags(target: KonanTarget): List<String> =
properties.resolvablePropertyList("additionalCacheFlags", target.visibleName)
internal val compilerVersion: String? by lazy {
properties["compilerVersion"]?.toString()
}
companion object {
fun registerIfAbsent(gradle: Gradle): Provider<KonanPropertiesBuildService> =
gradle.sharedServices.registerIfAbsent(serviceName, KonanPropertiesBuildService::class.java) { service ->
service.parameters.konanHome.set(gradle.rootProject.konanHome)
}
private val serviceName: String
get() {
val clazz = KonanPropertiesBuildService::class.java
return "${clazz}_${clazz.classLoader.hashCode()}"
}
}
}
@@ -11,6 +11,7 @@ import org.jetbrains.kotlin.compilerRunner.getKonanCacheKind
import org.jetbrains.kotlin.compilerRunner.konanHome
import org.jetbrains.kotlin.gradle.dsl.NativeCacheKind
import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider
import org.jetbrains.kotlin.gradle.targets.native.KonanPropertiesBuildService
import org.jetbrains.kotlin.gradle.tasks.CacheBuilder
import org.jetbrains.kotlin.gradle.tasks.addArg
import org.jetbrains.kotlin.gradle.utils.lifecycleWithDuration
@@ -35,12 +36,15 @@ internal class PlatformLibrariesGenerator(val project: Project, val konanTarget:
private val defDirectory =
File(distribution.platformDefs(konanTarget)).absoluteFile
private val konanPropertiesService: KonanPropertiesBuildService
get() = KonanPropertiesBuildService.registerIfAbsent(project.gradle).get()
private val konanCacheKind: NativeCacheKind by lazy {
project.getKonanCacheKind(konanTarget)
}
private val shouldBuildCaches: Boolean =
CacheBuilder.cacheWorksFor(konanTarget, project) && konanCacheKind != NativeCacheKind.NONE
konanPropertiesService.cacheWorksFor(konanTarget) && konanCacheKind != NativeCacheKind.NONE
private val mode: String? by lazy {
PropertiesProvider(project).nativePlatformLibrariesMode
@@ -117,6 +121,10 @@ internal class PlatformLibrariesGenerator(val project: Project, val konanTarget:
CacheBuilder.getRootCacheDirectory(File(konanHome), konanTarget, true, konanCacheKind).absolutePath
)
args.addArg("-cache-arg", "-g")
val additionalCacheFlags = konanPropertiesService.additionalCacheFlags(konanTarget)
additionalCacheFlags.forEach {
args.addArg("-cache-arg", it)
}
}
mode?.let {
@@ -33,31 +33,29 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinNativeCompilationData
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.KotlinNativeFragmentMetadataCompilationData
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.isMainCompilationData
import org.jetbrains.kotlin.gradle.plugin.sources.DefaultLanguageSettingsBuilder
import org.jetbrains.kotlin.gradle.targets.native.KonanPropertiesBuildService
import org.jetbrains.kotlin.gradle.targets.native.internal.isAllowCommonizer
import org.jetbrains.kotlin.gradle.utils.*
import org.jetbrains.kotlin.gradle.utils.klibModuleName
import org.jetbrains.kotlin.gradle.utils.listFilesOrEmpty
import org.jetbrains.kotlin.konan.CompilerVersion
import org.jetbrains.kotlin.konan.library.KLIB_INTEROP_IR_PROVIDER_IDENTIFIER
import org.jetbrains.kotlin.konan.properties.resolvablePropertyList
import org.jetbrains.kotlin.konan.properties.saveToFile
import org.jetbrains.kotlin.konan.target.CompilerOutputKind
import org.jetbrains.kotlin.konan.target.CompilerOutputKind.*
import org.jetbrains.kotlin.konan.target.Distribution
import org.jetbrains.kotlin.konan.target.HostManager
import org.jetbrains.kotlin.konan.target.KonanTarget
import org.jetbrains.kotlin.library.*
import org.jetbrains.kotlin.project.model.LanguageSettings
import org.jetbrains.kotlin.utils.ResolvedDependency as KResolvedDependency
import org.jetbrains.kotlin.utils.ResolvedDependencyId as KResolvedDependencyId
import org.jetbrains.kotlin.utils.ResolvedDependencies as KResolvedDependencies
import org.jetbrains.kotlin.utils.ResolvedDependenciesSupport as KResolvedDependenciesSupport
import org.jetbrains.kotlin.utils.ResolvedDependencyArtifactPath as KResolvedDependencyArtifactPath
import org.jetbrains.kotlin.utils.ResolvedDependencyVersion as KResolvedDependencyVersion
import java.io.File
import java.nio.file.Files
import javax.inject.Inject
import org.jetbrains.kotlin.konan.file.File as KFile
import org.jetbrains.kotlin.utils.ResolvedDependencies as KResolvedDependencies
import org.jetbrains.kotlin.utils.ResolvedDependenciesSupport as KResolvedDependenciesSupport
import org.jetbrains.kotlin.utils.ResolvedDependency as KResolvedDependency
import org.jetbrains.kotlin.utils.ResolvedDependencyArtifactPath as KResolvedDependencyArtifactPath
import org.jetbrains.kotlin.utils.ResolvedDependencyId as KResolvedDependencyId
import org.jetbrains.kotlin.utils.ResolvedDependencyVersion as KResolvedDependencyVersion
// TODO: It's just temporary tasks used while KN isn't integrated with Big Kotlin compilation infrastructure.
// region Useful extensions
@@ -730,8 +728,12 @@ private class ExternalDependenciesBuilder(
private val sourceCodeModuleId: KResolvedDependencyId =
intermediateLibraryName?.let { KResolvedDependencyId(it) } ?: KResolvedDependencyId.DEFAULT_SOURCE_CODE_MODULE_ID
private val konanPropertiesService: KonanPropertiesBuildService
get() = KonanPropertiesBuildService.registerIfAbsent(project.gradle).get()
fun buildCompilerArgs(): List<String> {
val konanVersion = Distribution(project.konanHome).compilerVersion?.let(CompilerVersion.Companion::fromString)
val compilerVersion = Distribution.getCompilerVersion(konanPropertiesService.compilerVersion, project.konanHome)
val konanVersion = compilerVersion?.let(CompilerVersion.Companion::fromString)
?: project.konanVersion
if (konanVersion.isAtLeast(1, 6, 0)) {
@@ -907,6 +909,9 @@ internal class CacheBuilder(
private val debuggable: Boolean
get() = binary.debuggable
private val konanPropertiesService: KonanPropertiesBuildService
get() = KonanPropertiesBuildService.registerIfAbsent(project.gradle).get()
private val konanCacheKind: NativeCacheKind
get() = project.getKonanCacheKind(konanTarget)
@@ -986,13 +991,7 @@ internal class CacheBuilder(
)
if (debuggable)
args += "-g"
// It's a dirty workaround, but we need a Gradle Build Service for a proper solution,
// which is too big to put in 1.6.0, so let's use ad-hoc solution for now.
// TODO: https://youtrack.jetbrains.com/issue/KT-48553.
if (konanTarget == KonanTarget.IOS_ARM64) {
// See https://youtrack.jetbrains.com/issue/KT-48552
args += "-Xembed-bitcode-marker"
}
args += konanPropertiesService.additionalCacheFlags(konanTarget)
args += externalDependenciesArgs
args += "-Xadd-cache=${library.libraryFile.absolutePath}"
args += "-Xcache-directory=${cacheDirectory.absolutePath}"
@@ -1071,7 +1070,7 @@ internal class CacheBuilder(
}
fun buildCompilerArgs(): List<String> = mutableListOf<String>().apply {
if (konanCacheKind != NativeCacheKind.NONE && !optimized && cacheWorksFor(konanTarget, project)) {
if (konanCacheKind != NativeCacheKind.NONE && !optimized && konanPropertiesService.cacheWorksFor(konanTarget)) {
rootCacheDirectory.mkdirs()
ensureCompilerProvidedLibsPrecached()
add("-Xcache-directory=${rootCacheDirectory.absolutePath}")
@@ -1102,36 +1101,6 @@ internal class CacheBuilder(
cacheKind.outputKind?.let {
"${baseName}-cache"
} ?: error("No output for kind $cacheKind")
private fun getCacheableTargets(project: Project) =
Distribution(project.konanHome)
.properties
.resolvablePropertyList("cacheableTargets", HostManager.hostName)
.map { KonanTarget.predefinedTargets.getValue(it) }
// Targets with well-tested static caches that can be enabled by default.
// TODO: There is a corresponding property in konan.properties (optInCacheableTargets),
// but naïve implementation makes build slower because it makes reading of konan.properties significantly more frequent.
// One possible solution is to use [Gradle Build service](https://docs.gradle.org/current/userguide/build_services.html).
// Tracking issue: https://youtrack.jetbrains.com/issue/KT-47529
private val targetsWithStableStaticCaches = setOf(
KonanTarget.IOS_X64,
KonanTarget.MACOS_X64,
KonanTarget.IOS_SIMULATOR_ARM64,
KonanTarget.MACOS_ARM64,
KonanTarget.IOS_ARM64,
KonanTarget.LINUX_X64
)
internal fun cacheWorksFor(target: KonanTarget, project: Project) =
target in getCacheableTargets(project)
internal fun defaultCacheKindForTarget(target: KonanTarget): NativeCacheKind =
if (target in targetsWithStableStaticCaches) {
NativeCacheKind.STATIC
} else {
NativeCacheKind.NONE
}
}
}
@@ -69,13 +69,11 @@ class Distribution(
result
}
/**
* Consider using [org.jetbrains.kotlin.gradle.targets.native.KonanPropertiesBuildService] in case of Gradle.
*/
val compilerVersion by lazy {
val propertyVersion = properties["compilerVersion"]?.toString()
val bundleVersion = if (konanHome.contains("-1"))
konanHome.substring(konanHome.lastIndexOf("-1") + 1)
else
null
propertyVersion ?: bundleVersion
getCompilerVersion(properties["compilerVersion"]?.toString(), konanHome)
}
val klib = "$konanHome/klib"
@@ -98,6 +96,20 @@ class Distribution(
override fun availableSubTarget(genericName: String) =
additionalPropertyFiles(genericName).map { it.name }
}
companion object {
/**
* Try to guess compiler version using [konanHome].
*/
private fun getBundleVersion(konanHome: String): String? =
if (konanHome.contains("-1"))
konanHome.substring(konanHome.lastIndexOf("-1") + 1)
else
null
fun getCompilerVersion(propertyVersion: String?, konanHome: String): String? =
propertyVersion ?: getBundleVersion(konanHome)
}
}
// TODO: Move into K/N?