Better approach to handle 'moduleName' in project level DSL

Now project level DSL only configures base part of module name, which
latter is enhanced by Kotlin compilation suffix. In this case
'KotlinCompilation.moduleName' is not used.

Additionally,
'KotlinJvmTask.moduleName' usage was deprecated in favor of
'compilerOptions.moduleName'. Though warning is only produced in case
project is using 'org.jetbrains.kotlin.jvm' or
'org.jetbrains.kotlin.android' plugins.

- 'moduleName' is always required to be non-null.

^KT-57688 Fixed
This commit is contained in:
Yahor Berdnikau
2023-04-05 22:10:17 +02:00
committed by Space Team
parent 08ba63df90
commit f7522ec796
18 changed files with 168 additions and 27 deletions
@@ -1540,6 +1540,7 @@ public abstract interface class org/jetbrains/kotlin/gradle/tasks/Kapt : org/jet
public abstract interface class org/jetbrains/kotlin/gradle/tasks/KaptGenerateStubs : org/jetbrains/kotlin/gradle/tasks/KotlinJvmCompile {
public abstract fun getKaptClasspath ()Lorg/gradle/api/file/ConfigurableFileCollection;
public abstract fun getModuleName ()Lorg/gradle/api/provider/Property;
public abstract fun getStubsDir ()Lorg/gradle/api/file/DirectoryProperty;
}
@@ -1606,6 +1607,7 @@ public final class org/jetbrains/kotlin/gradle/tasks/KotlinJavaToolchain$JdkSett
}
public abstract interface class org/jetbrains/kotlin/gradle/tasks/KotlinJvmCompile : org/jetbrains/kotlin/gradle/dsl/KotlinCompile, org/jetbrains/kotlin/gradle/tasks/BaseKotlinCompile, org/jetbrains/kotlin/gradle/tasks/KotlinCompilationTask {
public abstract fun getModuleName ()Lorg/gradle/api/provider/Property;
public abstract fun getParentKotlinOptions ()Lorg/gradle/api/provider/Property;
}
@@ -81,6 +81,14 @@ interface KotlinJvmCompile : BaseKotlinCompile,
KotlinCompileDeprecated<KotlinJvmOptionsDeprecated>,
KotlinCompilationTask<KotlinJvmCompilerOptions> {
@get:Deprecated(
message = "Please migrate to compilerOptions.moduleName",
replaceWith = ReplaceWith("compilerOptions.moduleName")
)
@get:Optional
@get:Input
override val moduleName: Property<String>
// JVM specific
@get:Internal("Takes part in compiler args.")
@Deprecated(
@@ -96,6 +104,14 @@ interface KaptGenerateStubs : KotlinJvmCompile {
@get:Internal("Not an input, just passed as kapt args. ")
val kaptClasspath: ConfigurableFileCollection
@get:Deprecated(
message = "Please migrate to compilerOptions.moduleName",
replaceWith = ReplaceWith("compilerOptions.moduleName")
)
@get:Optional
@get:Input
override val moduleName: Property<String>
}
interface BaseKapt : Task {
@@ -205,6 +205,10 @@ class CompilerOptionsProjectIT : KGPBaseTest() {
build("compileKotlin") {
assertTasksExecuted(":compileKotlin")
assertOutputDoesNotContain(
"w: :compileKotlin 'KotlinJvmCompile.moduleName' is deprecated, please migrate to 'compilerOptions.moduleName'!"
)
val compilationArgs = output.lineSequence().first { it.contains("Kotlin compiler args:") }
assert(compilationArgs.contains("-module-name customModule")) {
@@ -236,6 +240,7 @@ class CompilerOptionsProjectIT : KGPBaseTest() {
|kotlin {
| compilerOptions {
| javaParameters = true
| moduleName = "my_app"
| }
|}
""".trimMargin()
@@ -244,12 +249,63 @@ class CompilerOptionsProjectIT : KGPBaseTest() {
build("compileDebugKotlin") {
assertTasksExecuted(":compileDebugKotlin")
assertOutputDoesNotContain(
"w: :compileKotlin 'KotlinJvmCompile.moduleName' is deprecated, please migrate to 'compilerOptions.moduleName'!"
)
val compilationArgs = output.lineSequence().first { it.contains("Kotlin compiler args:") }
assert(compilationArgs.contains("-java-parameters")) {
printBuildOutput()
"Compiler arguments does not contain '-java-parameters': $compilationArgs"
}
assert(compilationArgs.contains("-module-name my_app_debug")) {
printBuildOutput()
"Compiler arguments does not contain '-module-name my_app_debug': $compilationArgs"
}
}
}
}
@DisplayName("KT-57688: task moduleName input overrides project level moduleName")
@JvmGradlePluginTests
@GradleTest
fun moduleNameTaskOverrideProject(gradleVersion: GradleVersion) {
project(
projectName = "simpleProject",
gradleVersion = gradleVersion,
buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.DEBUG)
) {
buildGradle.appendText(
//language=Groovy
"""
|
|kotlin {
| compilerOptions {
| moduleName = "customModule"
| }
|}
|
|tasks.named("compileKotlin", org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile.class).configure {
| moduleName = "otherCustomModuleName"
|}
""".trimMargin()
)
build("compileKotlin") {
assertTasksExecuted(":compileKotlin")
assertOutputContains(
"w: :compileKotlin 'KotlinJvmCompile.moduleName' is deprecated, please migrate to 'compilerOptions.moduleName'!"
)
val compilationArgs = output.lineSequence().first { it.contains("Kotlin compiler args:") }
assert(compilationArgs.contains("-module-name otherCustomModuleName")) {
printBuildOutput()
"Compiler arguments does not contain '-module-name otherCustomModuleName': $compilationArgs"
}
}
}
}
@@ -163,7 +163,7 @@ open class KotlinAndroidIncrementalIT : KGPBaseTest() {
)
build("assembleDebug") {
assertFileInProjectExists("libAndroid/build/tmp/kotlin-classes/debug/META-INF/custom_path.kotlin_module")
assertFileInProjectExists("libAndroid/build/tmp/kotlin-classes/debug/META-INF/custom_path_debug.kotlin_module")
}
val libAndroidUtilKt = subProject("libAndroid").kotlinSourcesDir().resolve("com/example/libAndroidUtil.kt")
@@ -111,6 +111,9 @@ abstract class KaptGenerateStubsTask @Inject constructor(
args.freeArgs = emptyList()
KotlinJvmCompilerOptionsHelper.fillCompilerArguments(compilerOptions, args)
overrideArgsUsingTaskModuleNameWithWarning(args)
requireNotNull(args.moduleName)
// Copied from KotlinCompile
if (reportingSettings().buildReportMode == BuildReportMode.VERBOSE) {
args.reportPerf = true
@@ -36,17 +36,16 @@ internal open class KotlinJvmPlugin(
@Suppress("DEPRECATION") compilationsContainer: NamedDomainObjectContainer<out AbstractKotlinCompilation<KotlinJvmOptions>>
) {
extensionCompilerOptions.verbose.convention(logger.isDebugEnabled)
extensionCompilerOptions.moduleName.convention(baseModuleName())
compilationsContainer.configureEach {
val jvmCompilerOptions = it.compilerOptions.options as KotlinJvmCompilerOptions
KotlinJvmCompilerOptionsHelper.syncOptionsAsConvention(
from = extensionCompilerOptions,
into = jvmCompilerOptions
)
jvmCompilerOptions.moduleName.convention(
extensionCompilerOptions.moduleName.orElse(
@Suppress("DEPRECATION")
project.providers.provider { it.moduleName }
)
it.moduleNameForCompilation(extensionCompilerOptions.moduleName)
)
}
}
@@ -77,16 +76,16 @@ internal open class KotlinJvmPlugin(
.apply {
disambiguationClassifier = null // don't add anything to the task names
}
val kotlinExtension = project.kotlinExtension as KotlinJvmProjectExtension
kotlinExtension.target = target
super.apply(project)
project.configureCompilerOptionsForTarget(
kotlinExtension.compilerOptions,
target.compilations
)
super.apply(project)
project.pluginManager.apply(ScriptingGradleSubplugin::class.java)
}
@@ -15,11 +15,10 @@ import org.gradle.api.tasks.TaskProvider
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
import org.jetbrains.kotlin.gradle.dsl.KotlinCompile
import org.jetbrains.kotlin.gradle.plugin.*
import org.jetbrains.kotlin.gradle.plugin.mpp.HierarchyAttributeContainer
import org.jetbrains.kotlin.gradle.plugin.mpp.*
import org.jetbrains.kotlin.gradle.plugin.mpp.InternalKotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.filterModuleName
import org.jetbrains.kotlin.gradle.plugin.mpp.internal
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.archivesName
import org.jetbrains.kotlin.gradle.plugin.mpp.moduleNameForCompilation
import org.jetbrains.kotlin.gradle.tasks.KotlinCompilationTask
import org.jetbrains.kotlin.gradle.tasks.locateTask
import org.jetbrains.kotlin.gradle.utils.ObservableSet
@@ -151,11 +150,7 @@ internal class KotlinCompilationImpl constructor(
@Suppress("OVERRIDE_DEPRECATION")
override val moduleName: String
get() {
val baseName = target.project.archivesName.orNull ?: target.project.name
val suffix = if (compilationName == KotlinCompilation.MAIN_COMPILATION_NAME) "" else "_$compilationName"
return filterModuleName("$baseName$suffix")
}
get() = moduleNameForCompilation(target.project.baseModuleName()).get()
//endregion
@@ -6,10 +6,12 @@
package org.jetbrains.kotlin.gradle.plugin.mpp
import org.gradle.api.Project
import org.gradle.api.provider.Provider
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonCompilerOptions
import org.jetbrains.kotlin.gradle.dsl.KotlinCommonOptions
import org.jetbrains.kotlin.gradle.plugin.HasCompilerOptions
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilation
import org.jetbrains.kotlin.gradle.plugin.mpp.pm20.util.archivesName
import org.jetbrains.kotlin.gradle.tasks.AbstractKotlinCompile
import org.jetbrains.kotlin.gradle.utils.fileExtensionCasePermutations
import org.jetbrains.kotlin.gradle.utils.lowerCamelCaseName
@@ -76,6 +78,19 @@ internal fun KotlinCompilation<*>.disambiguateName(simpleName: String): String {
private val invalidModuleNameCharactersRegex = """[\\/\r\n\t]""".toRegex()
internal fun Project.baseModuleName(): Provider<String> = archivesName.orElse(project.name)
internal fun KotlinCompilation<*>.moduleNameForCompilation(
baseName: Provider<String>
): Provider<String> = baseName.map {
val suffix = if (compilationName == KotlinCompilation.MAIN_COMPILATION_NAME) {
""
} else {
"_${compilationName}"
}
filterModuleName("$it$suffix")
}
internal fun filterModuleName(moduleName: String): String =
moduleName.replace(invalidModuleNameCharactersRegex, "_")
@@ -66,9 +66,6 @@ abstract class KotlinCompile @Inject constructor(
KotlinCompilationTask<KotlinJvmCompilerOptions>,
UsesKotlinJavaToolchain {
@get:Internal // covered by compiler options
abstract override val moduleName: Property<String>
final override val kotlinOptions: KotlinJvmOptions = KotlinJvmOptionsCompat(
{ this },
compilerOptions
@@ -111,6 +108,14 @@ abstract class KotlinCompile @Inject constructor(
set(value) = libraries.setFrom(value)
get() = libraries
@get:Deprecated(
message = "Please migrate to compilerOptions.moduleName",
replaceWith = ReplaceWith("compilerOptions.moduleName")
)
@get:Optional
@get:Input
abstract override val moduleName: Property<String>
@get:Input
abstract val useKotlinAbiSnapshot: Property<Boolean>
@@ -163,6 +168,9 @@ abstract class KotlinCompile @Inject constructor(
@get:Input
internal abstract val jvmTargetValidationMode: Property<PropertiesProvider.JvmTargetValidationMode>
@get:Internal
internal val nagTaskModuleNameUsage: Property<Boolean> = objectFactory.propertyWithConvention(false)
@get:Internal
internal val scriptDefinitions: ConfigurableFileCollection = objectFactory.fileCollection()
@@ -239,6 +247,9 @@ abstract class KotlinCompile @Inject constructor(
KotlinJvmCompilerOptionsHelper.fillCompilerArguments(compilerOptions, args)
overrideArgsUsingTaskModuleNameWithWarning(args)
requireNotNull(args.moduleName)
val localExecutionTimeFreeCompilerArgs = executionTimeFreeCompilerArgs
if (localExecutionTimeFreeCompilerArgs != null) {
args.freeArgs = localExecutionTimeFreeCompilerArgs
@@ -282,6 +293,21 @@ abstract class KotlinCompile @Inject constructor(
}
}
@Suppress("DEPRECATION")
protected fun overrideArgsUsingTaskModuleNameWithWarning(
args: K2JVMCompilerArguments
) {
val taskModuleName = moduleName.orNull
if (taskModuleName != null) {
if (nagTaskModuleNameUsage.get()) {
logger.warn(
"w: $path 'KotlinJvmCompile.moduleName' is deprecated, please migrate to 'compilerOptions.moduleName'!"
)
}
args.moduleName = taskModuleName
}
}
override fun callCompilerAsync(
args: K2JVMCompilerArguments,
inputChanges: InputChanges,
@@ -26,5 +26,8 @@ class KotlinJvmCompilerArgumentsProvider
val friendPaths: FileCollection = taskProvider.friendPaths
val compileClasspath: Iterable<File> = taskProvider.libraries
val destinationDir: File = taskProvider.destinationDirectory.get().asFile
@Suppress("DEPRECATION")
val taskModuleName: String? = taskProvider.moduleName.orNull
val nagTaskModuleNameUsage: Boolean = taskProvider.nagTaskModuleNameUsage.get()
internal val compilerOptions: KotlinJvmCompilerOptions = taskProvider.compilerOptions
}
@@ -39,7 +39,7 @@ import org.jetbrains.kotlin.project.model.LanguageSettings
*/
internal abstract class AbstractKotlinCompileConfig<TASK : AbstractKotlinCompile<*>>(
project: Project,
private val ext: KotlinTopLevelExtension,
val ext: KotlinTopLevelExtension,
private val languageSettings: Provider<LanguageSettings>
) : TaskConfigAction<TASK>(project) {
@@ -146,7 +146,7 @@ internal abstract class AbstractKotlinCompileConfig<TASK : AbstractKotlinCompile
compilation.internal.configurations.pluginConfiguration
)
}
task.moduleName.set(providers.provider { compilationInfo.moduleName })
@Suppress("DEPRECATION")
task.ownModuleName.set(project.provider { compilationInfo.moduleName })
task.sourceSetName.value(providers.provider { compilationInfo.compilationName })
@@ -39,6 +39,7 @@ internal class KaptGenerateStubsConfig : BaseKotlinCompileConfig<KaptGenerateStu
configureTask { task ->
val kotlinCompileTask = kotlinTaskProvider.get()
task.useModuleDetection.value(kotlinCompileTask.useModuleDetection).disallowChanges()
@Suppress("DEPRECATION")
task.moduleName.value(kotlinCompileTask.moduleName).disallowChanges()
task.libraries.from({ kotlinCompileTask.libraries - project.files(kaptClassesDir) })
task.compileTaskCompilerOptions.set(providers.provider { kotlinCompileTask.compilerOptions })
@@ -28,6 +28,7 @@ internal open class BaseKotlin2JsCompileConfig<TASK : Kotlin2JsCompile>(
configureAdditionalFreeCompilerArguments(task, compilation)
task.compilerOptions.moduleName.convention(compilation.moduleName)
task.moduleName.set(providers.provider { compilation.moduleName })
@Suppress("DEPRECATION")
task.outputFileProperty.value(
@@ -22,6 +22,7 @@ internal class KotlinCompileCommonConfig(
}
).disallowChanges()
task.refinesMetadataPaths.from(compilationInfo.refinesPaths).disallowChanges()
task.moduleName.set(providers.provider { compilationInfo.moduleName })
}
}
}
@@ -8,6 +8,8 @@ package org.jetbrains.kotlin.gradle.tasks.configuration
import org.gradle.api.Project
import org.gradle.api.attributes.Attribute
import org.gradle.api.provider.Provider
import org.jetbrains.kotlin.gradle.dsl.KotlinAndroidProjectExtension
import org.jetbrains.kotlin.gradle.dsl.KotlinJvmProjectExtension
import org.jetbrains.kotlin.gradle.dsl.KotlinTopLevelExtension
import org.jetbrains.kotlin.gradle.internal.transforms.ClasspathEntrySnapshotTransform
import org.jetbrains.kotlin.gradle.plugin.KotlinCompilationInfo
@@ -84,6 +86,14 @@ internal open class BaseKotlinCompileConfig<TASK : KotlinCompile> : AbstractKotl
providers.provider {
task.parentKotlinOptions.orNull?.moduleName ?: compilationInfo.moduleName
})
// In case of 'org.jetbrains.kotlin.jvm' and 'org.jetbrains.kotlin.android' plugins module name will be pre-configured
if (ext !is KotlinJvmProjectExtension && ext !is KotlinAndroidProjectExtension) {
@Suppress("DEPRECATION")
task.moduleName.set(providers.provider { compilationInfo.moduleName })
} else {
task.nagTaskModuleNameUsage.set(true)
}
}
}
}
@@ -91,6 +91,7 @@ class KotlinCompileApiTest {
assertEquals(setOf(pluginDependency, anotherCompilerPlugin), taskImpl.pluginClasspath.files)
}
@Suppress("DEPRECATION")
@Test
fun testModuleName() {
taskApi.moduleName.set("foo")
@@ -10,16 +10,22 @@ import org.gradle.api.file.DirectoryProperty
import org.gradle.api.model.ObjectFactory
import org.gradle.api.plugins.BasePluginConvention
import org.gradle.api.provider.Property
import org.gradle.api.provider.ProviderFactory
import org.jetbrains.kotlin.gradle.utils.chainedFinalizeValueOnRead
import org.jetbrains.kotlin.gradle.utils.propertyWithConvention
internal class BasePluginConfigurationG70(
private val basePluginConvention: BasePluginConvention,
private val objects: ObjectFactory
private val objects: ObjectFactory,
private val providerFactory: ProviderFactory,
) : BasePluginConfiguration {
override val archivesName: Property<String>
get() = objects
.propertyWithConvention(basePluginConvention.archivesBaseName)
.propertyWithConvention(
providerFactory.provider {
basePluginConvention.archivesBaseName
}
)
.chainedFinalizeValueOnRead()
override val distsDirectory: DirectoryProperty
@@ -32,7 +38,8 @@ internal class BasePluginConfigurationG70(
override fun getInstance(project: Project): BasePluginConfiguration {
return BasePluginConfigurationG70(
project.convention.getPlugin(BasePluginConvention::class.java),
project.objects
project.objects,
project.providers
)
}
}
@@ -10,16 +10,20 @@ import org.gradle.api.file.DirectoryProperty
import org.gradle.api.model.ObjectFactory
import org.gradle.api.plugins.BasePluginConvention
import org.gradle.api.provider.Property
import org.gradle.api.provider.ProviderFactory
import org.jetbrains.kotlin.gradle.utils.chainedFinalizeValueOnRead
import org.jetbrains.kotlin.gradle.utils.propertyWithConvention
internal class BasePluginConfigurationG6(
private val basePluginConvention: BasePluginConvention,
private val objects: ObjectFactory
private val objects: ObjectFactory,
private val providerFactory: ProviderFactory,
) : BasePluginConfiguration {
override val archivesName: Property<String>
get() = objects
.propertyWithConvention(basePluginConvention.archivesBaseName)
.propertyWithConvention(
providerFactory.provider { basePluginConvention.archivesBaseName }
)
.chainedFinalizeValueOnRead()
override val distsDirectory: DirectoryProperty
@@ -32,7 +36,8 @@ internal class BasePluginConfigurationG6(
override fun getInstance(project: Project): BasePluginConfiguration {
return BasePluginConfigurationG6(
project.convention.getPlugin(BasePluginConvention::class.java),
project.objects
project.objects,
project.providers
)
}
}