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 77f83363414..5f7ad3b8271 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 @@ -389,6 +389,9 @@ open class KotlinNativeTargetConfigurator( "" } + private val KotlinNativeCompilation.isMainCompilation: Boolean + get() = name == KotlinCompilation.MAIN_COMPILATION_NAME + private fun Project.createTestTask(compilation: KotlinNativeCompilation, testExecutableLinkTask: KotlinNativeCompile) { val compilationSuffix = compilation.name.takeIf { it != KotlinCompilation.TEST_COMPILATION_NAME }.orEmpty() val taskName = lowerCamelCaseName(compilation.target.targetName, compilationSuffix, testTaskNameSuffix) @@ -412,6 +415,58 @@ open class KotlinNativeTargetConfigurator( } } + private fun Project.binaryOutputDirectory( + buildType: NativeBuildType, + kind: NativeOutputKind, + compilation: KotlinNativeCompilation + ): File { + val targetSubDirectory = compilation.target.disambiguationClassifier?.let { "$it/" }.orEmpty() + val buildTypeSubDirectory = buildType.name.toLowerCase() + val kindSubDirectory = kind.outputDirectoryName + + return buildDir.resolve("bin/$targetSubDirectory${compilation.name}/$buildTypeSubDirectory/$kindSubDirectory") + } + + private fun Project.klibOutputDirectory( + compilation: KotlinNativeCompilation + ): File { + val targetSubDirectory = compilation.target.disambiguationClassifier?.let { "$it/" }.orEmpty() + return buildDir.resolve("classes/kotlin/$targetSubDirectory${compilation.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) { + 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 buildTypes = compilation.buildTypes @@ -442,25 +497,7 @@ open class KotlinNativeTargetConfigurator( optimized = buildType.optimized debuggable = buildType.debuggable - if (outputKind == CompilerOutputKind.FRAMEWORK) { - outputs.dir(outputFile) - } else { - outputs.file(outputFile) - } - - outputFile.set(provider { - val targetSubDirectory = compilation.target.disambiguationClassifier?.let { "$it/" }.orEmpty() - val buildTypeSubDirectory = buildType.name.toLowerCase() - val compilationName = compilation.compilationName - val prefix = compilerOutputKind.prefix(konanTarget) - val suffix = compilerOutputKind.suffix(konanTarget) - var filename = "$prefix$compilationName$suffix" - if (outputKind == CompilerOutputKind.FRAMEWORK) { - filename = filename.replace('-', '_') - } - File(project.buildDir, "bin/$targetSubDirectory$compilationName/$buildTypeSubDirectory/$filename") - }) - + registerOutputFiles(binaryOutputDirectory(buildType, kind, compilation)) dependsOnCompilerDownloading() linkAll.dependsOn(this) } @@ -511,17 +548,7 @@ open class KotlinNativeTargetConfigurator( "compilation for target '${compilation.platformType.name}'" enabled = compilation.target.konanTarget.enabledOnCurrentHost - outputs.file(outputFile) - outputFile.set(provider { - val targetSubDirectory = compilation.target.disambiguationClassifier?.let { "$it/" }.orEmpty() - val compilationName = compilation.compilationName - val klibName = if (compilation.name == KotlinCompilation.MAIN_COMPILATION_NAME) - project.name - else - compilationName - File(project.buildDir, "classes/kotlin/$targetSubDirectory$compilationName/$klibName.klib") - }) - + registerOutputFiles(klibOutputDirectory(compilation)) dependsOnCompilerDownloading() compilation.output.tryAddClassesDir { project.files(this.outputFile).builtBy(this) diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/NativeBinaryTypes.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/NativeBinaryTypes.kt index 55a345ea819..ce04d124bfd 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/NativeBinaryTypes.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/NativeBinaryTypes.kt @@ -21,18 +21,40 @@ enum class NativeBuildType(val optimized: Boolean, val debuggable: Boolean): Nam enum class NativeOutputKind( val compilerOutputKind: CompilerOutputKind, val taskNameClassifier: String, + val outputDirectoryName: String = taskNameClassifier, val description: String = taskNameClassifier, val additionalCompilerFlags: List = emptyList(), val runtimeUsageName: String? = null, val linkUsageName: String? = null, - val publishable: Boolean = true + val publishable: Boolean = true // Not used yet. ) { EXECUTABLE( CompilerOutputKind.PROGRAM, "executable", description = "an executable", - runtimeUsageName = Usage.NATIVE_RUNTIME + runtimeUsageName = Usage.NATIVE_RUNTIME, + publishable = false ), + DYNAMIC( + CompilerOutputKind.DYNAMIC, + "shared", + description = "a dynamic library", + runtimeUsageName = Usage.NATIVE_RUNTIME, + linkUsageName = Usage.NATIVE_LINK, + publishable = false + ) { + override fun availableFor(target: KonanTarget) = target != KonanTarget.WASM32 + }, + STATIC( + CompilerOutputKind.STATIC, + "static", + description = "a static library", + runtimeUsageName = Usage.NATIVE_RUNTIME, + linkUsageName = Usage.NATIVE_LINK, + publishable = false + ) { + override fun availableFor(target: KonanTarget) = target != KonanTarget.WASM32 + }, FRAMEWORK( CompilerOutputKind.FRAMEWORK, "framework", diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinCompilations.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinCompilations.kt index 071b0fe76e9..03ae87fa7a1 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinCompilations.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinCompilations.kt @@ -309,15 +309,6 @@ class KotlinNativeCompilation( allSources += sourceSet.kotlin } - // TODO: Can we do it better? - companion object { - val DEBUG = NativeBuildType.DEBUG - val RELEASE = NativeBuildType.RELEASE - - val EXECUTABLE = NativeOutputKind.EXECUTABLE - val FRAMEWORK = NativeOutputKind.FRAMEWORK - } - } private object CompilationSourceSetUtil { diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinTargets.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinTargets.kt index 76e3ebadf3c..4679a32c84c 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinTargets.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/plugin/mpp/kotlinTargets.kt @@ -150,6 +150,16 @@ class KotlinNativeTarget( "org.jetbrains.kotlin.native.target", String::class.java ) + + // TODO: Can we do it better? + // User-visible constants + val DEBUG = NativeBuildType.DEBUG + val RELEASE = NativeBuildType.RELEASE + + val EXECUTABLE = NativeOutputKind.EXECUTABLE + val FRAMEWORK = NativeOutputKind.FRAMEWORK + val DYNAMIC = NativeOutputKind.DYNAMIC + val STATIC = NativeOutputKind.STATIC } }