From 058ee77d8576ecd8371f28fd385e4b22595208bd Mon Sep 17 00:00:00 2001 From: Timofey Solonin Date: Tue, 19 Mar 2024 18:48:13 +0100 Subject: [PATCH 1/2] Reproduce external linkage failure Such failure happens when K/N produces a library archive of a static framework and the linkage happens outside, for example as part of an Xcode build process. --- sqliter-driver/build.gradle.kts | 60 ++++++++++++++++++++- sqliter-driver/externalLinkageSources/lib.m | 10 ++++ 2 files changed, 69 insertions(+), 1 deletion(-) create mode 100644 sqliter-driver/externalLinkageSources/lib.m diff --git a/sqliter-driver/build.gradle.kts b/sqliter-driver/build.gradle.kts index 3c54a9cb..3963e991 100644 --- a/sqliter-driver/build.gradle.kts +++ b/sqliter-driver/build.gradle.kts @@ -1,4 +1,7 @@ +import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget +import org.jetbrains.kotlin.gradle.plugin.mpp.NativeBuildType import org.jetbrains.kotlin.konan.target.HostManager +import java.io.ByteArrayOutputStream plugins { kotlin("multiplatform") @@ -26,7 +29,7 @@ fun configInterop(target: org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTar ) HostManager.hostIsMingw -> listOf("-linker-options", "-lsqlite3 -Lc:\\msys64\\mingw64\\lib") - else -> listOf("-linker-options", "-lsqlite3") + else -> emptyList() } } } @@ -55,6 +58,18 @@ kotlin { linuxArm64(), ) + if (HostManager.hostIsMac) { + val externalLinkageTask = tasks.register("testExternalLinkage") + tasks.named("allTests").configure { + dependsOn(externalLinkageTask) + } + testExternalLinkage(macosArm64(), "arm64-apple-macosx", "macosx", externalLinkageTask) + testExternalLinkage(macosX64(), "x86_64-apple-macosx", "macosx", externalLinkageTask) + testExternalLinkage(iosArm64(), "arm64-apple-ios", "iphoneos", externalLinkageTask) + testExternalLinkage(iosSimulatorArm64(), "arm64-apple-ios-simulator", "iphonesimulator", externalLinkageTask) + testExternalLinkage(iosX64(), "x86_64-apple-ios-simulator", "iphonesimulator", externalLinkageTask) + } + knTargets .forEach { target -> configInterop(target) @@ -134,3 +149,46 @@ listOf( "mingwX64Test", "linkDebugTestMingwX64", ).forEach { tasks.findByName(it)?.enabled = false } + +fun testExternalLinkage( + target: KotlinNativeTarget, + clangTriple: String, + sdkName: String, + aggregateTask: TaskProvider<*>, +) { + target.binaries.framework(buildTypes = listOf(NativeBuildType.DEBUG)) { + val framework = this + baseName = "sqliteDriver" + isStatic = true + + val testTask = tasks.register("testExternalLinkage${target.name}") { + val sourceFilesDirectory = layout.projectDirectory.dir("externalLinkageSources") + inputs.files(framework.linkTask, sourceFilesDirectory) + val output = layout.buildDirectory.file("testExternalLinkage/${target.name}") + outputs.dir(output) + doLast { + val sysrootPath: String = ByteArrayOutputStream().use { outputStream -> + project.exec { + commandLine("xcrun", "-sdk", sdkName, "--show-sdk-path") + standardOutput = outputStream + } + outputStream.toString().dropLast(1) + } + + exec { + commandLine( + "clang", "-target", clangTriple, "-fmodules", "-ObjC", + "-isysroot", sysrootPath, + "-F", framework.linkTask.outputFile.get().parentFile, + sourceFilesDirectory.file("lib.m"), + "-dynamiclib", "-o", output.get().asFile.resolve("output.dylib") + ) + } + } + } + + aggregateTask.configure { + dependsOn(testTask) + } + } +} \ No newline at end of file diff --git a/sqliter-driver/externalLinkageSources/lib.m b/sqliter-driver/externalLinkageSources/lib.m new file mode 100644 index 00000000..b2619c0d --- /dev/null +++ b/sqliter-driver/externalLinkageSources/lib.m @@ -0,0 +1,10 @@ +@import sqliteDriver; + +void forceSqliteSymbolsLoading(NSString * path, SqliteDriverDatabaseConfiguration * configuration) { + SqliteDriverNativeDatabaseManager * foo = [ + [SqliteDriverNativeDatabaseManager alloc] + initWithPath: path + configuration: configuration + ]; + [foo createSingleThreadedConnection]; +} \ No newline at end of file From a16ad84b554661072b36d9ee8178928c51aaa55e Mon Sep 17 00:00:00 2001 From: Timofey Solonin Date: Tue, 19 Mar 2024 18:48:24 +0100 Subject: [PATCH 2/2] Use autolinking to prevent the need to link with sqlite3 explicitly --- .../src/nativeInterop/cinterop/sqlite3.def | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/sqliter-driver/src/nativeInterop/cinterop/sqlite3.def b/sqliter-driver/src/nativeInterop/cinterop/sqlite3.def index 0cab7bab..0ada320e 100644 --- a/sqliter-driver/src/nativeInterop/cinterop/sqlite3.def +++ b/sqliter-driver/src/nativeInterop/cinterop/sqlite3.def @@ -5,4 +5,18 @@ headerFilter = sqlite3*.h linkerOpts.linux_x64 = -lpthread -ldl linkerOpts.macos_x64 = -lpthread -ldl +compilerOpts.ios_arm64 = -Xclang --linker-option=-lsqlite3 +compilerOpts.ios_x64 = -Xclang --linker-option=-lsqlite3 +compilerOpts.ios_simulator_arm64 = -Xclang --linker-option=-lsqlite3 +compilerOpts.watchos_arm32 = -Xclang --linker-option=-lsqlite3 +compilerOpts.watchos_arm64 = -Xclang --linker-option=-lsqlite3 +compilerOpts.watchos_x64 = -Xclang --linker-option=-lsqlite3 +compilerOpts.watchos_simulator_arm64 = -Xclang --linker-option=-lsqlite3 +compilerOpts.watchos_device_arm64 = -Xclang --linker-option=-lsqlite3 +compilerOpts.tvos_arm64 = -Xclang --linker-option=-lsqlite3 +compilerOpts.tvos_x64 = -Xclang --linker-option=-lsqlite3 +compilerOpts.tvos_simulator_arm64 = -Xclang --linker-option=-lsqlite3 +compilerOpts.macos_x64 = -Xclang --linker-option=-lsqlite3 +compilerOpts.macos_arm64 = -Xclang --linker-option=-lsqlite3 + noStringConversion = sqlite3_prepare_v2 sqlite3_prepare_v3