Hi! Does anyone have example projects that build O...
# multiplatform
t
Hi! Does anyone have example projects that build Objective-C directly into an iOS target? Is it possible to just include a handful of
.m
and
.h
files that way so I can use them in some
actual
implementations? Or do I have to somehow build a library of the
.m
files and link against that? I'm trying to follow the Gradle examples here but my iOS build is failing to find my header. Not sure if I have to adjust my Xcode project to include the header file or what. Any help is greatly appreciated!
z
Do you mean to compile a Kotlin Module into iOS Framework and use it in iOS project? If this is the case, then you can use kotlin-multiplatform plugin, and declare this as apple framework, it looks like this
Copy code
plugins {
    kotlin("multiplatform")
}
kotlin {
    listOf(
        iosX64(),
        iosArm64(),
    ).forEach {
        it.binaries.framework {
            baseName = "yourModuleName"
        }
    }
    // ...
}
Then you can use it in Xcode, just follow this https://kotlinlang.org/docs/kmm-integrate-in-existing-app.html#connect-the-framework-to-your-ios-project.
a
Your project is probably structured as (Kotlin side with some Obj-C code inside) -> (Xcode project building an app). Instead, current limitations of the Objective-C interop would require making this a three-step process: (Xcode project building a library from your Obj-C code) -> (Kotlin project utilizing this library by
cinterop
block) -> (Xcode project building an app).
t
@Zode I followed those steps originally so I think I have those basics in place. My structure is hopefully a fairly typical one: some Android-only code, some iOS-only code, and a shared KMM module with
commonMain
,
androidMain
, and
iosMain
. Almost all the code in the shared module is in
commonMain
already. But I have a very simple library where I built the Java version directly into the Android app and the Objective-C version directly into the iOS app. I've converted the Java version to Kotlin and I'm using that for the
actual
implementations for
androidMain
and now I'm trying to build the Objective-C version into the
iosMain
. I have full control over the source files so I'm trying to do whatever is simplest
this simple library is my DB handler and this should just be a very temporary thing until I can move over to SQLDelight in a release or two
@Artyom Degtyarev [JB] yeah, I think your description matches what I'm doing (please see above). If I have to have Xcode build the library then use it via
cinterop
, that's doable (especially since this should be time-limited, as I mention). Are you aware of any code examples of that that I can check out?
oh, and I should be able to just make that library target a dependency of my iOS app target so I can just build my iOS app and have it all handled automatically, I imagine. My final iOS app build uses the recommended process where Xcode itself does the final build work so I think it should be aware of any underlying library changes
one other thing that might help: once I get this library building, I don't expect to make any changes to it until I replace it with SQLDelight
k
Some thoughts here. If you want to directly write to sqlite before SQLDelight, you can use the driver directly: https://github.com/touchlab/SQLiter
If you’re going to use cinterop to talk to you objc library, it can get tricky around testing. For kotlin tests to run you’d need to make sure you link out to a library built from that objc, which kind of makes for a bit of a cyclical issue (chicken/egg). You can have the kotlin compiler generate an entry point for Kotlin native tests and call that from an XCTest, but that config is a handful.
I hesitate to also suggest this, https://github.com/touchlab/cklib, as we only use it in a few specific cases, but it sounds like something you might like. Essentially you can put objc code into a folder and it’ll be built and packaged into your klib. It copied clang config from kotlin native, but it’s not the prettiest or best documented thing for sure. Examples: https://github.com/touchlab/Kermit/blob/main/kermit-crashlytics-test/build.gradle.kts#L69 and https://github.com/cashapp/zipline/blob/trunk/zipline/build.gradle.kts#L154
t
@kpgalligan thanks! I think
cklib
might be a good fit. If not, I'll try building my Obj-C code into the library and using it through
cinterops
testing isn't much of a concern because I honestly don't have any automated tests for my iOS app yet. This Obj-C library is only to migrate existing installs (of which there are very few) and I'll only be writing tests for the KMM and Swift paths in the iOS app
@kpgalligan sorry for a basic question, but what's the Groovy equivalent of this?:
Copy code
plugins {
    id("co.touchlab.cklib")
}
When I try to just include it as:
Copy code
apply plugin: 'co.touchlab.cklib'
I get:
Copy code
Plugin with id 'co.touchlab.cklib' not found.
even though it seems to be in Maven Central which I source
(I haven't gotten around to switching over to Kotlin DSL but will some time after settling everything with my first KMM-based releases)
ah, just realized I needed this in my top-level `buildscript.dependencies`:
Copy code
classpath("co.touchlab:cklib-gradle-plugin:$cklib_version")
OK, a new basic question though:
Copy code
cklib {
    //config.kotlinVersion = "$kotlin_version"
    create("sqlighter") {
        language = co.touchlab.cklib.gradle.CompileToBitcode.Language.OBJC
    }
}
yields:
Copy code
> No signature of method: build_89t0gtdiazmlot5b0npjl25b8.cklib() is applicable for argument types: (build_89t0gtdiazmlot5b0npjl25b8$_run_closure3) values: [build_89t0gtdiazmlot5b0npjl25b8$_run_closure3@10e17582]
  Possible solutions: mkdir(java.lang.Object), split(groovy.lang.Closure), wait(), file(java.lang.Object), wait(long), copy(groovy.lang.Closure)
is it necessary to set
config.kotlinVersion
? Don't I need to specify the Obj-C files somehow? I see
zipline
does but neither the
cklib
example nor Kermit seem to. If I do, should I just add lines like the following?:
Copy code
create("sqlighter") {
        language = co.touchlab.cklib.gradle.CompileToBitcode.Language.OBJC
        srcDirs = project.files(
                file("path/to/srcdir1"),
                file("path/to/srcdir2")
        )
k
is it necessary to set 
config.kotlinVersion
?
Yes
Don’t I need to specify the Obj-C files somehow?
There’s a folder convention you can use. If your cklib name is “objcsample”, create a folder called “objcsample”, and put headers in a folder called “headers” and source in a folder called “cpp”. It would probably make more sense to call it something other than “cpp”, but I just copy/pasted this from the Kotlin/Native source 🙂
but what’s the Groovy equivalent of this?
No idea. We’ve only used it with the Kotlin dsl.