Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Incorrect archiver Command Line Call When Linking a Static "System" Library to another Static Library #20476

Open
haydenridd opened this issue Jul 2, 2024 · 2 comments · May be fixed by #22878
Labels
bug Observed behavior contradicts documented or intended behavior zig build system std.Build, the build runner, `zig build` subcommand, package management
Milestone

Comments

@haydenridd
Copy link

haydenridd commented Jul 2, 2024

Zig Version

0.13.0

Steps to Reproduce and Observed Behavior

High Level Summary

Zig appears to be erroneously passing .a files directly to ar when the following scenario takes place:

  • You are building a static library
  • You establish a dependency on a system library through addLibraryPath() and linkSystemLibrary/linkSystemLibrary2

This is possibly the root cause of this issue:
#13177

Detailed Info

Observe the example repo here:
https://github.com/haydenridd/zig-static-system-library-bug

In this example we have the following:

  • An executable that depends on:
    • A static library "static_library", which depends on:
      • Another static library "sys_lib"

In build.zig there is a boolean system_library_method that controls two different types of building this executable that should be equivalent.

When false:

  • Builds the project by:
    • Building "sys_lib" from source
    • Building "static_library" from source, "linking" against "sys_lib" (which really just adds this as a link dependency, there isn't really such a thing as "linking" one static library into another)
    • Building the executable which links against "static_library"

This behaves as expected, the build calls (common flags truncated for readability) look like:

zig clang /home/hayden/Documents/zig/system_includes_bug/sys_lib/src/sys_lib.c --no-default-config -fno-caret-diagnostics -target x86_64-unknown-linux-gnu -nostdinc -fno-spell-checking -isystem /home/hayden/.zvm/0.12.1/lib/include [-Xclang flags] [-f flags] -MD -MV -MF /home/hayden/Documents/zig/system_includes_bug/zig-cache/tmp/4e6ca6b8d2ff8d89-sys_lib.o.d -I /home/hayden/Documents/zig/system_includes_bug/sys_lib/src -c -o /home/hayden/Documents/zig/system_includes_bug/zig-cache/tmp/4e6ca6b8d2ff8d89-sys_lib.o --serialize-diagnostics /home/hayden/Documents/zig/system_includes_bug/zig-cache/tmp/4e6ca6b8d2ff8d89-sys_lib.o.diag
ar rcs /home/hayden/Documents/zig/system_includes_bug/zig-cache/o/790e50c2293689a2ff7f00f8f1fc00eb/libsys_lib.a /home/hayden/Documents/zig/system_includes_bug/zig-cache/o/3d3238ce221f946fb403332c4d443666/sys_lib.o
zig clang /home/hayden/Documents/zig/system_includes_bug/static_library/staticlib.c --no-default-config -fno-caret-diagnostics -target x86_64-unknown-linux-gnu -nostdinc -fno-spell-checking -isystem /home/hayden/.zvm/0.12.1/lib/include [-Xclang flags] [-f flags] -MD -MV -MF /home/hayden/Documents/zig/system_includes_bug/zig-cache/tmp/f112571b40b7097b-staticlib.o.d -I /home/hayden/Documents/zig/system_includes_bug/static_library -I /home/hayden/Documents/zig/system_includes_bug/zig-cache/o/baf03d5407472fb279c770a3919a020f -c -o /home/hayden/Documents/zig/system_includes_bug/zig-cache/tmp/f112571b40b7097b-staticlib.o --serialize-diagnostics /home/hayden/Documents/zig/system_includes_bug/zig-cache/tmp/f112571b40b7097b-staticlib.o.diag
ar rcs /home/hayden/Documents/zig/system_includes_bug/zig-cache/o/9306f2bf20f5853898d11b321e6f8fdb/libstaticlib.a /home/hayden/Documents/zig/system_includes_bug/zig-cache/o/b90eb644cbc286ea7edb3286aca2779a/staticlib.o
zig clang /home/hayden/Documents/zig/system_includes_bug/src/main.c --no-default-config -fno-caret-diagnostics -D__GLIBC_MINOR__=36 -target x86_64-unknown-linux-gnu -nostdinc -fno-spell-checking -isystem /home/hayden/.zvm/0.12.1/lib/include -isystem /usr/include [-Xclang flags] [-f flags] --param ssp-buffer-size=4 -D_DEBUG -O0 -fPIC -funwind-tables -gdwarf-4 -gdwarf32 -MD -MV -MF /home/hayden/Documents/zig/system_includes_bug/zig-cache/tmp/e451cba3f03d6294-main.o.d -I /home/hayden/Documents/zig/system_includes_bug/zig-cache/o/dda94905e809a5afabb5af92f37340c0 -c -o /home/hayden/Documents/zig/system_includes_bug/zig-cache/tmp/e451cba3f03d6294-main.o --serialize-diagnostics /home/hayden/Documents/zig/system_includes_bug/zig-cache/tmp/e451cba3f03d6294-main.o.diag
ld.lld --error-limit=0 --entry _start -z stack-size=16777216 --image-base=16777216 --eh-frame-hdr -znow -m elf_x86_64 -o /home/hayden/Documents/zig/system_includes_bug/zig-cache/o/fbfea196a3fefe3353258a5b17fcb0b6/main /usr/lib/gcc/x86_64-redhat-linux/12/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-redhat-linux/12/../../../../lib64/crti.o -L /usr/lib/gcc/x86_64-redhat-linux/12/../../../../lib64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /home/hayden/Documents/zig/system_includes_bug/zig-cache/o/9306f2bf20f5853898d11b321e6f8fdb/libstaticlib.a /home/hayden/Documents/zig/system_includes_bug/zig-cache/o/790e50c2293689a2ff7f00f8f1fc00eb/libsys_lib.a /home/hayden/Documents/zig/system_includes_bug/zig-cache/o/f545c2ea819fb388113868404264f77e/main.o --as-needed -lm -lpthread -lc -ldl -lrt -lutil /home/hayden/.cache/zig/o/f721cc9442cf1a25959b93955c415395/libcompiler_rt.a /usr/lib/gcc/x86_64-redhat-linux/12/../../../../lib64/crtn.o

There's a lot here, but the important part to pay attention to is the ar call that archives "static_lib" into a library:

ar rcs /home/hayden/Documents/zig/system_includes_bug/zig-cache/o/9306f2bf20f5853898d11b321e6f8fdb/libstaticlib.a /home/hayden/Documents/zig/system_includes_bug/zig-cache/o/b90eb644cbc286ea7edb3286aca2779a/staticlib.o

Now compare this to the behavior when system_library_method = true:

  • Builds the project by:
    • Building "static_library" from source, and again "linking" against "sys_lib", except this time against a prebuilt libsys_lib.a copied from the previous output into prebuilt_sys_lib folder
    • This is accomplished via addLibraryPath() and linkSystemLibrary2 calls respectively
    • Building the executable which links against "static_library" in the same way, with the caveat that we now need to manually add the system library paths via:
     for (static_lib.root_module.lib_paths.items) |path| {
            exe.addLibraryPath(path);
     }

This produces the following warning from ld.lld:

error: warning(link): unexpected LLD stderr:
ld.lld: warning: /home/hayden/Documents/zig/archiver_bug/.zig-cache/o/d14eb5f67992e73d6aef84dd739d4e63/libstaticlib.a: archive member '/home/hayden/Documents/zig/archiver_bug/prebuilt_sys_lib/lib/libsys_lib.a' is neither ET_REL nor LLVM bitcode

Examining the build calls, the culprit is this:

ar rcs /home/hayden/Documents/zig/system_includes_bug/zig-cache/o/34c04c0538e9a2ae1889b1bbdfe20397/libstaticlib.a /home/hayden/Documents/zig/system_includes_bug/sys_lib_folder/lib/libsys_lib.a /home/hayden/Documents/zig/system_includes_bug/zig-cache/o/29b356271420edfbf68e3497ca117069/staticlib.o

Zig is passing libsys_lib.a to the archiver, which LLVM is rightfully complaining about, as that isn't valid. However, the program still works because Zig also correctly passes the link dependency libsys_lib.a to the executable:

ld.lld --error-limit=0 --entry _start -z stack-size=16777216 --image-base=16777216 --eh-frame-hdr -znow -m elf_x86_64 -o /home/hayden/Documents/zig/system_includes_bug/zig-cache/o/46fb86a5c2db675a704552cca0155a25/main /usr/lib/gcc/x86_64-redhat-linux/12/../../../../lib64/crt1.o /usr/lib/gcc/x86_64-redhat-linux/12/../../../../lib64/crti.o -rpath /home/hayden/Documents/zig/system_includes_bug/sys_lib_folder/lib -L /home/hayden/Documents/zig/system_includes_bug/sys_lib_folder/lib -L /usr/local/lib64 -L /usr/local/lib -L /usr/lib/x86_64-linux-gnu -L /lib64 -L /lib -L /usr/lib64 -L /usr/lib -L /lib/x86_64-linux-gnu -L /usr/lib/gcc/x86_64-redhat-linux/12/../../../../lib64 -dynamic-linker /lib64/ld-linux-x86-64.so.2 /home/hayden/Documents/zig/system_includes_bug/zig-cache/o/34c04c0538e9a2ae1889b1bbdfe20397/libstaticlib.a /home/hayden/Documents/zig/system_includes_bug/sys_lib_folder/lib/libsys_lib.a /home/hayden/Documents/zig/system_includes_bug/zig-cache/o/a55704026b7918d88b03d934b7f436b6/main.o --as-needed -lm -lpthread -lc -ldl -lrt -lutil /home/hayden/.cache/zig/o/f721cc9442cf1a25959b93955c415395/libcompiler_rt.a /usr/lib/gcc/x86_64-redhat-linux/12/../../../../lib64/crtn.o

Expected Behavior

  • Zig should not be passing .a files directly to the archiver (ar)
  • The warning described above ("BLANK.a is neither ET_REL nor LLVM bitcode" should not occur as AFAIK what I present in my example is a valid way to add a dependency on a system library to a static library
@haydenridd haydenridd added the bug Observed behavior contradicts documented or intended behavior label Jul 2, 2024
@andrewrk andrewrk added the zig build system std.Build, the build runner, `zig build` subcommand, package management label Aug 13, 2024
@andrewrk andrewrk added this to the 0.15.0 milestone Aug 13, 2024
@brianferri
Copy link

Encountered the same issue while attempting to build with zig-linux-x86_64-0.14.0-dev.2370+5c6b25d9b linking zlib, this does not happen in 0.13.0, possible regression?

install
└─ install zuws
   └─ zig build-exe zuws Debug native failure
error: warning(link): unexpected LLD stderr:
ld.lld: warning: /home/brianferri/Desktop/_Misc/Projects/Harmony-co/uWebSocketsZig/.zig-cache/o/1e319ba9fb394e5eaf07e4ebec7fe483/libuWebSockets.a: archive member '/usr/lib/x86_64-linux-gnu/libz.so' is neither ET_REL nor LLVM bitcode
ld.lld: warning: /home/brianferri/Desktop/_Misc/Projects/Harmony-co/uWebSocketsZig/.zig-cache/o/fc19074bca7324f3a745d9c3e09e1296/libuSockets.a: archive member '/usr/lib/x86_64-linux-gnu/libz.so' is neither ET_REL nor LLVM bitcode

Happens in every Optimization mode

@jayschwa
Copy link
Contributor

This applies to shared system libraries too. For example, https://github.com/allyourcodebase/SDL links to the system's libX11.so and libpulse.so. Development versions of Zig (after 0.13.0) pass those to the ar rcs command, which then causes linker warnings for downstream apps.

ar rcs /home/jayschwa/catacomb/SDL/.zig-cache/o/[...]/libSDL2.a /usr/lib/x86_64-linux-gnu/libX11.so /usr/lib/x86_64-linux-gnu/libXext.so /usr/lib/x86_64-linux-gnu/libpulse.so /home/jayschwa/catacomb/SDL/.zig-cache/o/[...]/SDL.o [...]

I think I have identified a potential fix and will submit a pull request.

jayschwa added a commit to jayschwa/zig that referenced this issue Feb 26, 2025
Previously, system libraries like `libX11.so` were passed to `ar rcs`.
Consumers of the archive receive warnings about invalid contents.

Fixes ziglang#20476
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Observed behavior contradicts documented or intended behavior zig build system std.Build, the build runner, `zig build` subcommand, package management
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants