From 5a0a853d9bc0f3d88fc4a3558e66a3ae4ee6e3c9 Mon Sep 17 00:00:00 2001 From: Sergey Bogolepov Date: Mon, 14 Sep 2020 22:05:09 +0700 Subject: [PATCH] [Native] Add simple symbol mechanism to konan.properties Java Properties format is extremely trivial and does not support any kind of references or variables. It makes konan.properties repetitive. This commits adds support of perl-like `$` sigil which allows to reference properties inside values. --- .../kotlin/konan/properties/Properties.kt | 48 +++++++++++++++++++ .../compilerRunner/nativeToolRunners.kt | 3 +- .../kotlin/konan/target/Distribution.kt | 4 ++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/compiler/util-io/src/org/jetbrains/kotlin/konan/properties/Properties.kt b/compiler/util-io/src/org/jetbrains/kotlin/konan/properties/Properties.kt index f8a88cfe804..c4924226a69 100644 --- a/compiler/util-io/src/org/jetbrains/kotlin/konan/properties/Properties.kt +++ b/compiler/util-io/src/org/jetbrains/kotlin/konan/properties/Properties.kt @@ -69,3 +69,51 @@ fun Properties.keepOnlyDefaultProfiles() { // TODO: it actually affects only resolution made in :dependencies, // that's why we assume that 'default' profile comes first (and check this above). } + + +/** + * Wraps [propertyList] with resolving mechanism. See [String.resolveValue]. + */ +fun Properties.resolvablePropertyList( + key: String, suffix: String? = null, escapeInQuotes: Boolean = false, + visitedProperties: MutableSet = mutableSetOf() +): List = propertyList(key, suffix, escapeInQuotes).flatMap { + // We need to create a copy of a visitedProperties to avoid collisions + // between different elements of the list. + it.resolveValue(this, visitedProperties.toMutableSet()) +} + +/** + * Wraps [propertyString] with resolving mechanism. See [String.resolveValue]. + */ +fun Properties.resolvablePropertyString( + key: String, suffix: String? = null, + visitedProperties: MutableSet = mutableSetOf() +): String? = propertyString(key, suffix) + ?.split(' ') + ?.flatMap { it.resolveValue(this, visitedProperties) } + ?.joinToString(" ") + +/** + * Adds trivial symbol resolving mechanism to properties files. + * + * Given the following properties file: + * + * key0 = value1 value2 + * key1 = value3 $key0 + * key2 = $key1 + * + * "$key1".resolveValue(properties) will return List("value3", "value1", "value2") + */ +private fun String.resolveValue(properties: Properties, visitedProperties: MutableSet = mutableSetOf()): List = + when { + startsWith("$") -> { + val property = this.substringAfter('$') + // Keep track of visited properties to avoid running in circles. + if (!visitedProperties.add(property)) { + error("Circular dependency: ${visitedProperties.joinToString()}") + } + properties.resolvablePropertyList(property, visitedProperties = visitedProperties) + } + else -> listOf(this) + } diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/nativeToolRunners.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/nativeToolRunners.kt index c6f56b999bf..27328d5d5eb 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/nativeToolRunners.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/compilerRunner/nativeToolRunners.kt @@ -12,6 +12,7 @@ import org.jetbrains.kotlin.gradle.plugin.PropertiesProvider import org.jetbrains.kotlin.gradle.plugin.mpp.isAtLeast import org.jetbrains.kotlin.gradle.utils.NativeCompilerDownloader import org.jetbrains.kotlin.konan.CompilerVersion +import org.jetbrains.kotlin.konan.properties.resolvablePropertyString import org.jetbrains.kotlin.konan.target.HostManager import org.jetbrains.kotlin.konan.target.KonanTarget import org.jetbrains.kotlin.konan.util.DependencyDirectories @@ -104,7 +105,7 @@ internal abstract class AbstractKotlinNativeCInteropRunner(toolName: String, pro project.file("${project.konanHome}/konan/konan.properties").inputStream().use(::load) } - konanProperties.getProperty("llvmHome.mingw_x64")?.let { toolchainDir -> + konanProperties.resolvablePropertyString("llvmHome.mingw_x64")?.let { toolchainDir -> DependencyDirectories.defaultDependenciesRoot .resolve("$toolchainDir/bin") .absolutePath diff --git a/native/utils/src/org/jetbrains/kotlin/konan/target/Distribution.kt b/native/utils/src/org/jetbrains/kotlin/konan/target/Distribution.kt index 2c22e4c53a0..a5be1693e31 100644 --- a/native/utils/src/org/jetbrains/kotlin/konan/target/Distribution.kt +++ b/native/utils/src/org/jetbrains/kotlin/konan/target/Distribution.kt @@ -43,6 +43,10 @@ class Distribution( fun additionalPropertyFiles(genericName: String) = preconfiguredPropertyFiles(genericName) + userPropertyFiles(genericName) + /** + * Please note that konan.properties uses simple resolving mechanism. + * See [org.jetbrains.kotlin.konan.properties.resolveValue]. + */ val properties by lazy { val result = Properties()