diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/CompilerOptionsIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/CompilerOptionsIT.kt index 06cd54c6ddf..f8ff762762a 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/CompilerOptionsIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/CompilerOptionsIT.kt @@ -420,7 +420,7 @@ internal class CompilerOptionsIT : KGPBaseTest() { """.trimMargin() ) - build("compileKotlinHost", forceOutput = true) { + build("compileKotlinHost") { val expectedArg = "-progressive" val compilerArgs = output .substringAfter("Arguments = [") @@ -435,4 +435,94 @@ internal class CompilerOptionsIT : KGPBaseTest() { } } } + + @DisplayName("KT-57823: should be possible to configure native module name via compilation") + @NativeGradlePluginTests + @GradleTest + fun passesModuleNameFromNativeCompilation(gradleVersion: GradleVersion) { + project( + projectName = "new-mpp-lib-and-app/sample-lib", + gradleVersion = gradleVersion, + // We need to get specific task output as commonizer may run first producing + // arguments as well in output + buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.DEBUG) + ) { + buildGradle.appendText( + //language=Groovy + """ + | + |kotlin { + | targets { + | named("linux64", org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget.class) { + | compilations.all { + | compilerOptions.options.moduleName.set("i-am-your-module-name") + | } + | } + | } + |} + | + """.trimMargin() + ) + + build(":compileNativeMainKotlinMetadata") { + assertTasksExecuted(":compileNativeMainKotlinMetadata") + + extractNativeTasksCommandLineArgumentsFromOutput(":compileNativeMainKotlinMetadata") { + assertCommandLineArgumentsContain("-module-name", "com.example:sample-lib_nativeMain") + } + } + + build(":compileKotlinLinux64") { + assertTasksExecuted(":compileKotlinLinux64") + + extractNativeTasksCommandLineArgumentsFromOutput(":compileKotlinLinux64") { + assertCommandLineArgumentsContain("-module-name", "i-am-your-module-name") + } + } + } + } + + @DisplayName("KT-57823: uses archivesName value for native compilation module name convention") + @NativeGradlePluginTests + @GradleTest + fun nativeCompilationModuleNameConvention(gradleVersion: GradleVersion) { + project( + projectName = "new-mpp-lib-and-app/sample-lib", + gradleVersion = gradleVersion, + // We need to get specific task output as commonizer may run first producing + // arguments as well in output + // TODO Yahor: remove 'configurationCache = false' once it will be merged into `master` - issue due to the build reports error + buildOptions = defaultBuildOptions.copy(logLevel = LogLevel.DEBUG, configurationCache = false) + ) { + buildGradle.modify { + val buildScript = """ + |${it.substringBefore("apply plugin:")} + |apply plugin: 'base' + |apply plugin: ${it.substringAfter("apply plugin:")} + | + """.trimMargin() + if (gradleVersion < GradleVersion.version("7.1")) { + "$buildScript\narchivesBaseName = \"myNativeLib\"" + } else { + "$buildScript\nbase.archivesName.set(\"myNativeLib\")" + } + } + + build(":compileNativeMainKotlinMetadata") { + assertTasksExecuted(":compileNativeMainKotlinMetadata") + + extractNativeTasksCommandLineArgumentsFromOutput(":compileNativeMainKotlinMetadata") { + assertCommandLineArgumentsContain("-module-name", "com.example:myNativeLib_nativeMain") + } + } + + build(":compileKotlinLinux64") { + assertTasksExecuted(":compileKotlinLinux64") + + extractNativeTasksCommandLineArgumentsFromOutput(":compileKotlinLinux64") { + assertCommandLineArgumentsContain("-module-name", "com.example:myNativeLib") + } + } + } + } } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/compilationImpl/factory/KotlinCompilerOptionsFactories.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/compilationImpl/factory/KotlinCompilerOptionsFactories.kt index 97eeb211fe8..191c9b09699 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/compilationImpl/factory/KotlinCompilerOptionsFactories.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/compilationImpl/factory/KotlinCompilerOptionsFactories.kt @@ -8,8 +8,11 @@ package org.jetbrains.kotlin.gradle.plugin.mpp.compilationImpl.factory import org.jetbrains.kotlin.gradle.dsl.* import org.jetbrains.kotlin.gradle.plugin.HasCompilerOptions import org.jetbrains.kotlin.gradle.plugin.KotlinTarget +import org.jetbrains.kotlin.gradle.plugin.mpp.baseModuleName +import org.jetbrains.kotlin.gradle.plugin.mpp.moduleNameForCompilation import org.jetbrains.kotlin.gradle.targets.native.NativeCompilerOptions import org.jetbrains.kotlin.gradle.utils.configureExperimentalTryK2 +import org.jetbrains.kotlin.gradle.utils.klibModuleName internal object KotlinMultiplatformCommonCompilerOptionsFactory : KotlinCompilationImplFactory.KotlinCompilerOptionsFactory { override fun create(target: KotlinTarget, compilationName: String): KotlinCompilationImplFactory.KotlinCompilerOptionsFactory.Options { @@ -32,6 +35,14 @@ internal object KotlinNativeCompilerOptionsFactory : KotlinCompilationImplFactor override fun create(target: KotlinTarget, compilationName: String): KotlinCompilationImplFactory.KotlinCompilerOptionsFactory.Options { val compilerOptions = NativeCompilerOptions(target.project) + compilerOptions.options.moduleName.convention( + target.project.klibModuleName( + moduleNameForCompilation( + compilationName, + target.project.baseModuleName() + ) + ) + ) val kotlinOptions = object : KotlinCommonOptions { override val options get() = compilerOptions.options diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinCompilations.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinCompilations.kt index c073c9efa74..11e6601fadc 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinCompilations.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinCompilations.kt @@ -86,8 +86,9 @@ private val invalidModuleNameCharactersRegex = """[\\/\r\n\t]""".toRegex() internal fun Project.baseModuleName(): Provider = archivesName.orElse(project.name) -internal fun KotlinCompilation<*>.moduleNameForCompilation( - baseName: Provider = project.baseModuleName() +internal fun moduleNameForCompilation( + compilationName: String, + baseName: Provider ): Provider = baseName.map { val suffix = if (compilationName == KotlinCompilation.MAIN_COMPILATION_NAME) { "" @@ -97,6 +98,10 @@ internal fun KotlinCompilation<*>.moduleNameForCompilation( filterModuleName("$it$suffix") } +internal fun KotlinCompilation<*>.moduleNameForCompilation( + baseName: Provider = project.baseModuleName() +): Provider = moduleNameForCompilation(compilationName, baseName) + internal fun filterModuleName(moduleName: String): String = moduleName.replace(invalidModuleNameCharactersRegex, "_") diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetConfigurator.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetConfigurator.kt index 8243f398fac..54d74c1c0ca 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetConfigurator.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/targets/native/KotlinNativeTargetConfigurator.kt @@ -47,7 +47,6 @@ import org.jetbrains.kotlin.gradle.testing.internal.configureConventions import org.jetbrains.kotlin.gradle.testing.internal.kotlinTestRegistry import org.jetbrains.kotlin.gradle.testing.testTaskName import org.jetbrains.kotlin.gradle.utils.Xcode -import org.jetbrains.kotlin.gradle.utils.klibModuleName import org.jetbrains.kotlin.gradle.utils.newInstance import org.jetbrains.kotlin.konan.target.HostManager import org.jetbrains.kotlin.konan.target.KonanTarget @@ -396,7 +395,6 @@ open class KotlinNativeTargetConfigurator : AbstractKotl it.enabled = konanTarget.enabledOnCurrentHost it.destinationDirectory.set(project.klibOutputDirectory(compilationInfo).resolve("klib")) - it.compilerOptions.moduleName.set(project.klibModuleName(it.baseName)) val propertiesProvider = PropertiesProvider(project) if (propertiesProvider.useK2 == true) { it.compilerOptions.useK2.set(true) diff --git a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/klibUtils.kt b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/klibUtils.kt index fb16ee7c027..686291182d9 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/klibUtils.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/common/kotlin/org/jetbrains/kotlin/gradle/utils/klibUtils.kt @@ -6,6 +6,14 @@ package org.jetbrains.kotlin.gradle.utils import org.gradle.api.Project +import org.gradle.api.provider.Provider +import org.jetbrains.kotlin.gradle.plugin.mpp.baseModuleName + +internal fun Project.klibModuleName( + baseName: Provider = baseModuleName() +): Provider = baseName.map { + klibModuleName(it) +} internal fun Project.klibModuleName(baseName: String = project.name): String = if (group.toString().isNotEmpty()) "$group:$baseName" else baseName \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/compilerArgumetns/KotlinNativeCompilationModuleNameTest.kt b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/compilerArgumetns/KotlinNativeCompilationModuleNameTest.kt new file mode 100644 index 00000000000..eb3bb36eb9a --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin/src/functionalTest/kotlin/org/jetbrains/kotlin/gradle/unitTests/compilerArgumetns/KotlinNativeCompilationModuleNameTest.kt @@ -0,0 +1,85 @@ +/* + * Copyright 2010-2023 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.gradle.unitTests.compilerArgumetns + +import org.jetbrains.kotlin.gradle.dsl.KotlinNativeCompilerOptions +import org.jetbrains.kotlin.gradle.dsl.multiplatformExtension +import org.jetbrains.kotlin.gradle.util.buildProjectWithMPP +import org.jetbrains.kotlin.gradle.util.main +import org.jetbrains.kotlin.gradle.util.test +import kotlin.test.* + +class KotlinNativeCompilationModuleNameTest { + + @Test + fun `main compilation module name convention`() { + val project = buildProjectWithMPP( + projectBuilder = { + withName(PROJECT_NAME) + } + ) + val linuxX64Target = project.multiplatformExtension.linuxX64() + + project.evaluate() + + assertEquals( + PROJECT_NAME, + linuxX64Target.compilations.main.compilerOptions.options.moduleName.get(), + "Main compilation moduleName value is not expected!" + ) + } + + @Test + fun `test compilation module name convention`() { + val project = buildProjectWithMPP( + projectBuilder = { + withName(PROJECT_NAME) + } + ) + val linuxX64Target = project.multiplatformExtension.linuxX64() + + project.evaluate() + + assertEquals( + "${PROJECT_NAME}_test", + linuxX64Target.compilations.test.compilerOptions.options.moduleName.get(), + "Test compilation moduleName value is not expected!" + ) + } + + @Test + fun `Metadata compilation module name convention`() { + val project = buildProjectWithMPP( + projectBuilder = { + withName(PROJECT_NAME) + } + ) { + with(multiplatformExtension) { + targetHierarchy.default() + linuxX64() + linuxArm64() + } + } + + project.evaluate() + + val compilerOptions = project + .multiplatformExtension + .metadata() + .compilations + .getByName("linuxMain") + .compilerOptions.options as KotlinNativeCompilerOptions + assertEquals( + "${PROJECT_NAME}_linuxMain", + compilerOptions.moduleName.get(), + "Main compilation moduleName value is not expected!" + ) + } + + companion object { + const val PROJECT_NAME = "nativeProject" + } +} \ No newline at end of file