Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Kotlin Multiplatform build fails on macOS #5305

Open
JulianBissekkou opened this issue Jun 15, 2024 · 4 comments
Open

Kotlin Multiplatform build fails on macOS #5305

JulianBissekkou opened this issue Jun 15, 2024 · 4 comments
Labels

Comments

@JulianBissekkou
Copy link

JulianBissekkou commented Jun 15, 2024

SQLDelight Version

2.0.2

Operating System

Mac OS 14.3.1

Gradle Version

Gradle 8.7
Revision: 650af14d7653aa949fce5e886e685efc9cf97c10

Kotlin Version

1.9.23

Dialect

SQLite

AGP Version

No response

Describe the Bug

I have an iOS App that is supports macOS.

Screenshot 2024-06-15 at 13 18 06

After the build failed I added the linker flag -lsqlite3
Screenshot 2024-06-15 at 13 19 17

on iOS I am able to run the App and everything works as expected, however, on macOS the build fails.

Stacktrace

Undefined symbols for architecture arm64:
  "_sqlite3_enable_load_extension", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_enable_load_extension_wrapper190 in shared[12](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_load_extension", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_load_extension_wrapper189 in shared[12](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_mutex_held", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_mutex_held_wrapper213 in shared[12](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_mutex_notheld", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_mutex_notheld_wrapper214 in shared[12](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_unlock_notify", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_unlock_notify_wrapper239 in shared[12](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_win32_set_directory", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_win32_set_directory_wrapper171 in shared[12](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_win32_set_directory16", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_win32_set_directory16_wrapper173 in shared[12](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_win32_set_directory8", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_win32_set_directory8_wrapper172 in shared[12](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
ld: symbol(s) not found for architecture arm64
clang: error: linker command failed with exit code 1 (use -v to see invocation)


### Gradle Build Script

```gradle
plugins {
    alias(libs.plugins.kotlinMultiplatform)
    alias(libs.plugins.androidLibrary)
    alias(libs.plugins.kotlinxSerialization)
    alias(libs.plugins.ksp)
    alias(libs.plugins.kmpNativeCoroutines)
    alias(libs.plugins.sqldelight)
}

kotlin {
    androidTarget {
        compilations.all {
            kotlinOptions {
                jvmTarget = "11"
            }
        }
    }

    listOf(
        iosX64(),
        iosArm64(),
        iosSimulatorArm64(),
        macosArm64(),
        macosX64(),
    ).forEach { iosTarget ->
        iosTarget.binaries.framework {
            baseName = "Shared"
            isStatic = true
        }
    }

    sourceSets {
        androidMain.dependencies {
            implementation(libs.ktor.client.okhttp)
        }
        iosMain.dependencies {
            implementation(libs.native.driver)
        }
        macosMain.dependencies {
            implementation(libs.native.driver)
        }
        commonMain.dependencies {
            implementation(libs.ktor.client.core)
            implementation(libs.ktor.client.content.negotiation)
            implementation(libs.ktor.serialization.kotlinx.json)
            implementation(libs.koin.core)
            implementation(libs.runtime)
            implementation(libs.sqldelight.coroutine.extension)
            api(libs.kmm.viewmodel)
        }

        // Required by KMM-ViewModel
        all {
            languageSettings.optIn("kotlinx.cinterop.ExperimentalForeignApi")
            languageSettings.optIn("kotlin.experimental.ExperimentalObjCName")
        }
    }
}

android {
    namespace = "com.jetbrains.kmpapp.shared"
    compileSdk = 34
    compileOptions {
        sourceCompatibility = JavaVersion.VERSION_11
        targetCompatibility = JavaVersion.VERSION_11
    }
    defaultConfig {
        minSdk = 24
    }
}

sqldelight {
    databases {
        create("AppDatabase") {
            packageName.set("com.jetbrains.kmpapp")
        }
    }
    linkSqlite = true
}
@JulianBissekkou
Copy link
Author

I am pretty new to kmp, so I might be wrong here but I assume that the sqlite3 library on the mac is somehow "outdated" and does not contain the symbols.

I assume that the libary that is linked is a system library stored at /System/Library/Tcl/sqlite3/libtclsqlite3.dylib.
When I try to search for the first missing symbol I get no result:

nm /System/Library/Tcl/sqlite3/libtclsqlite3.dylib | grep load_extension  

However, when I do the same with sqllite installed by homebrew I get some results:

nm /opt/homebrew/Cellar/sqlite/3.42.0/lib/libsqlite3.dylib | grep load_extension
00000000000116b4 T _sqlite3_enable_load_extension
000000000001122c T _sqlite3_load_extension

Does anybody maybe know a workaround? This issue is currently blocking for us.

@kpgalligan
Copy link
Collaborator

I haven't built a macos app with sqldelight personally (I wrote most of the driver, or at least the original version). The tests run fine with -lsqlite3 without specifying the library search path, so I assume it's using a sqlite3 library from Xcode tools. libtclsqlite3 kind of seems like it's specific to tcl, but I've never used it. I would guess you'll need to include your own sqlite implementation.

Since you're building with Xcode, the easy solution would probably be to grab and build sqlite source directly in Xcode, and drop -lsqlite3. To do that just for iOS, I assume you'll need some target slight-of-hand in Xcode config.

@JulianBissekkou
Copy link
Author

I compiled the sql lib from the mentioned sources and added the dylib file to the project. It was able to find some symbols but still failed to compile since some of them are unknown.
Since I am building just a small POC i want to keep things simple. I was wondering if anything else is configued on my side.
Is there an example project with a macOS app that I can try out and compare?

@JulianBissekkou
Copy link
Author

@kpgalligan
If you run the tests are you compiling an MacosArm64 binary?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants