Skip to content

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

@haydenridd

Description

@haydenridd

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugObserved behavior contradicts documented or intended behaviorzig build systemstd.Build, the build runner, `zig build` subcommand, package management

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions