Why Zig adds dynamic library path into final executable

I have a build.zig file that compiles zig along with a shared library located in non-standard path i,e, not in usual paths that linker will refer to.

var temp_exe = b.addExecutable(.{ .name = "temp_exe", .root_source_file = .{ .path = "scratchpad/temp.zig" }, .target = target, .optimize = optimize });
temp_exe.addLibraryPath(.{ .path = "/home/akhil/practice/fancy-regex/target/release" });
temp_exe.linkSystemLibrary("fancy_regex");
b.installArtifact(temp_exe);

I’ve added the non-standard path in library search path for zig to refer the shared library libfancy_regex.so

But the path is hardcoded in the executable which I don’t want.

(.venv) ➜  fasttokenizer git:(python) ✗ readelf -d zig-out/bin/temp_exe

Dynamic section at offset 0x4e5f90 contains 26 entries:
  Tag        Type                         Name/Value
 0x000000000000001d (RUNPATH)            Library runpath: [/home/akhil/practice/fancy-regex/target/release]
 0x0000000000000001 (NEEDED)             Shared library: [/home/akhil/practice/fancy-regex/target/release/libfancy_regex.so]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [ld-linux-x86-64.so.2]

How to tell zig to avoid adding RUNPATH but just have the NEEDED that only has filename libfancy_regex.so like libc.so.6

I suspect that’s it’s just rpath, there are tools that can clear it for you.

It’s not zig specific, it’s a Unix thing.

Try to set rpath to $ORIGIN or $ORIGIN/../lib using:

temp_exe.addRPathSpecial("$ORIGIN");

$ORIGIN means load dynamic libraries from executable directory.

1 Like

Solved now I don’t get the hardcoded path

(.venv) ➜  fasttokenizer git:(python) ✗ readelf -d zig-out/bin/temp_exe                                                           

Dynamic section at offset 0x4e5f30 contains 25 entries:
  Tag        Type                         Name/Value
 0x0000000000000001 (NEEDED)             Shared library: [libfancy_regex.so.0]
 0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
 0x0000000000000001 (NEEDED)             Shared library: [ld-linux-x86-64.so.2]

The issue was with rust shared library that didn’t had SONAME in it’s data fields. After adding it in the shared library I don’t see hardcoded path in zig binary.

// in build.rs
fn main() {
    println!(
        "cargo:rustc-cdylib-link-arg=-Wl,-soname,libfancy_regex.so.{}",
        std::env::var("CARGO_PKG_VERSION_MAJOR").unwrap()
    );
}

References:
Don't use absolute path to shared libraries that don't have a SONAME set · Issue #7766 · mesonbuild/meson · GitHub

Set FFI SONAME to fips203-ffi crate major version by dkg · Pull Request #7 · integritychain/fips203 · GitHub

Support soname for cdylibs · Issue #5045 · rust-lang/cargo · GitHub