zig cc -Wl,--version: unsupported linker arg: --version
zig cc -Wl,--version is not understood by the linker:
clang-16
$ clang-16 -Wl,--version
GNU ld (GNU Binutils for Ubuntu) 2.38
Copyright (C) 2022 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) a later version.
This program has absolutely no warranty.
zig-cc
$ zig cc -Wl,--version
error: unsupported linker arg: --version
meson uses it to determine the linker. Example when configuring glib:
$ CC="zig cc" CXX="zig c++" meson setup .. --prefix=/tmp
The Meson build system
Version: 0.61.2
Source dir: /home/motiejus/x/glib-2.69.3
Build dir: /home/motiejus/x/glib-2.69.3/build
Build type: native build
Project name: glib
Project version: 2.69.3
../meson.build:1:0: ERROR: Unable to detect linker for compiler "zig cc -Wl,--version"
stdout:
stderr: error: unsupported linker arg: --version
A full log can be found at /home/motiejus/x/glib-2.69.3/build/meson-logs/meson-log.txt
I did not find a reasonable way to add such flag to src/main.zig and src/Compilation.zig. The best current way to do it is here:
https://github.com/ziglang/zig/blob/28923474401051a9aa0bddd60904b9be64943dba/src/Compilation.zig#L3942-L3948
However, this whole function implies a single c_object is passed, which is obviously not the case here.
Just encountered similar problem while trying to use zig cc as drop-in replacement with meson-based build. Found no way to override this yet, so I assume this means a no-go for meson use cases, unless flag gets supported on zig cc side.
Here's what I think it should do:
$ zig cc -Wl,--version
zig ld 0.11.0-dev.3198+ad20236e9
It will be up to Meson to decide what to do with this information.
I am hitting the same problem with cmake; trying to use zig as drop in replacement for C/C++.
Cmake generates the shorter argument -v and the failing command becomes:
zig cc -Wl,-v
I would like to contribute to this issue, but I am new to Zig and its compiler, so I take it as an opportunity to dig deeper into Zig if someone is willing to guide me.
Me digging the code
To my understanding, the execution of zig cc -Wl,--version does not find a match for --version.
This triggers the execution of this final else statement and thus call fatal.
https://github.com/ziglang/zig/blob/128fd7dd02ae112cba68d0ad6cc40dc1ce8c34b1/src/main.zig#L2207-L2217
A very naive approach that I tried is to add another else if block that should match the --version word.
So, right before the final else, I added this piece of code:
else if (mem.eql(u8, arg, "--version")) {
try std.io.getStdOut().writeAll("zig ld " ++ build_options.version ++ "\n");
}
However, this has two effects:
- print to stdout
zig ld 0.11.0-dev.3735+a72d634b7 - continue the execution of the program and also add to stdout
GNU ld (GNU Binutils for Ubuntu) 2.38
Copyright (C) 2022 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) a later version.
This program has absolutely no warranty.
This secondary effect is produced when hitting line 2272
https://github.com/ziglang/zig/blob/128fd7dd02ae112cba68d0ad6cc40dc1ce8c34b1/src/main.zig#L2267-L2273
Questions
I read the comment https://github.com/ziglang/zig/issues/15549#issue-1692182315 but i do not understand why this https://github.com/ziglang/zig/blob/28923474401051a9aa0bddd60904b9be64943dba/src/Compilation.zig#L3942-L3948 should be the place to act to fix the issue.
May I have some help to clear my mind? Since it's my first look at the code I am missing the big picture (and many details as well :D ).
Questions
I read the comment #15549 (comment) but i do not understand why this
https://github.com/ziglang/zig/blob/28923474401051a9aa0bddd60904b9be64943dba/src/Compilation.zig#L3942-L3948
should be the place to act to fix the issue.
My original intent was to execve to the underlying system-specific lld. So the output of zig cc -Wl,--version would be equivalent to this:
$ zig ld.lld --version
LLD 16.0.1 (compatible with GNU linkers)
May I have some help to clear my mind? Since it's my first look at the code I am missing the big picture (and many details as well :D ).
What Andrew is proposing is much easier to implement, since you don't need to invoke the underlying linker.
continue the execution of the program and also add to stdout
I believe this should not be necessary. Just exit after printing the version.
I see it now, thanks for the clarification! If the goal is to print the version and exit, I would gladly open a PR and make my contribution.
Shall I add the -v option as well? I discovered this because I stumbled upon the same problem using zig cc -Wl,-v
I implemented the change, but then, while using it, I realized that it is more complicated than anticipated.
Simple printing the version and exit does not work since it will cause an early exit on any invocation of zig cc or zig c++ including the -Wl,-v argument.
On the other end, printing the ld version and continue the program execution will behave correctly, but it will print on stdout both zig ld <version> and the linker version output.
What would be the correct behaviour?
Would it be correct to intercept the "-Wl,-v", print the zig ld <version> to stdout and then remove the "-v" from the linker argument before passing the control to clangMain(arena, all_args) ? Sounds very hackish though.
Am I missing something else?
I implemented the change, but then, while using it, I realized that it is more complicated than anticipated.
Simple printing the version and exit does not work since it will cause an early exit on any invocation of
zig ccorzig c++including the-Wl,-vargument.On the other end, printing the ld version and continue the program execution will behave correctly, but it will print on stdout both
zig ld <version>and the linker version output.What would be the correct behaviour?
We should follow the lead on what gcc/clang do:
motiejus@mtwork:/code/hermetic_cc_toolchain/test/c$ clang-16 -fuse-ld=lld -Wl,--version main.c -o main
Ubuntu LLD 16.0.6 (compatible with GNU linkers)
motiejus@mtwork:/code/hermetic_cc_toolchain/test/c$ clang-16 -Wl,--version main.c -o main
GNU ld (GNU Binutils for Ubuntu) 2.38
Copyright (C) 2022 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) a later version.
This program has absolutely no warranty.
motiejus@mtwork:/code/hermetic_cc_toolchain/test/c$ gcc -Wl,--version main.c -o main
collect2 version 11.3.0
/usr/bin/ld -plugin /usr/lib/gcc/x86_64-linux-gnu/11/liblto_plugin.so -plugin-opt=/usr/lib/gcc/x86_64-linux-gnu/11/lto-wrapper -plugin-opt=-fresolution=/tmp/ccjuwBPu.res -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s -plugin-opt=-pass-through=-lc -plugin-opt=-pass-through=-lgcc -plugin-opt=-pass-through=-lgcc_s --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -dynamic-linker /lib64/ld-linux-x86-64.so.2 -pie -z now -z relro -o main /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/Scrt1.o /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/11/crtbeginS.o -L/usr/lib/gcc/x86_64-linux-gnu/11 -L/usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/11/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/11/../../.. --version /tmp/cc24Zva2.o -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /usr/lib/gcc/x86_64-linux-gnu/11/crtendS.o /usr/lib/gcc/x86_64-linux-gnu/11/../../../x86_64-linux-gnu/crtn.o
GNU ld (GNU Binutils for Ubuntu) 2.38
Copyright (C) 2022 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or (at your option) a later version.
This program has absolutely no warranty.
It does not create a file:
motiejus@mtwork:/code/hermetic_cc_toolchain/test/c$ ls -lh ./main
ls: cannot access './main': No such file or directory
Does that help?
Yes! Actually thanks to your example I found out what was bugging me: -v and --versionare two completely different arguments.
-v stands for --verbose but I was keep reading it as --version.
I got even more confused because the verbose argument also print the version of the linker, and so I wasn't spotting my mistake.
Well, I guess I can revisit my PR, remove the -v argument, implement the --version behavior and open a different issue for the --verbose/-v unsupported linker arg.