I have a project that depends on GLFW, which uses dlopen
to query for X11 support.
I want to use musl-libc because it makes sharing an executable easier, GNU libc always seems to break when trying to run it on an older version of Linux than the one it was compiled on.
Now from my testing I have discovered that when I target musl, dlopen
always returns null
. Here is the full example:
const std = @import("std");
pub fn main() !void {
std.log.err("{?}", .{std.c.dlopen("libX11.so", .{
.LAZY = true,
.GLOBAL = false,
})});
}
$ zig run test.zig -lc -target x86_64-linux-musl
error: null
$ zig run test.zig -lc -target x86_64-linux-gnu
error: anyopaque@15272d0
Does anyone know if it is possible to make this work on musl?
I know for a fact that C or C++ code compiled with Zig for musl can use dlopen()
, but there could be a limitation from Zig code maybe?
Have you checked that it’s looking at the right library path(s) such as LD_LIBRARY_PATH
?
It is very difficult to load glibc shared objects without dynamically linking against glibc (musl does not support doing this). The static musl libc.a
defines dlopen
to simply return NULL
. If you just want to be able to target musl based systems, then I believe Zig now provides out of the box support for dynamically linking musl libc and then dlopen
will work for shared libraries built against musl libc.
2 Likes
you can use or read std.DynLib i believe. but in my experience, for musl i need to use absolute path
Have you tried targeting an old version of GNU libc? Zig allows you to target specific versions independent of the build machine, e.g. -target x86_64-linux-gnu.2.21
.
1 Like
I actually noticed, that even if I target the latest (which is not present on my system, I only have glibc version 2.35 and I do sometimes have problems with other games because of that), then it appears the executable can still be ran without a problem.
So I guess Zig is doing something else that makes it more compatible than other languages are.
Are you ultimately trying to do some rendering via OpenGL? I might be trying to get this working soon here. I’ve recently been enhancing my X11 library written in zig GitHub - marler8997/zigx as well as my cross-platform windowing library GitHub - marler8997/zin: Cross-platform GUIs which uses zigx as one of its backends. I’ve heard I might need to support dlopen
to open certain vendor-supplied .so
files in order to use the GPU but I haven’t gotten there yet.
1 Like
Yes, right now I’m using GLAD+GLFW to load an OpenGL window. And both of them use dlopen
internally.
There’s this project. The technique looks intriguing.
1 Like
From what I can gather, the idea is to place a small precompiled executable–one which links against glibc–into memory, then jump to its initialization routine. Dynamic linking would then happen normally, bringing glibc into your program’s memory space. The small executable then stores the pointer to glibc’s dlopen somewhere and longjmp back into your program.
This can actually be implemented relatively easily in Zig since ELF-related structs are part of the standard library. If I had time I’d try it myself. It’s a fun (and educational) hack.