Hey everyone :wave:, I'm working on creating Kotli...
# kotlin-native
r
Hey everyone 👋, I'm working on creating Kotlin/Native bindings for WebKit GTK and running into an issue with the
linkDebugExecutableLinuxX64
task. I have a dedicated module for the WebKit bindings with a
cinterop
def file (webkit.def), which builds fine. However, when I try using it as a dependency in a sample app module, I get these errors:
Copy code
e: /home/leinardi/.konan/dependencies/x86_64-unknown-linux-gnu-gcc-8.3.0-glibc-2.19-kernel-4.9-2/x86_64-unknown-linux-gnu/bin/ld.gold invocation reported errors
[...]
/usr/lib/x86_64-linux-gnu/libgmodule-2.0.so: error: undefined reference to 'dlclose', version 'GLIBC_2.34'
/usr/lib/x86_64-linux-gnu/libgmodule-2.0.so: error: undefined reference to 'dlsym', version 'GLIBC_2.34'
/usr/lib/x86_64-linux-gnu/libgmodule-2.0.so: error: undefined reference to 'dlopen', version 'GLIBC_2.34'
/usr/lib/x86_64-linux-gnu/libgmodule-2.0.so: error: undefined reference to 'dlerror', version 'GLIBC_2.34'
Based on what I found online, adding
-Wl,--no-as-needed -ldl
to
linkerOpts
should help, but that gives an error:
ld.gold: -Wl,--no-as-needed: unknown option
. For context: • I'm new to
cinterop
and am primarily an Android dev. • The WebKit binding module depends on two other
cinterop
modules (atk.def and soup.def), so the issue might be in one of these modules. Interestingly, if I use the GTK4 bindings (gtk4.def) without the WebKit dependency, the sample project runs without issues so I assume it must be something int he
webkit.def
file. Any advice on resolving the linking errors? Thanks in advance! 🙏
l
Try adding the following to the
.def
file:
Copy code
linkerOpts.linux = <lib names here> --allow-shlib-undefined
r
hi @loke using
--allow-shlib-undefined
actually made it build, link and run! Since I'm creating bindings for GObject libraries, do you think that using this linker option could cause some issue? Or make debugging runtime errors more difficult?
btw I just found out that using
kotlin.incremental.native=true
cuts the build and link time from minutes to seconds once the klib artifacts are cached
l
@Roberto Leinardi I don't know to be honest. On one hand you have some purists that say that "it's not supported", and things like that. Their suggestion is to compile required libraries yourself with a different version of glibc and then bundle those. In my opinion, that won't fly in most cases, and even when it is an option, you now have to manage security patches for a bunch of third-party libraries.
On the other hand, this is the only way to make it work, a lot of people are using this method, and I've never actually heard of anything failing due to it.
If I understand correctly, the root cause is that the Kotlin native compiler uses its own version of glibc when building. This version is older, because they want to support Redhat 7 or something like that. But then that means you can't link with libraries that depend on higher versions of glibc. The version check is done by referencing a symbol that describes the version number, so if that symbol doesn't exist, you get a link error. Adding this flag means that referencing undefined symbols won't fail, so compilation succeeds. Now, at runtime there is no problem because you're linking with the system glbc, which is of the newer version.
If my understanding is correct, there are a few issues you can find. None of them are bad enough to warrant the current stupid behaviour: • If you reference a symbol at compile time that really doesn't exist, then you'll get a runtime error instead of a compile error. • There may be unexpected behaviours if you run the resulting binary on an OS version lower than what you built on.
r
@loke thanks a lot for the explanation! Right now I'm trying to avoid using it because I like the idea of a being able to check at compile time about missing symbols but, if I reach a point where I can't work around it anymore, I'll definitely make use of
--allow-shlib-undefined
and just deal with eventual runtime errors. Thanks again!
are you aware by any chance of an issue about this on YouTrack that I can 👍 and subscribe?
l
Yes, there is one. I subscribed to it when I first got stuck. Let me see if I can find it.
What I can tell you is that I link with maybe 10 different libraries, and I have used this flag for a long time. I don't think I've ever come across a problem that was caused by this. The only way to encounter it would be if you define an external symbol (maybe in the
.def
file, in the explicit C section) and then use it. That would cause a link error without the flag but a runtime error with it. I have never done this.
👍 1
r
thank you again! There seems to be some interesting comments like this and this. Have you already tried to use the
includeDirs.headerFilterOnly()
or the
targetSysRoot.linux_x64
? (I'm still reading through)
l
I have not. But based on my understanding, I don't see how that could help.
But there is of course the possibility that I'm wrong.
r
I'm experimenting with the overriding of the
targetSysRoot
, so that it will use the host glibc instead of the bundled one. I found this blog post and still playing with it: https://zachary.grafton.me/2024/01/21/kotlin-native-on-fedora-39.html
l
Intersting approach.
r
btw if you like the idea of building GTK apps with K/N, check out gtk-kn, it is still in a pretty early stage but I'm making progress and we are looking for more people with cinterop knowledge 🙂
I just tried with this and it actually worked, I was able to compile and link without issues!
Copy code
binaries {
            executable {
                entryPoint = "org.gtkkn.samples.gtksource.sample.main"
                freeCompilerArgs += listOf(
                    "-Xoverride-konan-properties=targetSysRoot.linux_x64=/" //Change buildroot location
                        + ";libGcc.linux_x64=/usr/lib/gcc/x86_64-linux-gnu/13" //Look for libGcc in the correct place
                        + ";linker.linux_x64=/usr/bin/ld.bfd" //Use a proper linker, gold seems to choke on some newer stuff
                        + ";crtFilesLocation.linux_x64=/usr/lib/x86_64-linux-gnu/", //Tell Kotlin where to find some C runtime libraries
                )
            }
        }
l
You know, I would probably use this.
But... (and it's a big but), I'd need it to work with the JVM backend as well.
My main UI is written in JavaFX now, and switching to GTK would certainly be something I'd consider.
The native version only has a text-based interface right now.
r
for the JVM there is already a pretty advanced binding project: Java-GI
l
Yeah, but if I am to switch, I'd love to be able to leverage something that would allow the native version to use it.
👍 1