[gradle-plugin] Add a konan.useEnvironmentVariables property

This commit is contained in:
Ilya Matveev
2018-03-05 19:08:39 +03:00
committed by ilmat192
parent 763592fe03
commit 6aee9446c6
5 changed files with 179 additions and 18 deletions
@@ -1,13 +1,53 @@
package org.jetbrains.kotlin.gradle.plugin
import org.gradle.api.Project
import org.jetbrains.kotlin.gradle.plugin.KonanPlugin.ProjectProperty
import java.io.File
object EnvironmentVariables {
/**
* The plugin allows an IDE to specify some building parameters. These parameters
* are passed to the plugin via environment variables. Two variables are supported:
* - CONFIGURATION_BUILD_DIR - an absolute path to a destination directory for all compilation tasks.
* The IDE should take care about specifying different directories
* for different targets. This setting has less priority than
* an explicitly specified destination directory in the build script.
* - DEBUGGING_SYMBOLS - If YES, the debug support will be enabled for all artifacts. This option has less
* priority than explicitly specified enableDebug option in the build script and
* enableDebug project property.
*
* Support for environment variables should be explicitly enabled by setting a project property:
* konan.useEnvironmentVariables = true.
*/
internal interface EnvironmentVariables {
val configurationBuildDir: File?
val debuggingSymbols: Boolean
}
internal class EnvironmentVariablesUnused: EnvironmentVariables {
override val configurationBuildDir: File?
get() = null
override val debuggingSymbols: Boolean
get() = false
}
internal class EnvironmentVariablesImpl: EnvironmentVariables {
override val configurationBuildDir: File?
get() = System.getenv("CONFIGURATION_BUILD_DIR")?.let {
File(it).apply {check(isAbsolute) { "A path passed using CONFIGURATION_BUILD_DIR should be absolute" } }
File(it).apply { check(isAbsolute) { "A path passed using CONFIGURATION_BUILD_DIR should be absolute" } }
}
val debuggingSymbols: Boolean
override val debuggingSymbols: Boolean
get() = System.getenv("DEBUGGING_SYMBOLS")?.toUpperCase() == "YES"
}
}
internal val Project.useEnvironmentVariables: Boolean
get() = findProperty(ProjectProperty.KONAN_USE_ENVIRONMENT_VARIABLES)?.toString()?.toBoolean() ?: false
internal val Project.environmentVariables: EnvironmentVariables
get() = if (useEnvironmentVariables) {
EnvironmentVariablesImpl()
} else {
EnvironmentVariablesUnused()
}
@@ -100,12 +100,12 @@ abstract class KonanBuildingConfig<T: KonanBuildingTask>(private val name_: Stri
// In this case all produced files has the same name but are placed in different directories
// depending on their targets (e.g. linux/foo.kexe and macbook/foo.kexe).
// 2. Custom path provided by IDE. In this case CONFIGURATION_BUILD_DIR environment variable should
// contain a path to a destination directory. All produced files are placed in this directory and have
// different names depending on their target (e.g. foo/bar/baz_linux.kexe and foo/bar/baz_macbook.kexe).
// contain a path to a destination directory. All produced files are placed in this directory so IDE
// should take care about setting different CONFIGURATION_BUILD_DIR for different targets.
protected fun determineOutputPlacement(target: KonanTarget): OutputPlacement {
val configurationBuildDir = EnvironmentVariables.configurationBuildDir
val configurationBuildDir = project.environmentVariables.configurationBuildDir
return if (configurationBuildDir != null) {
OutputPlacement(configurationBuildDir, "${name}_${target.visibleName}")
OutputPlacement(configurationBuildDir, name)
} else {
OutputPlacement(defaultBaseDir.targetSubdir(target), name)
}
@@ -245,11 +245,12 @@ class KonanPlugin @Inject constructor(private val registry: ToolingModelBuilderR
: Plugin<ProjectInternal> {
enum class ProjectProperty(val propertyName: String) {
KONAN_HOME ("konan.home"),
KONAN_VERSION ("konan.version"),
KONAN_BUILD_TARGETS ("konan.build.targets"),
KONAN_JVM_ARGS ("konan.jvmArgs"),
DOWNLOAD_COMPILER ("download.compiler")
KONAN_HOME ("konan.home"),
KONAN_VERSION ("konan.version"),
KONAN_BUILD_TARGETS ("konan.build.targets"),
KONAN_JVM_ARGS ("konan.jvmArgs"),
KONAN_USE_ENVIRONMENT_VARIABLES("konan.useEnvironmentVariables"),
DOWNLOAD_COMPILER ("download.compiler")
}
companion object {
@@ -70,7 +70,7 @@ abstract class KonanCompileTask: KonanBuildingTask(), KonanCompileSpec {
@Input val linkerOpts = mutableListOf<String>()
@Input var enableDebug = project.findProperty("enableDebug")?.toString()?.toBoolean()
?: EnvironmentVariables.debuggingSymbols
?: project.environmentVariables.debuggingSymbols
@Input var noStdLib = false
@Input var noMain = false
@@ -1,3 +1,19 @@
/*
* Copyright 2010-2018 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.gradle.plugin.test
import org.jetbrains.kotlin.konan.target.Family
@@ -7,6 +23,8 @@ import spock.lang.Unroll
import static org.jetbrains.kotlin.gradle.plugin.test.KonanProject.escapeBackSlashes
// TODO: Rewrite tests using Kotlin.
class EnvVariableSpecification extends BaseKonanSpecification {
class WrapperResult {
@@ -49,10 +67,14 @@ class EnvVariableSpecification extends BaseKonanSpecification {
return project
}
private WrapperResult runWrapper(KonanProject project, List<String> tasks, Map<String, String> environment = [:]) {
private WrapperResult runWrapper(KonanProject project,
List<String> tasks,
Map<String, String> environment = [:],
Map<String, String> properties = ["konan.useEnvironmentVariables": 'true']) {
def wrapper = (HostManager.host.family == Family.WINDOWS) ? "gradlew.bat" : "gradlew"
def command = ["$project.projectDir.absolutePath/$wrapper".toString()]
command.addAll(tasks)
command.addAll(properties.collect { "-P${it.key}=${it.value}".toString() })
def projectBuilder = new ProcessBuilder()
.directory(project.projectDir)
.command(command)
@@ -62,8 +84,11 @@ class EnvVariableSpecification extends BaseKonanSpecification {
return new WrapperResult(process)
}
private WrapperResult runWrapper(KonanProject project, String task, Map<String, String> environment = [:]) {
return runWrapper(project, [task], environment)
private WrapperResult runWrapper(KonanProject project,
String task,
Map<String, String> environment = [:],
Map<String, String> properties = ["konan.useEnvironmentVariables": 'true']) {
return runWrapper(project, [task], environment, properties)
}
private String artifactFileName(String baseName, ArtifactType type, KonanTarget target = HostManager.host) {
@@ -85,7 +110,7 @@ class EnvVariableSpecification extends BaseKonanSpecification {
suffix = target.family.dynamicSuffix
break
}
return "$prefix${baseName}_${target.visibleName}.$suffix"
return "$prefix${baseName}.$suffix"
}
@Unroll("Plugin should support #action debug via an env variable")
@@ -214,4 +239,99 @@ class EnvVariableSpecification extends BaseKonanSpecification {
files2.contains(artifactFileName("main", ArtifactType.LIBRARY))
}
def 'Plugin should ignore environmentVariables if konan.useEnvironmentVariables is false or is not set'() {
when:
def project = createProjectWithWrapper()
def newDestinationDir = project.createSubDir("newDestination")
def newDestinationPath = newDestinationDir.absolutePath
project.buildFile.append("""\
apply plugin: 'konan'
konanArtifacts {
program('program')
library('library')
dynamic('dynamic')
framework('framework')
}
task assertNoOverrides {
doLast {
konanArtifacts.forEach { artifact ->
artifact.forEach {
if (it.destinationDir.absolutePath == '${escapeBackSlashes(newDestinationPath)}'){
throw new AssertionError("CONFIGURATION_BUILD_DIR overrides a default output path " +
"when it shouldn't.\\n" +
"Task: \${it.name}, Path: \${it.destinationDir}")
}
if (it.enableDebug) {
throw new AssertionError("DEBUGGING_SYMBOLS overrides a default value " +
"when it shouldn't\\n" +
"Task: \${it.name}")
}
}
}
}
}
""".stripIndent())
def resultNoProp = runWrapper(project,
"assertNoOverrides",
["DEBUGGING_SYMBOLS": "true", "CONFIGURATION_BUILD_DIR": newDestinationPath], [:])
.printStderr()
.getExitValue()
def resultFalseValue = runWrapper(project,
"assertNoOverrides",
["DEBUGGING_SYMBOLS": "true", "CONFIGURATION_BUILD_DIR": newDestinationPath],
["konan.useEnvironmentVariables": "false"])
.printStderr()
.getExitValue()
then:
resultNoProp == 0
resultFalseValue == 0
}
def 'Up-to-date checks should work with different directories for different targets'() {
when:
def project = createProjectWithWrapper()
def fooDir = project.createSubDir("foo")
def barDir = project.createSubDir("bar")
project.buildFile.append("""\
apply plugin: 'konan'
konanArtifacts {
library('foo')
library('bar')
}
task assertUpToDate {
dependsOn 'compileKonanFoo'
doLast {
if (!konanArtifacts.foo.getByTarget('host').state.upToDate) {
throw new AssertionError("Compilation task is not up-to-date")
}
}
}
""".stripIndent())
project.generateSrcFile("main.kt")
def buildResult1 = runWrapper(project, "compileKonanFoo",
["CONFIGURATION_BUILD_DIR": fooDir.absolutePath])
.printStderr()
.getExitValue()
def buildResult2 = runWrapper(project, "compileKonanBar",
["CONFIGURATION_BUILD_DIR": barDir.absolutePath])
.printStderr()
.getExitValue()
def buildResult3 = runWrapper(project,
"assertUpToDate",
["CONFIGURATION_BUILD_DIR": fooDir.absolutePath])
.printStderr()
.getExitValue()
then:
buildResult1 == 0
buildResult2 == 0
buildResult3 == 0
}
}