cashapp / sqldelight

SQLDelight - Generates typesafe Kotlin APIs from SQL
https://cashapp.github.io/sqldelight/
Apache License 2.0
6.12k stars 512 forks source link

linkDebugFrameworkIosArm64 fails with "Undefined symbols for architecture arm64" #5368

Closed GuilhE closed 1 month ago

GuilhE commented 1 month ago

SQLDelight Version

2.0.2

Operating System

14.5 (23F79) arm64

Gradle Version

8.7

Kotlin Version

2.0.20-Beta2

Dialect

SQLite

AGP Version

8.3.2

Describe the Bug

I've two modules, core-database and core-di. The first contains the database.db and a Dao. The second depends on the first and contains all the project's DI logic including the drivers for each target (android and iOS). On android there's no problem, it runs like expected. On iOS, running ./gradlew :core-di:build fails with the stacktrace shared bellow. The database is not directly exposed to any target, instead, a repository will be shared containing a Dao instance to perform operations.

Stacktrace

The /Applications/Xcode-15.3.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld command returned non-zero exit code: 1.
output:
ld: warning: ignoring duplicate libraries: '-ldl'
Undefined symbols for architecture arm64:
  "_sqlite3_bind_blob", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_bind_blob_wrapper69 in libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a[2](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_bind_double", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_bind_double_wrapper71 in libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a[2](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_bind_int64", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_bind_int64_wrapper73 in libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a[2](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_bind_null", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_bind_null_wrapper74 in libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a[2](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_bind_parameter_index", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_bind_parameter_index_wrapper84 in libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a[2](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_bind_text", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_bind_text_wrapper75 in libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a[2](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_bind_zeroblob", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_bind_zeroblob_wrapper80 in libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a[2](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_busy_timeout", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_busy_timeout_wrapper22 in libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a[2](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_changes", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_changes_wrapper16 in libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a[2](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_clear_bindings", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_clear_bindings_wrapper85 in libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a[2](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_close", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_close_wrapper6 in libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a[2](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_close_v2", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_close_v2_wrapper7 in libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a[2](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_column_blob", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_column_blob_wrapper99 in libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a[2](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_column_bytes", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_column_bytes_wrapper106 in libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a[2](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_column_count", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_column_count_wrapper86 in libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a[2](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_column_double", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_column_double_wrapper100 in libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a[2](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_column_int64", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_column_int64_wrapper102 in libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a[2](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_column_name", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_column_name_wrapper87 in libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a[2](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_column_text", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_column_text_wrapper103 in libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a[2](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_column_type", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_column_type_wrapper108 in libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a[2](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_db_config", referenced from:
      knifunptr_co_touchlab_sqliter_sqlite314_sqlite3_db_config in libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a[2](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_db_readonly", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_db_readonly_wrapper177 in libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a[2](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_errmsg", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_errmsg_wrapper53 in libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a[2](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_exec", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_exec_wrapper8 in libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a[2](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_finalize", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_finalize_wrapper109 in libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a[2](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_last_insert_rowid", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_last_insert_rowid_wrapper14 in libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a[2](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_open_v2", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_open_v2_wrapper43 in libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a[2](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_prepare16_v2", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_prepare16_v2_wrapper61 in libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a[2](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_reset", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_reset_wrapper110 in libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a[2](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_step", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_step_wrapper97 in libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a[2](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
ld: symbol(s) not found for architecture arm64

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':core-di:linkDebugFrameworkIosArm64'.
> Compilation finished with errors

If I add:

kotlin.native.cacheKind.iosArm64=none
kotlin.native.cacheKind.iosSimulatorArm64=none

the output becomes:

The /Applications/Xcode-15.3.0.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ld command returned non-zero exit code: 1.
output:
ld: warning: ignoring duplicate libraries: '-ldl'
Undefined symbols for architecture arm64:
  "_sqlite3_bind_blob", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_bind_blob_wrapper69 in CoreDi.framework.o
  "_sqlite3_bind_double", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_bind_double_wrapper71 in CoreDi.framework.o
  "_sqlite3_bind_int64", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_bind_int64_wrapper73 in CoreDi.framework.o
  "_sqlite3_bind_null", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_bind_null_wrapper74 in CoreDi.framework.o
  "_sqlite3_bind_parameter_index", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_bind_parameter_index_wrapper84 in CoreDi.framework.o
  "_sqlite3_bind_text", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_bind_text_wrapper75 in CoreDi.framework.o
  "_sqlite3_bind_zeroblob", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_bind_zeroblob_wrapper80 in CoreDi.framework.o
  "_sqlite3_busy_timeout", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_busy_timeout_wrapper22 in CoreDi.framework.o
  "_sqlite3_changes", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_changes_wrapper16 in CoreDi.framework.o
  "_sqlite3_clear_bindings", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_clear_bindings_wrapper85 in CoreDi.framework.o
  "_sqlite3_close", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_close_wrapper6 in CoreDi.framework.o
  "_sqlite3_close_v2", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_close_v2_wrapper7 in CoreDi.framework.o
  "_sqlite3_column_blob", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_column_blob_wrapper99 in CoreDi.framework.o
  "_sqlite3_column_bytes", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_column_bytes_wrapper106 in CoreDi.framework.o
  "_sqlite3_column_count", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_column_count_wrapper86 in CoreDi.framework.o
  "_sqlite3_column_double", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_column_double_wrapper100 in CoreDi.framework.o
  "_sqlite3_column_int64", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_column_int64_wrapper102 in CoreDi.framework.o
  "_sqlite3_column_name", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_column_name_wrapper87 in CoreDi.framework.o
  "_sqlite3_column_text", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_column_text_wrapper103 in CoreDi.framework.o
  "_sqlite3_column_type", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_column_type_wrapper108 in CoreDi.framework.o
  "_sqlite3_db_config", referenced from:
      knifunptr_co_touchlab_sqliter_sqlite314_sqlite3_db_config in CoreDi.framework.o
  "_sqlite3_db_readonly", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_db_readonly_wrapper177 in CoreDi.framework.o
  "_sqlite3_errmsg", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_errmsg_wrapper53 in CoreDi.framework.o
  "_sqlite3_exec", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_exec_wrapper8 in CoreDi.framework.o
  "_sqlite3_finalize", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_finalize_wrapper109 in CoreDi.framework.o
  "_sqlite3_last_insert_rowid", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_last_insert_rowid_wrapper14 in CoreDi.framework.o
  "_sqlite3_open_v2", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_open_v2_wrapper43 in CoreDi.framework.o
  "_sqlite3_prepare16_v2", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_prepare16_v2_wrapper61 in CoreDi.framework.o
  "_sqlite3_reset", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_reset_wrapper110 in CoreDi.framework.o
  "_sqlite3_step", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_step_wrapper97 in CoreDi.framework.o
ld: symbol(s) not found for architecture arm64

> Task :core-di:linkDebugFrameworkIosArm64 FAILED

FAILURE: Build failed with an exception.

Gradle Build Script

sqldelight {
    databases {
        create("MyDatabase") {
            packageName.set("com.mydatabase")
        }
    }
    linkSqlite.set(true)
}
GuilhE commented 1 month ago

I've followed this setup: https://cashapp.github.io/sqldelight/2.0.2/js_sqlite/gradle/#schema-dependencies and now it works 👍🏼

baruchn commented 4 days ago

I seem to have the same issue with only one module. SQLDelight 2.0.2, Kotlin 2.0.20.

Undefined symbols for architecture arm64:
  "_sqlite3_bind_blob", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_bind_blob_wrapper69 in ComposeApp[5](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_bind_double", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_bind_double_wrapper71 in ComposeApp[5](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_bind_int64", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_bind_int64_wrapper73 in ComposeApp[5](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_bind_null", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_bind_null_wrapper74 in ComposeApp[5](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_bind_parameter_index", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_bind_parameter_index_wrapper84 in ComposeApp[5](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_bind_text", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_bind_text_wrapper75 in ComposeApp[5](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_bind_zeroblob", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_bind_zeroblob_wrapper80 in ComposeApp[5](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_busy_timeout", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_busy_timeout_wrapper22 in ComposeApp[5](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_changes", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_changes_wrapper16 in ComposeApp[5](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_clear_bindings", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_clear_bindings_wrapper85 in ComposeApp[5](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_close", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_close_wrapper6 in ComposeApp[5](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_close_v2", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_close_v2_wrapper7 in ComposeApp[5](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_column_blob", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_column_blob_wrapper99 in ComposeApp[5](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_column_bytes", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_column_bytes_wrapper106 in ComposeApp[5](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_column_count", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_column_count_wrapper86 in ComposeApp[5](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_column_double", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_column_double_wrapper100 in ComposeApp[5](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_column_int64", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_column_int64_wrapper102 in ComposeApp[5](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_column_name", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_column_name_wrapper87 in ComposeApp[5](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_column_text", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_column_text_wrapper103 in ComposeApp[5](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_column_type", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_column_type_wrapper108 in ComposeApp[5](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_db_config", referenced from:
      knifunptr_co_touchlab_sqliter_sqlite314_sqlite3_db_config in ComposeApp[5](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_db_readonly", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_db_readonly_wrapper177 in ComposeApp[5](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_errmsg", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_errmsg_wrapper53 in ComposeApp[5](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_exec", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_exec_wrapper8 in ComposeApp[5](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_finalize", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_finalize_wrapper109 in ComposeApp[5](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_last_insert_rowid", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_last_insert_rowid_wrapper14 in ComposeApp[5](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_open_v2", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_open_v2_wrapper43 in ComposeApp[5](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_prepare16_v2", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_prepare16_v2_wrapper61 in ComposeApp[5](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_reset", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_reset_wrapper110 in ComposeApp[5](libco.touchlab:sqliter-driver-cinterop-sqlite3-cache.a.o)
  "_sqlite3_step", referenced from:
      _co_touchlab_sqliter_sqlite3_sqlite3_step_wrapper97 in ComposeApp[5](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)
kpgalligan commented 4 days ago

It's a sqlite linking issue: https://github.com/cashapp/sqldelight/issues/1442#issuecomment-1938897368

By "issue" I don't mean a "bug". You need to add -lsqlite3 to your linker flags in whatever module is building your framework.

For @GuilhE the build fails in :core-di:linkDebugFrameworkIosArm64. I assume you're building a dynamic framework. You'll need to add the linker flags.

Why this?

kotlin.native.cacheKind.iosArm64=none
kotlin.native.cacheKind.iosSimulatorArm64=none

I wouldn't expect it to do anything useful.

@baruchn same root issue. Not sure of your config. Your whole KMP project is one module? That's a bit different, as the sqldelight plugin should add the flag.

GuilhE commented 4 days ago

For @GuilhE the build fails in :core-di:linkDebugFrameworkIosArm64. I assume you're building a dynamic framework. You'll need to add the linker flags.

I've configured a schema dependency on another module like documented here and it worked. No need for XCode > Build Settings > "Other Linker Flags"

kpgalligan commented 4 days ago

I've configured a schema dependency on another module like documented here and it worked. No need for XCode > Build Settings > "Other Linker Flags"

So core-di has a schema dependency that points at core-database? Where is the db code generated? I assume in core-di. If that's what you did, a couple things:

1) The code is being generated in core-di, which possibly means you're exporting lots of files you don't need to be into your framework header.

2) If you make your framework static instead of dynamic, you'll probably need to do XCode > Build Settings > "Other Linker Flags" anyway, unless something has changed with how those are packaged.

baruchn commented 4 days ago

@kpgalligan Yes, one module. Static framework. Adding -lsqlite3 through XCode seems to resolve the issue.

GuilhE commented 4 days ago

@kpgalligan ok, let me help and clarify. This is a multi-module KMP project, and the module core-di is "the shared framework exposed" entry point (it will depend on the other modules). It configures Koin and calls expect fun <moduleX>Module(): Module functions to include their DI setup:

object DependencyInjection {
    /**
     * DI engine initialization.
     * This function must be called by the iOS app inside the respective App struct.
     */
    @Suppress("unused")
    fun initKoin(enableNetworkLogs: Boolean) = initKoin(enableNetworkLogs = enableNetworkLogs) {}

    /**
     * DI engine initialization.
     * This function must be called by the Android app inside the respective Application class.
     */
    @HiddenFromObjC
    fun initKoin(enableNetworkLogs: Boolean = false, appDeclaration: KoinAppDeclaration = {}) {
        startKoin {
            appDeclaration()
            modules(
                moduleAModule(),
                moduleBModule(),
                moduleCModule(),
                ...
            )
        }
    }
}

build.gradle:

kotlin {
    androidTarget()
    listOf(iosArm64(), iosSimulatorArm64()).forEach { iosTarget ->
        iosTarget.binaries.framework {
            baseName = "MyFramework"
            export(...) //only those that I need to call on iOS to avoid same objects with diff. namespaces problem
        }
    }
}

sqldelight {
    //https://cashapp.github.io/sqldelight/2.0.2/js_sqlite/gradle/#schema-dependencies
    databases {
        create("MyDatabase") {
            packageName.set("com.core.di")
            dependency(projects.coreDatabase)
        }
    }
}

Module core-database has all the DB logic (and code generation):

kotlin {
    androidTarget()
    listOf(iosArm64(), iosSimulatorArm64()).forEach { iosTarget ->
        iosTarget.binaries.framework {
            baseName = "CoreDatabase" //although configured like this only core-di will be exported: ./gradlew :core-di:embedAndSignAppleFrameworkForXcode

        }
    }
}

sqldelight {
    databases {
        create("MyDatabase") {
            packageName.set("com.core.database")
        }
    }
}

If I include the sqldelight configuration on core-di it works. If not, even with -lsqlite3 I was having this problem 🤷🏼‍♂️

note: to avoid export unnecessary info to objc-headers, everything is mostly internal or @HiddenFromObjC...

kpgalligan commented 4 days ago

If not, even with -lsqlite3 I was having this problem

-lsqlite3 wasn't in the right place. It is always the solution. The linker can't find those symbols. In your original post, the failure was in :core-di:linkDebugFrameworkIosArm64. That means code-di needs to add -lsqlite3 to its linker flags. The schema dependency now adds the linker flag in the sqldelight plugin.

note: to avoid export unnecessary info to objc-headers, everything is mostly internal or @HiddenFromObjC...

That's your code, not the code generated by sqldelight. If core-di winds up generating the whole db schema, then you're exporting all of your table-related code. I don't remember how schema dependencies work. If core-di is simply using code generated by core-database, you're not exporting as much. However, sqldelight will generate some accessor and boilerplate code, which will expose sqldelight dependencies, and possibly some coroutines. It's all part of the public Kotlin API.

GuilhE commented 4 days ago

-lsqlite3 wasn't in the right place. It is always the solution.

I don't doubt it.

The linker can't find those symbols. In your original post, the failure was in :core-di:linkDebugFrameworkIosArm64. That means code-di needs to add -lsqlite3 to its linker flags.

I've tried adding it on Xcode and also in build.gradle, like specified in this thread, but none made it work. What could I be doing wrong?

To complicate things further, upon review the thread, I believe I didn't try this:

sqldelight {
  linkSqlite = true
}

So I've commented the schema dependency config and added that parameter. It works. I've commented both the schema dependency and linkSqlite and it works too. 🫨

Now ./gradlew :core-di:build --no-build-cache works 🤷🏼 and I only need to specify:

sqldelight {
    databases {
        create("MyDatabase") {
            packageName.set("com.core.database")
        }
    }
}

🫤😖 what!?

The schema dependency now adds the linker flag in the sqldelight plugin.

So, with the schema dependency config. the flag is being added right? Good!

That's your code, not the code generated by sqldelight. If core-di winds up generating the whole db schema, then you're exporting all of your table-related code. I don't remember how schema dependencies work. If core-di is simply using code generated by core-database, you're not exporting as much. However, sqldelight will generate some accessor and boilerplate code, which will expose sqldelight dependencies, and possibly some coroutines. It's all part of the public Kotlin API.

True, but core-di does not "use" nor generates any code related to DB. It exposes a manager that uses the private DAOs, etc... Yes the generated code is public but iOS does not handle directly this code. Looking at the headers.h the data exposed does not have anything related with the DB, only the code I need to be public and Koin, KotlinBase, Kotlinx_coroutines, Kotlinx_serialization. All part of the public Kotlin API as you mentioned 😊

lucasmarcal-faire commented 7 hours ago

This issue also happens to me when running debug builds. Release builds work fine

kpgalligan commented 7 hours ago

@GuilhE

Koin, KotlinBase, Kotlinx_coroutines, Kotlinx_serialization

If your Swift code isn't directly calling those, then it's excess. It doesn't just add clutter to the header. Binary adapters are generated, which can bloat the binary with code you don't use. It's not the end of the world, but something to possibly consider.

kpgalligan commented 7 hours ago

This issue also happens to me when running debug builds. Release builds work fine

Somewhere, somehow, -lsqlite3 isn't being passed to the linker. In this case, for some reason, only debug builds. If by "release builds" you mean when run from Xcode, then it's possible that the setting in Xcode is only applied to release builds.