diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/NewMultiplatformIT.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/NewMultiplatformIT.kt index c357b85dfb6..31cfe6b5918 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/NewMultiplatformIT.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/NewMultiplatformIT.kt @@ -663,6 +663,20 @@ class NewMultiplatformIT : BaseGradleIT() { "build/bin/$nativeHostTargetName/main/release/static/$staticPrefix${baseName}_api.h" ) + val klibPrefix = CompilerOutputKind.LIBRARY.prefix(HostManager.host) + val klibSuffix = CompilerOutputKind.LIBRARY.suffix(HostManager.host) + val klibPath = "${targetClassesDir(nativeHostTargetName)}${klibPrefix}native-lib$klibSuffix" + + val frameworkPrefix = CompilerOutputKind.FRAMEWORK.prefix(HostManager.host) + val frameworkSuffix = CompilerOutputKind.FRAMEWORK.suffix(HostManager.host) + val frameworkPaths = listOf( + "build/bin/$nativeHostTargetName/main/debug/framework/$frameworkPrefix$baseName$frameworkSuffix.dSYM", + "build/bin/$nativeHostTargetName/main/debug/framework/$frameworkPrefix$baseName$frameworkSuffix", + "build/bin/$nativeHostTargetName/main/release/framework/$frameworkPrefix$baseName$frameworkSuffix" + ) + .takeIf { HostManager.hostIsMac } + .orEmpty() + val taskSuffix = nativeHostTargetName.capitalize() val linkTasks = listOf( ":linkDebugShared$taskSuffix", @@ -671,25 +685,48 @@ class NewMultiplatformIT : BaseGradleIT() { ":linkReleaseStatic$taskSuffix" ) + val klibTask = ":compileKotlin$taskSuffix" + + val frameworkTasks = listOf(":linkDebugFramework$taskSuffix", ":linkReleaseFramework$taskSuffix") + .takeIf { HostManager.hostIsMac } + .orEmpty() + + // Building build("assemble") { assertSuccessful() sharedPaths.forEach { assertFileExists(it) } staticPaths.forEach { assertFileExists(it) } headerPaths.forEach { assertFileExists(it) } + frameworkPaths.forEach { assertFileExists(it) } + assertFileExists(klibPath) } + // Test that all up-to date checks are correct build("assemble") { assertSuccessful() assertTasksUpToDate(linkTasks) + assertTasksUpToDate(frameworkTasks) + assertTasksUpToDate(klibTask) } + // Remove outputs and check that they are rebuilt. assertTrue(projectDir.resolve(headerPaths[0]).delete()) + assertTrue(projectDir.resolve(klibPath).delete()) + if (HostManager.hostIsMac) { + assertTrue(projectDir.resolve(frameworkPaths[0]).deleteRecursively()) + } build("assemble") { assertSuccessful() assertTasksUpToDate(linkTasks.drop(1)) assertTasksExecuted(linkTasks[0]) + assertTasksExecuted(klibTask) + + if (HostManager.hostIsMac) { + assertTasksUpToDate(frameworkTasks.drop(1)) + assertTasksExecuted(frameworkTasks[0]) + } } } diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-native-libraries/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-native-libraries/build.gradle index ff6bc7ef586..8f7df251a9f 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-native-libraries/build.gradle +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/new-mpp-native-libraries/build.gradle @@ -21,12 +21,15 @@ repositories { kotlin { targets { - fromPreset(presets.macosX64, 'macos64') + fromPreset(presets.macosX64, 'macos64') { + compilations.main.outputKinds = [FRAMEWORK] + } + fromPreset(presets.linuxX64, 'linux64') fromPreset(presets.mingwX64, 'mingw64') configure([linux64, mingw64, macos64]) { - compilations.main.outputKinds 'DYNAMIC', 'STATIC' + compilations.main.outputKinds += [DYNAMIC, STATIC] } } } \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetConfigurator.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetConfigurator.kt index 6a3d8cff8bc..03efbf7677c 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetConfigurator.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/KotlinTargetConfigurator.kt @@ -437,41 +437,6 @@ open class KotlinNativeTargetConfigurator( compilerPluginClasspath = project.configurations.getByName(NATIVE_COMPILER_PLUGIN_CLASSPATH_CONFIGURATION_NAME) } - private fun KotlinNativeCompile.registerOutputFiles(outputDirectory: File) { - val konanTarget = compilation.target.konanTarget - - val prefix = outputKind.prefix(konanTarget) - val suffix = outputKind.suffix(konanTarget) - val baseName = if (compilation.isMainCompilation) project.name else compilation.name - - outputFile.set(project.provider { - var filename = "$prefix$baseName$suffix" - if (outputKind == CompilerOutputKind.FRAMEWORK || - outputKind == CompilerOutputKind.STATIC || - outputKind == CompilerOutputKind.DYNAMIC || - outputKind == CompilerOutputKind.PROGRAM && konanTarget == KonanTarget.WASM32 - ) { - filename = filename.replace('-', '_') - } - - outputDirectory.resolve(filename) - }) - - // Register outputs - if (outputKind == CompilerOutputKind.FRAMEWORK) { - outputs.dir(outputFile) - } else { - outputs.file(outputFile) - } - - if (outputKind == CompilerOutputKind.STATIC || outputKind == CompilerOutputKind.DYNAMIC) { - outputs.file(project.provider { - val apiFileName = "$prefix${baseName}_api.h".replace('-', '_') - outputDirectory.resolve(apiFileName) - }) - } - } - private fun Project.createBinaryLinkTasks(compilation: KotlinNativeCompilation) = whenEvaluated { val konanTarget = compilation.target.konanTarget val availableOutputKinds = compilation.outputKinds.filter { it.availableFor(konanTarget) } @@ -495,7 +460,7 @@ open class KotlinNativeTargetConfigurator( optimized = buildType.optimized debuggable = buildType.debuggable - registerOutputFiles(binaryOutputDirectory(buildType, kind, compilation)) + destinationDir = binaryOutputDirectory(buildType, kind, compilation) addCompilerPlugins() linkAll.dependsOn(this) @@ -582,7 +547,7 @@ open class KotlinNativeTargetConfigurator( "compilation for target '${compilation.platformType.name}'." enabled = compilation.target.konanTarget.enabledOnCurrentHost - registerOutputFiles(klibOutputDirectory(compilation)) + destinationDir = klibOutputDirectory(compilation) addCompilerPlugins() compilation.output.tryAddClassesDir { project.files(this.outputFile).builtBy(this) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinNativeTasks.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinNativeTasks.kt index 34c0ab992a7..8f4fa6635a1 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinNativeTasks.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/tasks/KotlinNativeTasks.kt @@ -20,6 +20,10 @@ import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeCompilation import org.jetbrains.kotlin.gradle.plugin.mpp.defaultSourceSetName import org.jetbrains.kotlin.gradle.plugin.mpp.isMainCompilation import org.jetbrains.kotlin.konan.target.CompilerOutputKind +import org.jetbrains.kotlin.konan.target.CompilerOutputKind.DYNAMIC +import org.jetbrains.kotlin.konan.target.CompilerOutputKind.FRAMEWORK +import org.jetbrains.kotlin.konan.target.CompilerOutputKind.PROGRAM +import org.jetbrains.kotlin.konan.target.CompilerOutputKind.STATIC import org.jetbrains.kotlin.konan.target.KonanTarget import java.io.File @@ -78,19 +82,11 @@ private fun FileCollection.filterOutPublishableInteropLibs(project: Project): Fi } } - // endregion - open class KotlinNativeCompile : AbstractCompile() { init { - @Suppress("LeakingThis") - setDestinationDir(project.provider { - val output = outputFile.get() - if (output.isDirectory) output else output.parentFile - }) - sourceCompatibility = "1.6" targetCompatibility = "1.6" } @@ -178,9 +174,21 @@ open class KotlinNativeCompile : AbstractCompile() { val kotlinNativeVersion: String @Input get() = project.konanVersion.toString() - // We manually register this property as output file or directory depending on output kind. + // OutputFile is located under the destinationDir, so there is no need to register it as a separate output. @Internal - val outputFile: Property = project.objects.property(File::class.java) + val outputFile: Provider = project.provider { + val konanTarget = compilation.target.konanTarget + + val prefix = outputKind.prefix(konanTarget) + val suffix = outputKind.suffix(konanTarget) + val baseName = if (compilation.isMainCompilation) project.name else compilation.name + var filename = "$prefix$baseName$suffix" + if (outputKind in listOf(FRAMEWORK, STATIC, DYNAMIC) || outputKind == PROGRAM && konanTarget == KonanTarget.WASM32) { + filename = filename.replace('-', '_') + } + + destinationDir.resolve(filename) + } // endregion @Internal