Thanks a lot for adding zig cc and zig c++ functionality. It is really useful.
I tried to use zig c++ instead of the standard LLVM toolchain for one of my projects. I build it on MacOS. In general, it mostly works, but I've discovered the following issues:
1) There is a number of flags passed to the linker using -Wl,my_linker_option. They are important for proper linking of the project. But some of them are not supported yet.
warning: unsupported linker arg: -search_paths_first
warning: unsupported linker arg: -headerpad_max_install_names
warning: unsupported linker arg: -force_load
warning: unsupported linker arg: -force_load
2) If I configure my CMake-based project to use make and then run make, it seems to work fine as long as make is using just a single thread. But if I use e.g. make -j 2 I start seeing some issues:
zig -c test.cpp -std=c++14 -ffast-math -fno-finite-math-only -g -I/path/to/include -emit-llvm -O0 -o test.o
Invalid argument: -c
It seems as if there is a race condition somewhere. As you can seen in zig's command line it misses c++ after zig somehow.
3) If I configure my CMake-based project to use ninja and then run ninja, I see issues with dependency tracking supported by clang. Specifically, there seems to be an issue with handling of -MF flags (see below). Same project can be build just fine if I use the vanilla LLVM toolchain.
zig: error: no such file or directory: 'test.cpp.o.d'
The following command failed when running ninja:
zig clang -c -MD -MV -MF zig-cache/tmp/eamNMvLXEZYC-test.o.d -MD -MT -MF test.cpp.o.d -o zig-cache/tmp/eamNMvLXEZYC-test.o test.cpp
It would be nice if these issues could be resolved.
Please let me know if I can provide any additional information that would allow to fix these issues.
Oh, one more thing I forgot to mention:
4) If I use CXX="zig c++" cmake it runs into some problems for some targets that play with the compiler name. It seems like cmake does not correctly handle the space between zig and c++ in some cases. So, I created a small shell-wrapper called zigc++ which looks like this:
#!/bin/bash
zig c++ $@
If I then use it like CXX="zigc++" cmake, then the issue disappears. So, maybe it is a good idea to provide such wrappers for zig cc and zig c++ as part of Zig pre-built binaries?
zig -c test.cpp -std=c++14 -ffast-math -fno-finite-math-only -g -I/path/to/include -emit-llvm -O0 -o test.o
Invalid argument: -c
you're missing c++ here. zig c++ -c ...
edit: oops, I see that you noticed this. can you confirm that it's a problem on zig's end though?
edit: oops, I see that you noticed this. can you confirm that it's a problem on zig's end though?
The thing is: if I use a single-threaded make, it does not happen. It seems to happen only with make -j N, where N > 1. Which indicates that command-line options are passed correctly to zig in a single-threaded make.
You could verify this with strace -f -e trace=execve make ... and then see what argv is being passed to zig
You could verify this with strace -f -e trace=execve make ... and then see what argv is being passed to zig
Seems like it is a make issue, because make dumps a wrong command line in verbose mode. I tried to use the zigc++ wrapper instead of zig c++ and the issue disappears. Seems like the whitespace between zig and c++ is an issue for CMake or make or both of them.
(2) is a make issue as noted above
(3) is solved in e4edc6d118e0e0cd3510bbe89ca4a292436bb82f
(4) there is no plan to do this; I consider that to be out of scope of the project
As for (1) I am repurposing this issue to address it. If you run into any more independent problems, let's handle those in new issues.
Alright so the remaining issue has to do with the fact that Zig uses LLD as the linker, and until very recently the mach-o LLD code was unmaintained. It does not support these flags.
However now I expect this new team to quickly bring LLD up to speed for mach-o, and so I expect this issue to be resolved with the release of LLVM 11 (in 6 months).
@andrewrk BTW, I was about to download the latest builds from https://ziglang.org/download/#release-master, but it seems to be not updated since yesterday for some reason. Don't know if it is expected or not.
Alright so the remaining issue has to do with the fact that Zig uses LLD as the linker, and until very recently the mach-o LLD code was unmaintained. It does not support these flags.
I don't quite understand this comment. Couldn't Zig just pass the provided -Wl,my_linker_option to a linker "as is", without doing anything about these flags?
Or do you say that the error messages I see are from the LLD linker and not from Zig?
(2) is a make issue as noted above
(4) there is no plan to do this; I consider that to be out of scope of the project
Regarding (2) and (4), my impression it is essentially the same problem, which is a space between zig and cc or c++. I don't have a strong opinion here, but IMHO if this is something that makes use of zig with make/cmake as a C/C++ compiler problematic, it would be nice to have a standard solution for that (e.g. a simple wrapper), especially if it is so trivial. After all, most people use some build systems to build their projects and ideally they shouldn't need any custom workarounds to use Zig. But the decision about this topic is of course yours.
(3) is solved in e4edc6d
I'll test and report back ASAP.
@andrewrk BTW, I was about to download the latest builds from https://ziglang.org/download/#release-master, but it seems to be not updated since yesterday for some reason. Don't know if it is expected or not.
Thanks for letting me know. Fixed in https://github.com/ziglang/www.ziglang.org/commit/88683aa8cdf2b26b30baaf5f6e64f9a9b621c1a8 (had to update the update-download-page.zig script to the latest zig std lib after making breaking changes).
I don't quite understand this comment. Couldn't Zig just pass the provided
-Wl,my_linker_optionto a linker "as is", without doing anything about these flags?
a linker
Which one?
Which one?
E.g. -Wl,-search_paths_first, -Wl,-force-load, -Wl,-headerpad_max_install_names
sorry, I meant, which linker?
sorry, I meant, which linker?
Clang on MacOS uses /usr/bin/ld if it is asked to link an executable. So, I assumed Zig would do the same.
The macOS linker /usr/bin/ld is not available on non-macOS systems, so relying on it would prevent cross-compiling for macOS. Also /usr/bin/ld is not always available on macOS systems, for example if xcode command line tools have not been installed. This is why Zig uses LLD as the linker, rather than depending on a system linker, and it means that zig cc is an alternative to installing the xcode command line tools. All of that relies on LLD working well on macOS however, which has not yet been the case. But finally, LLD's macos support is seeing some love, and I expect this situation to change during this release cycle of LLVM.
Ah, OK. Thanks for the clarifications regarding those linker issues! I cross my fingers that LLD's macos support will be improved soon :-)
Quick question: Have you considered adding something like -fuse-ld=/path/to/your/linker, which is supported by clang. This could be useful for using non-standard linkers in case it is needed.
(3) is solved in e4edc6d
@andrewrk I tried with the latest build, to check if -MF, -MT and -MD flags are now processed properly.
I reproduced with a very simple simple.cpp file, which just prints "Hello World!".
zig c++ -MD -MT simple.cpp.o -MF simple.cpp.o.d -o simple.o -c simple.cpp
And I get
zig: error: no such file or directory: 'simple.cpp.o.d'
The following command failed:
~/src/zig-macos-x86_64-0.5.0+b5526d0b3/zig clang -c -nostdinc -fno-spell-checking -isystem ~/src/zig-macos-x86_64-0.5.0+b5526d0b3/lib/zig/libcxx/include -D_LIBCPP_DISABLE_VISIBILITY_ANNOTATIONS -D_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS -target x86_64-unknown-macosx-gnu -isystem ~/src/zig-macos-x86_64-0.5.0+b5526d0b3/lib/zig/include -isystem /usr/include -Xclang -target-cpu -Xclang skylake -Xclang -target-feature -Xclang -3dnow,-3dnowa,+64bit,+adx,+aes,+avx,+avx2,-avx512bf16,-avx512bitalg,-avx512bw,-avx512cd,-avx512dq,-avx512er,-avx512f,-avx512ifma,-avx512pf,-avx512vbmi,-avx512vbmi2,-avx512vl,-avx512vnni,-avx512vp2intersect,-avx512vpopcntdq,+bmi,+bmi2,-branchfusion,-cldemote,+clflushopt,-clwb,-clzero,+cmov,+cx16,+cx8,-enqcmd,+ermsb,+f16c,-false-deps-lzcnt-tzcnt,+false-deps-popcnt,-fast-11bytenop,-fast-15bytenop,-fast-bextr,+fast-gather,-fast-hops,-fast-lzcnt,+fast-scalar-fsqrt,-fast-scalar-shift-masks,+fast-shld-rotate,+fast-variable-shuffle,+fast-vector-fsqrt,-fast-vector-shift-masks,+fma,-fma4,+fsgsbase,+fxsr,-gfni,-idivl-to-divb,+idivq-to-divl,+invpcid,-lea-sp,-lea-uses-ag,-lwp,+lzcnt,+macrofusion,+merge-to-threeway-branch,+mmx,+movbe,-movdir64b,-movdiri,-mpx,-mwaitx,+nopl,-pad-short-functions,+pclmul,-pconfig,-pku,+popcnt,-prefer-128-bit,-prefer-256-bit,-prefer-mask-registers,-prefetchwt1,+prfchw,-ptwrite,-rdpid,+rdrnd,+rdseed,-retpoline,-retpoline-external-thunk,-retpoline-indirect-branches,-retpoline-indirect-calls,+rtm,+sahf,+sgx,-sha,-shstk,+slow-3ops-lea,-slow-incdec,-slow-lea,-slow-pmaddwd,-slow-pmulld,-slow-shld,-slow-two-mem-ops,-slow-unaligned-mem-16,-slow-unaligned-mem-32,-soft-float,+sse,-sse-unaligned-mem,+sse2,+sse3,+sse4.1,+sse4.2,-sse4a,+ssse3,-tbm,-use-aa,-use-glm-div-sqrt-costs,-vaes,-vpclmulqdq,+vzeroupper,-waitpkg,-wbnoinvd,+x87,-xop,+xsave,+xsavec,+xsaveopt,+xsaves -fno-omit-frame-pointer -fsanitize=undefined -fsanitize-trap=undefined -D_DEBUG -Og -fstack-protector-strong --param ssp-buffer-size=4 -fPIC -MT -MF simple.cpp.o.d -o zig-cache/tmp/k0VTvsQBoTOp-simple.o simple.cpp
If I try a slightly different command-line without -MT simple.cpp.o, then there is no failure:
zig c++ -MD -MF simple.cpp.o.d -o simple.o -c simple.cpp
Thanks for the report. Solved in f8cc6a191723d763fc7a8908f3e5beb4eff8317f.
Quick question: Have you considered adding something like
-fuse-ld=/path/to/your/linker, which is supported by clang. This could be useful for using non-standard linkers in case it is needed.
This is a big topic, too big to answer as a quick question
Thanks for the report. Solved in f8cc6a1.
Great! I can confirm that -MT issues are solved now. My project can be build almost correctly, except for the -Wl,-force-load issue mentioned before, which results in the wrongly linked executables missing some parts.
Good to know. Let's revisit the linker issues once LLVM 11 is a bit further along in the release cycle.
LLVM 11 seems to have be have been released in October. Is this fixed?
Most helpful comment
You could verify this with
strace -f -e trace=execve make ...and then see what argv is being passed to zig