https://kotlinlang.org logo
j

Jeff Lockhart

09/30/2022, 2:08 AM
Does anyone know if there's a way to link a cinterop dynamic .so library from a relative path within the project? This workaround seems to only work for static libraries.
t

Tijl

09/30/2022, 8:07 AM
coming to this a bit from a macos only perspective, but a
linkerOpt
with
-rpath
?
d

Dominaezzz

09/30/2022, 8:17 AM
Do it from Gradle and use absolute paths. Much easier.
j

Jeff Lockhart

09/30/2022, 5:15 PM
This was easier for iOS and macOS for sure. The CocoaPods plugin also takes care of linking for tests itself now. I am using
-rpath
to reference the relative path at runtime, but was still figuring out how to pass the linker option in gradle and just realized I can do it in the same place! 🤦‍♂️ (I was figuring out
-rpath
after giving up on gradle
linkerOpts()
not working for
-L
.) For context, if anyone else runs into this, I'm adding Linux and Windows native targets to my library. I'm able to reference the headers with a relative path from gradle with
includeDirs()
, but
linkerOpts()
isn't supported by cinterop:
warning: -linker-option(s)/-linkerOpts option is not supported by cinterop. Please add linker options to .def file or binary compilation instead.
But .def doesn't support relative paths and somehow I overlooked the binary compilation mentioned at the end. I was able to link the mingwX64 library's relative path, since it uses a .lib import library which is statically linked. But this doesn't work for the Linux .so. Instead of passing
linkerOpts()
to cinterop, I need to pass it to the test binary: build.gradle.kts
Copy code
kotlin {
    ...
    targets.withType<KotlinNativeTarget> {
        val libPath = "$projectDir/<lib-relative-path>"
        val main by compilations.getting
        val libName by main.cinterops.creating {
            includeDirs("<lib-headers-relative-path>")
            if (konanTarget.family == Family.MINGW) {
                extraOpts("-libraryPath", libPath)
            }
            //linkerOpts(...) <- does not work!
        }
        if (konanTarget.family == Family.LINUX) {
            binaries.getTest(DEBUG).linkerOpts += listOf(
                "-L$libPath", "-llibName", "-rpath", libPath
            )
        }
    }
}
libName.def
Copy code
...

staticLibraries.mingw_x64 = libName.lib
I also need to use a copy task to copy the dynamic .dll to the .kexe directory to find the library at runtime, since Windows doesn't support
-rpath
.
u

黄文和

10/31/2022, 10:02 AM
My approach is to compile the c library from source code as a pre-dependency of the gradle build task, and dynamically generate .def and link through the static library, which allows me to distribute the binary without requiring the user's runtime environment to contain certain dependencies
25 Views