diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/InteropLibraryCreation.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/InteropLibraryCreation.kt index 6c8f9d67b4c..6b1754fe802 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/InteropLibraryCreation.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/InteropLibraryCreation.kt @@ -33,7 +33,8 @@ fun createInteropLibrary( manifest: Properties, dependencies: List, nopack: Boolean, - shortName: String? + shortName: String?, + staticLibraries: List ) { val version = KotlinLibraryVersioning( libraryVersion = null, @@ -58,6 +59,7 @@ fun createInteropLibrary( nativeBitcodeFiles.forEach(this::addNativeBitcode) addManifestAddend(manifest) addLinkDependencies(dependencies) + staticLibraries.forEach(this::addIncludedBinary) commit() } } diff --git a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/main.kt b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/main.kt index 91fcf436ffe..dc21c6cacdb 100644 --- a/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/main.kt +++ b/Interop/StubGenerator/src/main/kotlin/org/jetbrains/kotlin/native/interop/gen/jvm/main.kt @@ -377,7 +377,8 @@ private fun processCLib(flavorName: String, cinteropArguments: CInteropArguments manifest = def.manifestAddendProperties, dependencies = stdlibDependency + imports.requiredLibraries.toList(), nopack = cinteropArguments.nopack, - shortName = cinteropArguments.shortModuleName + shortName = cinteropArguments.shortModuleName, + staticLibraries = staticLibraries ) return null } diff --git a/backend.native/tests/build.gradle b/backend.native/tests/build.gradle index aae5db61fb9..6141a58535c 100644 --- a/backend.native/tests/build.gradle +++ b/backend.native/tests/build.gradle @@ -3506,6 +3506,28 @@ createInterop("auxiliaryCppSources") { it.extraOpts "-Xsource-compiler-option", "-std=c++17" } +createInterop("embedStaticLibraries") { + it.defFile 'interop/embedStaticLibraries/embedStaticLibraries.def' + it.headers "$projectDir/interop/embedStaticLibraries/embedStaticLibraries.h" + + // Note: also hardcoded in def file. + final String libDir = "$buildDir/embedStaticLibraries/" + + it.getByTarget(target.name).doFirst { + 1.upto(4) { + UtilsKt.buildStaticLibrary( + project, + [file("$projectDir/interop/embedStaticLibraries/${it}.c")], + file("$libDir/${it}.a"), + file("$libDir/${it}.objs"), + ) + } + } + + it.extraOpts '-staticLibrary', "$libDir/1.a" + it.extraOpts '-staticLibrary', "$libDir/2.a" +} + if (PlatformInfo.isAppleTarget(project)) { createInterop("objcSmoke") { it.defFile 'interop/objc/objcSmoke.def' @@ -3719,6 +3741,12 @@ interopTest("interop_auxiliarySources") { interop = 'auxiliaryCppSources' } +interopTest("interop_embedStaticLibraries") { + disabled = (project.testTarget == 'wasm32') // No interop for wasm yet. + source = "interop/embedStaticLibraries/main.kt" + interop = 'embedStaticLibraries' +} + interopTest("interop_values") { disabled = (project.testTarget == 'wasm32') // No interop for wasm yet. source = "interop/basics/values.kt" diff --git a/backend.native/tests/interop/embedStaticLibraries/1.c b/backend.native/tests/interop/embedStaticLibraries/1.c new file mode 100644 index 00000000000..1b08c920edb --- /dev/null +++ b/backend.native/tests/interop/embedStaticLibraries/1.c @@ -0,0 +1,3 @@ +int get1() { + return 1; +} diff --git a/backend.native/tests/interop/embedStaticLibraries/2.c b/backend.native/tests/interop/embedStaticLibraries/2.c new file mode 100644 index 00000000000..52b9914d8e6 --- /dev/null +++ b/backend.native/tests/interop/embedStaticLibraries/2.c @@ -0,0 +1,3 @@ +int get2() { + return 2; +} diff --git a/backend.native/tests/interop/embedStaticLibraries/3.c b/backend.native/tests/interop/embedStaticLibraries/3.c new file mode 100644 index 00000000000..17b9646ec50 --- /dev/null +++ b/backend.native/tests/interop/embedStaticLibraries/3.c @@ -0,0 +1,3 @@ +int get3() { + return 3; +} diff --git a/backend.native/tests/interop/embedStaticLibraries/4.c b/backend.native/tests/interop/embedStaticLibraries/4.c new file mode 100644 index 00000000000..ab697746441 --- /dev/null +++ b/backend.native/tests/interop/embedStaticLibraries/4.c @@ -0,0 +1,3 @@ +int get4() { + return 4; +} diff --git a/backend.native/tests/interop/embedStaticLibraries/embedStaticLibraries.def b/backend.native/tests/interop/embedStaticLibraries/embedStaticLibraries.def new file mode 100644 index 00000000000..686ec63efd0 --- /dev/null +++ b/backend.native/tests/interop/embedStaticLibraries/embedStaticLibraries.def @@ -0,0 +1,3 @@ +staticLibraries = \ + backend.native/tests/build/embedStaticLibraries/3.a \ + backend.native/tests/build/embedStaticLibraries/4.a diff --git a/backend.native/tests/interop/embedStaticLibraries/embedStaticLibraries.h b/backend.native/tests/interop/embedStaticLibraries/embedStaticLibraries.h new file mode 100644 index 00000000000..e481df854db --- /dev/null +++ b/backend.native/tests/interop/embedStaticLibraries/embedStaticLibraries.h @@ -0,0 +1,4 @@ +int get1(void); +int get2(void); +int get3(void); +int get4(void); diff --git a/backend.native/tests/interop/embedStaticLibraries/main.kt b/backend.native/tests/interop/embedStaticLibraries/main.kt new file mode 100644 index 00000000000..9f8e8902570 --- /dev/null +++ b/backend.native/tests/interop/embedStaticLibraries/main.kt @@ -0,0 +1,9 @@ +import kotlin.test.* +import embedStaticLibraries.* + +fun main() { + assertEquals(1, get1()) + assertEquals(2, get2()) + assertEquals(3, get3()) + assertEquals(4, get4()) +} diff --git a/build-tools/src/main/kotlin/org/jetbrains/kotlin/Utils.kt b/build-tools/src/main/kotlin/org/jetbrains/kotlin/Utils.kt index 9892faef254..983d13d98e9 100644 --- a/build-tools/src/main/kotlin/org/jetbrains/kotlin/Utils.kt +++ b/build-tools/src/main/kotlin/org/jetbrains/kotlin/Utils.kt @@ -319,4 +319,30 @@ fun Project.mergeManifestsByTargets(source: File, destination: File) { destinationProperties[KLIB_PROPERTY_NATIVE_TARGETS] = mergedNativeTargets.joinToString(" ") destinationFile.saveProperties(destinationProperties) +} + +fun Project.buildStaticLibrary(cSources: Collection, output: File, objDir: File) { + delete(objDir) + delete(output) + + val platform = platformManager.platform(testTarget) + + objDir.mkdirs() + exec { + it.commandLine(platform.clang.clangC( + "-c", + *cSources.map { it.absolutePath }.toTypedArray() + )) + it.workingDir(objDir) + } + + output.parentFile.mkdirs() + exec { + it.commandLine( + "${platform.configurables.absoluteLlvmHome}/bin/llvm-ar", + "-rc", + output, + *fileTree(objDir).files.toTypedArray() + ) + } } \ No newline at end of file