Cross compilation with sysroot loads shared library from incorrect path?

I am currently in the process of trying out zig build for compiling an application for an embedded linux platform. No problems compiling at all (and loving how easy Zig makes cross compilation :heart:), but I can’t seem to wrap my head around linking shared libraries.

The application relies on a closed-source shared library.

With Cmake I can do this:

set(TARGET_SYSROOT "/path/to/sysroot")
set(CMAKE_C_FLAGS   "--sysroot=${TARGET_SYSROOT}")
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)

[...]

target_link_libraries( ${X} sharedlib )

Which will:

  1. Make the compiler look for the library in the sysroot (e.g., /path/to/sysroot/lib/libsharedlib.so), and
  2. Make the application load the library from its usual location (e.g. /lib/libsharedlib.so)

The equivalent zig seems to be invoking

zig build --sysroot "/path/to/sysroot" --search-prefix "/path/to/sysroot"

and then

exe.linkSystemLibrary("sharedlib");

in the build script.

This compiles just fine, but when I load it onto the device, it looks for the shared library in “/path/to/sysroot”, so it fails to run:

error while loading shared libraries: /path/to/sysroot/lib/libsharedlib.so: cannot open shared object file: No such file or directory

Considering how nice everything else regarding cross compilation is in Zig, I’m surprised I can’t seem to get this working.

What am I doing wrong? :sweat_smile:

(I can share more information about the target and build process if needed)

It’s a bug, check out this

Ah, a shame. Thanks for the links though. Appreciated.

For now I’ve fixed it by patching the files as a post-build step.
It’s not blocking, but it is a little annoying.

What is the expected correct behaviour, then?

zig --sysroot "whatever"

Searching “./whatever” on the compiler-host and root dir on target?

Edit: Marking this solved.

In case anyone is interested, here’s what I did as a temporary fix:

readelf -d will show you the incorrectly assigned library paths:

readelf -d /path/to/binary
  Tag        Type                         Name/Value
...
 0x00000001 (NEEDED)                     Shared library: [/path/to/sysroot/lib/libsharedlib.so]
...

then patchelf --replace-needed can patch the library path.
Patchelf is a NixOS system utility available here.

 patchelf --replace-needed /path/to/sysroot/lib/libsharedlib.so libsharedlib.so /path/to/binary

now the path is correctly assigned:

readelf -d /path/to/binary
  Tag        Type                         Name/Value
...
 0x00000001 (NEEDED)                     Shared library: [libsharedlib.so]
...

A pure zig solution is welcome if one is available. :slight_smile:

2 Likes