[Build] Fix configuration cache issues (part 5)
Make Project.configureFormInstrumentation and Task.useAndroidConfiguration extensions, :dependencies:android-sdk unzip tasks compatible with configuration cache Relates to #KT-44611
This commit is contained in:
@@ -31,46 +31,6 @@ import java.io.File
|
|||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
fun Project.configureFormInstrumentation() {
|
fun Project.configureFormInstrumentation() {
|
||||||
plugins.matching { it::class.java.canonicalName.startsWith("org.jetbrains.kotlin.gradle.plugin") }.all {
|
|
||||||
// When we change the output classes directory, Gradle will automatically configure
|
|
||||||
// the test compile tasks to use the instrumented classes. Normally this is fine,
|
|
||||||
// however, it causes problems for Kotlin projects:
|
|
||||||
|
|
||||||
// The "internal" modifier can be used to restrict access to the same module.
|
|
||||||
// To make it possible to use internal methods from the main source set in test classes,
|
|
||||||
// the Kotlin Gradle plugin adds the original output directory of the Java task
|
|
||||||
// as "friendly directory" which makes it possible to access internal members
|
|
||||||
// of the main module. Also this directory should be available on classpath during compilation
|
|
||||||
|
|
||||||
// This fails when we change the classes dir. The easiest fix is to prepend the
|
|
||||||
// classes from the "friendly directory" to the compile classpath.
|
|
||||||
val testCompile = tasks.findByName("compileTestKotlin") as AbstractCompile?
|
|
||||||
testCompile?.doFirst {
|
|
||||||
val originalClassesDirs = files((mainSourceSet as ExtensionAware).extra.get("classesDirsCopy"))
|
|
||||||
|
|
||||||
testCompile.classpath = (testCompile.classpath
|
|
||||||
- mainSourceSet.output.classesDirs
|
|
||||||
+ originalClassesDirs)
|
|
||||||
|
|
||||||
// Since Kotlin 1.3.60, the friend paths available to the test compile task are calculated as the main source set's
|
|
||||||
// output.classesDirs. Since the classesDirs are excluded from the classpath (replaced by the originalClassesDirs),
|
|
||||||
// in order to be able to access the internals of 'main', tests need to receive the original classes dirs as a
|
|
||||||
// -Xfriend-paths compiler argument as well.
|
|
||||||
fun addFreeCompilerArgs(kotlinCompileTask: AbstractCompile, vararg args: String) {
|
|
||||||
val getKotlinOptions = kotlinCompileTask::class.java.getMethod("getKotlinOptions")
|
|
||||||
val kotlinOptions = getKotlinOptions(kotlinCompileTask)
|
|
||||||
|
|
||||||
val getFreeCompilerArgs = kotlinOptions::class.java.getMethod("getFreeCompilerArgs")
|
|
||||||
val freeCompilerArgs = getFreeCompilerArgs(kotlinOptions) as List<*>
|
|
||||||
|
|
||||||
val setFreeCompilerArgs = kotlinOptions::class.java.getMethod("setFreeCompilerArgs", List::class.java)
|
|
||||||
setFreeCompilerArgs(kotlinOptions, freeCompilerArgs + args)
|
|
||||||
}
|
|
||||||
addFreeCompilerArgs(testCompile, "-Xfriend-paths=" + originalClassesDirs.joinToString(",") { it.absolutePath })
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
val instrumentationClasspathCfg = configurations.create("instrumentationClasspath")
|
val instrumentationClasspathCfg = configurations.create("instrumentationClasspath")
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
@@ -101,6 +61,46 @@ fun Project.configureFormInstrumentation() {
|
|||||||
// Ensure that our task is invoked when the source set is built
|
// Ensure that our task is invoked when the source set is built
|
||||||
sourceSetParam.compiledBy(instrumentTask)
|
sourceSetParam.compiledBy(instrumentTask)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
plugins.matching { it::class.java.canonicalName.startsWith("org.jetbrains.kotlin.gradle.plugin") }.configureEach {
|
||||||
|
// When we change the output classes directory, Gradle will automatically configure
|
||||||
|
// the test compile tasks to use the instrumented classes. Normally this is fine,
|
||||||
|
// however, it causes problems for Kotlin projects:
|
||||||
|
|
||||||
|
// The "internal" modifier can be used to restrict access to the same module.
|
||||||
|
// To make it possible to use internal methods from the main source set in test classes,
|
||||||
|
// the Kotlin Gradle plugin adds the original output directory of the Java task
|
||||||
|
// as "friendly directory" which makes it possible to access internal members
|
||||||
|
// of the main module. Also this directory should be available on classpath during compilation
|
||||||
|
|
||||||
|
// This fails when we change the classes dir. The easiest fix is to prepend the
|
||||||
|
// classes from the "friendly directory" to the compile classpath.
|
||||||
|
if (!tasks.names.contains("compileTestKotlin")) return@configureEach
|
||||||
|
|
||||||
|
tasks.named<AbstractCompile>("compileTestKotlin").configure {
|
||||||
|
val originalClassesDirs = project.files((project.mainSourceSet as ExtensionAware).extra.get("classesDirsCopy"))
|
||||||
|
|
||||||
|
classpath = (classpath
|
||||||
|
- project.mainSourceSet.output.classesDirs
|
||||||
|
+ originalClassesDirs)
|
||||||
|
|
||||||
|
// Since Kotlin 1.3.60, the friend paths available to the test compile task are calculated as the main source set's
|
||||||
|
// output.classesDirs. Since the classesDirs are excluded from the classpath (replaced by the originalClassesDirs),
|
||||||
|
// in order to be able to access the internals of 'main', tests need to receive the original classes dirs as a
|
||||||
|
// -Xfriend-paths compiler argument as well.
|
||||||
|
fun addFreeCompilerArgs(kotlinCompileTask: AbstractCompile, vararg args: String) {
|
||||||
|
val getKotlinOptions = kotlinCompileTask::class.java.getMethod("getKotlinOptions")
|
||||||
|
val kotlinOptions = getKotlinOptions(kotlinCompileTask)
|
||||||
|
|
||||||
|
val getFreeCompilerArgs = kotlinOptions::class.java.getMethod("getFreeCompilerArgs")
|
||||||
|
val freeCompilerArgs = getFreeCompilerArgs(kotlinOptions) as List<*>
|
||||||
|
|
||||||
|
val setFreeCompilerArgs = kotlinOptions::class.java.getMethod("setFreeCompilerArgs", List::class.java)
|
||||||
|
setFreeCompilerArgs(kotlinOptions, freeCompilerArgs + args)
|
||||||
|
}
|
||||||
|
addFreeCompilerArgs(this, "-Xfriend-paths=" + originalClassesDirs.joinToString(",") { it.absolutePath })
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
import org.gradle.api.Project
|
import org.gradle.api.Project
|
||||||
import org.gradle.api.Task
|
import org.gradle.api.Task
|
||||||
|
import org.gradle.api.artifacts.ProjectDependency
|
||||||
import org.gradle.api.file.FileSystemOperations
|
import org.gradle.api.file.FileSystemOperations
|
||||||
import org.gradle.api.internal.tasks.testing.filter.DefaultTestFilter
|
import org.gradle.api.internal.tasks.testing.filter.DefaultTestFilter
|
||||||
import org.gradle.api.tasks.TaskProvider
|
import org.gradle.api.tasks.TaskProvider
|
||||||
@@ -243,18 +244,25 @@ private fun Task.useAndroidConfiguration(systemPropertyName: String, configName:
|
|||||||
val configuration = with(project) {
|
val configuration = with(project) {
|
||||||
configurations.getOrCreate(configName)
|
configurations.getOrCreate(configName)
|
||||||
.also {
|
.also {
|
||||||
dependencies.add(
|
if (it.allDependencies.matching { dep ->
|
||||||
configName,
|
dep is ProjectDependency &&
|
||||||
dependencies.project(":dependencies:android-sdk", configuration = configName)
|
dep.targetConfiguration == configName &&
|
||||||
)
|
dep.dependencyProject.path == ":dependencies:android-sdk"
|
||||||
|
}.count() == 0) {
|
||||||
|
dependencies.add(
|
||||||
|
configName,
|
||||||
|
dependencies.project(":dependencies:android-sdk", configuration = configName)
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependsOn(configuration)
|
dependsOn(configuration)
|
||||||
|
|
||||||
if (this is Test) {
|
if (this is Test) {
|
||||||
|
val androidFilePath = configuration.singleFile.canonicalPath
|
||||||
doFirst {
|
doFirst {
|
||||||
systemProperty(systemPropertyName, configuration.singleFile.canonicalPath)
|
systemProperty(systemPropertyName, androidFilePath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+14
-8
@@ -1,3 +1,4 @@
|
|||||||
|
import org.gradle.configurationcache.extensions.serviceOf
|
||||||
import org.gradle.internal.os.OperatingSystem
|
import org.gradle.internal.os.OperatingSystem
|
||||||
import java.net.URI
|
import java.net.URI
|
||||||
|
|
||||||
@@ -72,22 +73,27 @@ fun unzipSdkTask(
|
|||||||
additionalConfig: Configuration? = null, dirLevelsToSkipOnUnzip: Int = 0, ext: String = "zip",
|
additionalConfig: Configuration? = null, dirLevelsToSkipOnUnzip: Int = 0, ext: String = "zip",
|
||||||
prepareTask: TaskProvider<DefaultTask> = prepareSdk,
|
prepareTask: TaskProvider<DefaultTask> = prepareSdk,
|
||||||
unzipFilter: CopySpec.() -> Unit = {}
|
unzipFilter: CopySpec.() -> Unit = {}
|
||||||
): Task {
|
): TaskProvider<Task> {
|
||||||
val id = "${sdkName}_$sdkVer"
|
val id = "${sdkName}_$sdkVer"
|
||||||
val cfg = configurations.create(id)
|
val createdCfg = configurations.create(id)
|
||||||
val dependency = "google:$sdkName:$sdkVer${coordinatesSuffix.takeIf { it.isNotEmpty() }?.let { ":$it" } ?: ""}@$ext"
|
val dependency = "google:$sdkName:$sdkVer${coordinatesSuffix.takeIf { it.isNotEmpty() }?.let { ":$it" } ?: ""}@$ext"
|
||||||
dependencies.add(cfg.name, dependency)
|
dependencies.add(createdCfg.name, dependency)
|
||||||
|
|
||||||
val unzipTask = task("unzip_$id") {
|
val sdkDestDir = sdkDestDir
|
||||||
|
val unzipTask = tasks.register("unzip_$id") {
|
||||||
|
val cfg = project.configurations.getByName(id)
|
||||||
dependsOn(cfg)
|
dependsOn(cfg)
|
||||||
inputs.files(cfg)
|
inputs.files(cfg)
|
||||||
val targetDir = file("$sdkDestDir/$destinationSubdir")
|
val targetDir = project.file("$sdkDestDir/$destinationSubdir")
|
||||||
outputs.dirs(targetDir)
|
outputs.dirs(targetDir)
|
||||||
|
val fs = project.serviceOf<FileSystemOperations>()
|
||||||
|
val archiveOperations = project.serviceOf<ArchiveOperations>()
|
||||||
|
val file = cfg.singleFile
|
||||||
doFirst {
|
doFirst {
|
||||||
project.copy {
|
fs.copy {
|
||||||
when (ext) {
|
when (ext) {
|
||||||
"zip" -> from(zipTree(cfg.singleFile))
|
"zip" -> from(archiveOperations.zipTree(file))
|
||||||
"tar.gz" -> from(tarTree(resources.gzip(cfg.singleFile)))
|
"tar.gz" -> from(archiveOperations.tarTree(project.resources.gzip(file)))
|
||||||
else -> throw GradleException("Don't know how to handle the extension \"$ext\"")
|
else -> throw GradleException("Don't know how to handle the extension \"$ext\"")
|
||||||
}
|
}
|
||||||
unzipFilter.invoke(this)
|
unzipFilter.invoke(this)
|
||||||
|
|||||||
@@ -19,4 +19,3 @@ dependencies {
|
|||||||
sourceSets {
|
sourceSets {
|
||||||
"test" {}
|
"test" {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user