diff --git a/libraries/tools/kotlin-gradle-plugin/build.gradle b/libraries/tools/kotlin-gradle-plugin/build.gradle index 8f6b9c10a96..43728b91893 100644 --- a/libraries/tools/kotlin-gradle-plugin/build.gradle +++ b/libraries/tools/kotlin-gradle-plugin/build.gradle @@ -21,7 +21,7 @@ repositories { maven { url 'http://repository.jetbrains.com/utils/' } // todo: remove this once the AGP artifacts get published - maven { url project.property("googlePreviewRepositoryPath") } // path to the local unpacked preview repo + maven { url (project.findProperty("googlePreviewRepositoryPath") ?: System.getProperty("googlePreviewRepositoryPath")) } } configurations { @@ -57,6 +57,7 @@ tasks.withType(project.compileKotlin.class) { } compileKotlin.dependsOn compileGroovy +compileAgp25Kotlin.dependsOn compileGroovy compileGroovy.dependsOn.remove("compileJava") def groovyClassesDir = file("${buildDir}/mainGroovyClasses") @@ -68,6 +69,7 @@ sourceSets.main.java.srcDirs += sourceSets.main.kotlin.srcDirs sourceSets { agp25 { compileClasspath += configurations.compile + configurations.agp25CompileOnly + sourceSets.main.output + compileClasspath += files(groovyClassesDir) } } diff --git a/libraries/tools/kotlin-gradle-plugin/src/agp25/kotlin/org/jetbrains/kotlin/gradle/plugin/android/Android25ProjectHandler.kt b/libraries/tools/kotlin-gradle-plugin/src/agp25/kotlin/org/jetbrains/kotlin/gradle/plugin/android/Android25ProjectHandler.kt index d17cc24164a..010d4953055 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/agp25/kotlin/org/jetbrains/kotlin/gradle/plugin/android/Android25ProjectHandler.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/agp25/kotlin/org/jetbrains/kotlin/gradle/plugin/android/Android25ProjectHandler.kt @@ -8,6 +8,8 @@ import com.android.build.gradle.api.UnitTestVariant import com.android.builder.model.SourceProvider import org.gradle.api.Project import org.gradle.api.tasks.compile.AbstractCompile +import org.jetbrains.kotlin.gradle.internal.Kapt3KotlinGradleSubplugin +import org.jetbrains.kotlin.gradle.plugin.android.AndroidGradleWrapper import org.jetbrains.kotlin.gradle.tasks.KotlinCompile import java.io.File @@ -39,6 +41,45 @@ class Android25ProjectHandler(kotlinConfigurationTools: KotlinConfigurationTools } } + override fun wireKotlinTasks(project: Project, + androidPlugin: BasePlugin, + androidExt: BaseExtension, + variantData: BaseVariant, + javaTask: AbstractCompile, + kotlinTask: KotlinCompile, + kotlinAfterJavaTask: KotlinCompile?) { + + val preJavaKotlinOutput = + (if (kotlinAfterJavaTask == null) + // Add Kapt3 output as well, since there's no SyncOutputTask with the new API + project.files(kotlinTask.destinationDir, Kapt3KotlinGradleSubplugin.getKaptClasssesDir(project, getVariantName(variantData))) + else + // Don't register the output, but add the task to the pipeline + project.files() + ).builtBy(kotlinTask) + + val preJavaClasspathKey = variantData.registerPreJavacGeneratedBytecode(preJavaKotlinOutput) + val kotlinClasspath = variantData.getCompileClasspath(preJavaClasspathKey) + + kotlinTask.conventionMapping.map("classpath") { + kotlinClasspath + project.files(AndroidGradleWrapper.getRuntimeJars(androidPlugin, androidExt)) + } + + kotlinTask.setJavaOutput(javaTask.destinationDir) + kotlinAfterJavaTask?.setJavaOutput(javaTask.destinationDir) + + // Use kapt1 annotations file for up-to-date check since annotation processing is done with javac + kotlinTask.annotationsFile?.let { javaTask.inputs.file(it) } + + val kotlinAfterJavaOutput = project.files(kotlinAfterJavaTask).builtBy(kotlinAfterJavaTask) + variantData.registerPostJavacGeneratedBytecode(kotlinAfterJavaOutput) + + if (kotlinAfterJavaTask != null) { + // Then don't register kotlinTask output, but only use it for Java compilation + javaTask.appendClasspath(kotlinTask.destinationDir) + } + } + override fun getSourceProviders(variantData: BaseVariant): Iterable = variantData.sourceSets diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt index 8597099d0fe..a09708e0e69 100755 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinPlugin.kt @@ -3,7 +3,6 @@ package org.jetbrains.kotlin.gradle.plugin import com.android.build.gradle.BaseExtension import com.android.build.gradle.BasePlugin import com.android.build.gradle.api.AndroidSourceSet -import com.android.build.gradle.internal.variant.BaseVariantData import com.android.builder.model.SourceProvider import groovy.lang.Closure import org.apache.tools.ant.util.ReflectUtil.newInstance @@ -21,13 +20,13 @@ import org.gradle.api.tasks.SourceSet import org.gradle.api.tasks.compile.AbstractCompile import org.gradle.api.tasks.compile.JavaCompile import org.jetbrains.kotlin.com.intellij.openapi.util.io.FileUtil +import org.jetbrains.kotlin.com.intellij.openapi.util.text.StringUtil.compareVersionNumbers import org.jetbrains.kotlin.gradle.dsl.KotlinJvmOptionsImpl import org.jetbrains.kotlin.gradle.internal.AnnotationProcessingManager import org.jetbrains.kotlin.gradle.internal.Kapt3GradleSubplugin import org.jetbrains.kotlin.gradle.internal.Kapt3KotlinGradleSubplugin import org.jetbrains.kotlin.gradle.internal.Kapt3KotlinGradleSubplugin.Companion.getKaptClasssesDir import org.jetbrains.kotlin.gradle.internal.initKapt -import org.jetbrains.kotlin.gradle.plugin.android.AndroidGradleWrapper import org.jetbrains.kotlin.gradle.tasks.* import org.jetbrains.kotlin.gradle.utils.ParsedGradleVersion import org.jetbrains.kotlin.incremental.configureMultiProjectIncrementalCompilation @@ -375,22 +374,13 @@ class KotlinConfigurationTools internal constructor(val kotlinSourceSetProvider: abstract class AbstractAndroidProjectHandler(private val kotlinConfigurationTools: KotlinConfigurationTools) { protected val artifactDifferenceRegistryProvider get() = - kotlinConfigurationTools.kotlinGradleBuildServices.artifactDifferenceRegistryProvider + kotlinConfigurationTools.kotlinGradleBuildServices.artifactDifferenceRegistryProvider - private val logger = Logging.getLogger(this.javaClass) + protected val KotlinCompile.annotationsFile: File? get() = kaptOptions.annotationsFile + protected fun KotlinCompile.setJavaOutput(file: File) { javaOutputDir = file } + protected fun AbstractCompile.appendClasspath(file: File) = appendClasspathDynamically(file) - private fun Project.tryGetSingleArtifact(variantData: BaseVariantData<*>): File? { - val log = logger - log.kotlinDebug { "Trying to determine single artifact for project $path" } - - val outputs = variantData.outputs - if (outputs.size != 1) { - log.kotlinDebug { "Output count != 1 for variant: ${outputs.map { it.outputFile.relativeTo(rootDir).path }.joinToString()}" } - return null - } - - return variantData.outputs.first().outputFile - } + protected val logger = Logging.getLogger(this.javaClass) protected abstract fun forEachVariant(project: Project, action: (V) -> Unit): Unit @@ -402,6 +392,14 @@ abstract class AbstractAndroidProjectHandler(private val kotlinConfigurationT protected abstract fun getJavaTask(variantData: V): AbstractCompile? protected abstract fun addJavaSourceDirectoryToVariantModel(variantData: V, javaSourceDirectory: File): Unit + protected abstract fun wireKotlinTasks(project: Project, + androidPlugin: BasePlugin, + androidExt: BaseExtension, + variantData: V, + javaTask: AbstractCompile, + kotlinTask: KotlinCompile, + kotlinAfterJavaTask: KotlinCompile?): Unit + protected abstract fun configureMultiProjectIc(project: Project, variantData: V, javaTask: AbstractCompile, @@ -455,10 +453,6 @@ abstract class AbstractAndroidProjectHandler(private val kotlinConfigurationT val variantDataName = getVariantName(variantData) logger.kotlinDebug("Process variant [$variantDataName]") - val testedVariantData = getTestedVariantData(variantData) - val isAndroidTestVariant = variantDataName.endsWith("androidTest", ignoreCase = true) && - testedVariantData != null - val javaTask = getJavaTask(variantData) if (javaTask == null) { @@ -474,7 +468,6 @@ abstract class AbstractAndroidProjectHandler(private val kotlinConfigurationT // store kotlin classes in separate directory. They will serve as class-path to java compiler kotlinTask.destinationDir = File(project.buildDir, "tmp/kotlin-classes/$variantDataName") kotlinTask.description = "Compiles the $variantDataName kotlin." - kotlinTask.setDependsOn(javaTask.dependsOn) val isKapt3Enabled = Kapt3GradleSubplugin.isEnabled(project) @@ -502,10 +495,6 @@ abstract class AbstractAndroidProjectHandler(private val kotlinConfigurationT val appliedPlugins = subpluginEnvironment.addSubpluginOptions( project, kotlinTask, javaTask, variantData, null) - kotlinTask.mapClasspath { - javaTask.classpath + project.files(AndroidGradleWrapper.getRuntimeJars(androidPlugin, androidExt)) - } - var kotlinAfterJavaTask: KotlinCompile? = null if (javaTask is JavaCompile && aptFiles.isNotEmpty() && !isKapt3Enabled) { @@ -524,18 +513,11 @@ abstract class AbstractAndroidProjectHandler(private val kotlinConfigurationT configureSources(task, variantData) } - if (isAndroidTestVariant) { - // Android Gradle plugin bypasses the Gradle finalizedBy for its tasks in some cases, and - // the Kotlin classes may not be copied for the tested variant. Make sure they are. - kotlinTask.dependsOn(syncOutputTaskName(getVariantName(testedVariantData!!))) - } - appliedPlugins.flatMap { it.getSubpluginKotlinTasks(project, kotlinTask) } .forEach { configureSources(it, variantData) } - //todo Wire tasks and classpaths with the new API - configureJavaTask(kotlinTask, javaTask, logger) - createSyncOutputTask(project, kotlinTask, javaTask, kotlinAfterJavaTask, variantDataName) + wireKotlinTasks(project, androidPlugin, androidExt, variantData, javaTask, + kotlinTask, kotlinAfterJavaTask) configureMultiProjectIc(project, variantData, javaTask, kotlinTask, kotlinAfterJavaTask) } @@ -555,7 +537,7 @@ abstract class AbstractAndroidProjectHandler(private val kotlinConfigurationT } } -private fun configureJavaTask(kotlinTask: KotlinCompile, javaTask: AbstractCompile, logger: Logger) { +internal fun configureJavaTask(kotlinTask: KotlinCompile, javaTask: AbstractCompile, logger: Logger) { // Gradle Java IC in older Gradle versions (before 2.14) cannot check .class directories updates. // To make it work, reset the up-to-date status of compileJava with this flag. kotlinTask.anyClassesCompiled = false @@ -587,9 +569,9 @@ private fun configureJavaTask(kotlinTask: KotlinCompile, javaTask: AbstractCompi javaTask.appendClasspathDynamically(kotlinTask.destinationDir!!) } -private fun syncOutputTaskName(variantName: String) = "copy${variantName.capitalize()}KotlinClasses" +internal fun syncOutputTaskName(variantName: String) = "copy${variantName.capitalize()}KotlinClasses" -private fun createSyncOutputTask( +internal fun createSyncOutputTask( project: Project, kotlinTask: KotlinCompile, javaTask: AbstractCompile, diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/LegacyAndroidAndroidProjectHandler.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/LegacyAndroidAndroidProjectHandler.kt index ed2278aa1d4..d74115a71d4 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/LegacyAndroidAndroidProjectHandler.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/LegacyAndroidAndroidProjectHandler.kt @@ -1,5 +1,6 @@ package org.jetbrains.kotlin.gradle.plugin +import com.android.build.gradle.BaseExtension import com.android.build.gradle.BasePlugin import com.android.build.gradle.internal.variant.BaseVariantData import com.android.build.gradle.internal.variant.BaseVariantOutputData @@ -31,6 +32,30 @@ internal class LegacyAndroidAndroidProjectHandler(kotlinConfigurationTools: Kotl variantManager.variantDataList.forEach(action) } + override fun wireKotlinTasks(project: Project, + androidPlugin: BasePlugin, + androidExt: BaseExtension, + variantData: BaseVariantData, + javaTask: AbstractCompile, + kotlinTask: KotlinCompile, + kotlinAfterJavaTask: KotlinCompile?) { + + kotlinTask.setDependsOn(javaTask.dependsOn) + + kotlinTask.mapClasspath { + javaTask.classpath + project.files(AndroidGradleWrapper.getRuntimeJars(androidPlugin, androidExt)) + } + + getTestedVariantData(variantData)?.let { testedVariantData -> + // Android Gradle plugin bypasses the Gradle finalizedBy for its tasks in some cases, and + // the Kotlin classes may not be copied for the tested variant. Make sure they are. + kotlinTask.dependsOn(syncOutputTaskName(getVariantName(testedVariantData))) + } + + configureJavaTask(kotlinTask, javaTask, logger) + createSyncOutputTask(project, kotlinTask, javaTask, kotlinAfterJavaTask, getVariantName(variantData)) + } + override fun getVariantName(variant: BaseVariantData): String = variant.name override fun checkVariant(variant: BaseVariantData): Unit { @@ -44,7 +69,6 @@ internal class LegacyAndroidAndroidProjectHandler(kotlinConfigurationTools: Kotl override fun getJavaTask(variantData: BaseVariantData): AbstractCompile? = AndroidGradleWrapper.getJavaTask(variantData) - override fun addJavaSourceDirectoryToVariantModel(variantData: BaseVariantData, javaSourceDirectory: File) = variantData.addJavaSourceFoldersToModel(javaSourceDirectory)