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

Add support for zig cc as C compiler. #13757

Merged
merged 1 commit into from
Apr 8, 2020
Merged

Conversation

hessammehr
Copy link
Contributor

With the upcoming release of Zig 0.6, zig cc can be used as a convenient and portable cross-compiler and a drop-in replacement for clang. This PR allows Nim to use Zig as its C compiler using --cc=zig. Further, you can easily cross-compile like so:

nim c -f --cc:zig --zig.options.linker:"-target x86_64-windows-gnu" --zig.options.always:"-target x86_64-windows-gnu"

@zah
Copy link
Member

zah commented Mar 25, 2020

Why does this feature exist in Zig? Does it allow you to easily compile Zig and C code in the same project (and potentially Nim and Zig code now)?

@hessammehr
Copy link
Contributor Author

I can imagine a number of philosophical and practical reasons in addition to what you mention. Zig already ships with LLVM for code generation, so including Clang is not a big deal. At the same time one of Zig's aims is to make cross-compilation easy, so it bundles the stdlib for a whole bunch of targets, which it can compile on demand, thanks to the bundled Clang. @andrewrk can give you the definitive answer.

The use case of compiling Zig and Nim together is not something I had considered but, given Nim compiles to C, it should be fairly feasible.

@andrewrk
Copy link

Hi 👋

I'm responding to a request from zahary on IRC to explain a little bit about this.

The reason the zig compiler has a C compiler in it is the following reasoning:

  • zig has a translate-c feature so that .h files for example can be imported and used directly, without ffi bindings needed to be added.
  • this feature uses clang to analyze the .h file
  • this requires linking against libclang
  • libclang can compile C code, we may as well expose this feature
  • zig cc adds clang command line argument parsing support, on top of that.

So yes it is just clang doing the compilation, and LLD doing the linking. But the main benefit that zig brings here is that has no system dependencies, so it will "just work" everywhere. (Also the cross compiling stuff which was noted above)

more details on this blog post

If Nim wants to explore this possibility, I would be happy to coordinate!

@juancarlospaco
Copy link
Collaborator

Nim ships a C Compiler too, also #11529

@ghost
Copy link

ghost commented Mar 25, 2020

@juancarlospaco tinyc is not really comparable to Zig. Zig compiler uses LLVM for both C and Zig, so it's basically on the same level for C code as Clang

@ksandvik
Copy link

Won't there be an additional burden to maintain the Zig cc compatibility and regression testing?

@ghost
Copy link

ghost commented Mar 25, 2020

@ksandvik no one says it will be default, Nim supports quite a lot of compilers but most of them aren't really tested, see for example https://github.com/nim-lang/Nim/blob/devel/compiler/extccomp.nim#L94 or https://github.com/nim-lang/Nim/blob/devel/compiler/extccomp.nim#L215 or https://github.com/nim-lang/Nim/blob/devel/compiler/extccomp.nim#L242

The only tested compilers are Clang, GCC, and VCC really, all others are mostly community-supported (if someone uses them and finds a but they might fix it, etc)

@Araq
Copy link
Member

Araq commented Mar 26, 2020

There is a better way to do this but the PR follows the existing practice so it's fine. Will be merged after 1.2 is out.

@dom96
Copy link
Contributor

dom96 commented Apr 1, 2020

Why not just merge now? This PR isn't likely to break anything.

@timotheecour
Copy link
Member

@hessammehr is this supposed to work as-is or would I need additional compilation flags to pass to nim / zig?
right now I'm getting an error on OSX (for a hello world):

nim c -f --cc:zig $timn_D/tests/nim/all/t10536.nim
In file included from /Users/timothee/git_clone/nim/timn/build/nimcache/@mt10536.nim.c:9:
/Users/timothee/git_clone/nim/Nim_devel/lib/nimbase.h:262:10: fatal error: 'limits.h' file not found
#include <limits.h>

ditto with nim c -f --cc:zig --zig.options.linker:"-target x86_64-windows-gnu" --zig.options.always:"-target x86_64-windows-gnu" $timn_D/tests/nim/all/t10536.nim

@hessammehr
Copy link
Contributor Author

hessammehr commented Apr 10, 2020

What version of zig are you using? zig cc is only a drop-in replacement for clang in master afaik. The first official release with this functionality is 0.6.

@ghost
Copy link

ghost commented Apr 10, 2020

@timotheecour did you download the latest master from there?
2020-04-10-17-38-51_grim

@andrewrk
Copy link

FWIW, 0.6.0 is scheduled to be released on Monday.

@timotheecour
Copy link
Member

@timotheecour did you download the latest master from there?

i did brew install zig but brew install --HEAD zig hits ziglang/zig#4799

@ghost
Copy link

ghost commented Apr 11, 2020

What would be the command to compile hello.nim on windows?
I have

C:\Users\->zig version
0.5.0+121307679

C:\Users\->nim --version
Nim Compiler Version 1.3.1 [Windows: amd64]
Compiled at 2020-04-11
Copyright (c) 2006-2020 by Andreas Rumpf

git hash: 5f6962337de94b524afbb4f41b79eae362af67c8
active boot switches: -d:release

And when I run nim c --cc=zig hello.nim I get errors about libc not found from zig:


C:\Users\-\Documents\nim-tests>nim c --cc=zig hello.nim
Hint: used config file 'C:\Program Files\Nim\config\nim.cfg' [Conf]
Hint: system [Processing]
Hint: widestrs [Processing]
Hint: io [Processing]
Hint: hello [Processing]
CC: stdlib_io.nim
CC: stdlib_system.nim
CC: hello.nim
Unable to link against libc: Unable Uto fnablind libc inseta ltloa tliionnk: a glaiibncs tr ulntiibc: Umnea nbolet t of finoudn libc dinstallation
:S elibc e r`uznitgi lmibec n ot found-
-Shee e`zlig lipb` fco --help` for rmore  detailsm.ore
detUanable to linikls.
 against libc: Unable to find libc installation: libc runtime not found
See `zig libc --help` for moreError:  dexecution of an external compiler program 'zig.exe cc -c    -I"C:\Program Files\Nim\lib" -IC:\Users\-\Documents\nim-tests -o C:\Users\-\nimcache\hello_d\stdlib_system.nim.c.o C:\Users\-\nimcache\hello_d\stdlib_system.nim.c' failed with exit code: 1

et
ails.

@hessammehr
Copy link
Contributor Author

I believe nim c -f --cc:zig --zig.options.linker:"-target x86_64-windows-gnu" --zig.options.always:"-target x86_64-windows-gnu" should do the trick.

@ghost
Copy link

ghost commented Apr 11, 2020

@hessammehr Thanks, now it tries to compile the file containing echo "Hello, world" but it fails with

C:\Users\-\Documents\nim-tests>nim c -f --cc:zig --zig.options.linker:"-target x86_64-windows-gnu" --zig.options.always:"-target x86_64-windows-gnu" hello.nim
Hint: used config file 'C:\Program Files\Nim\config\nim.cfg' [Conf]
Hint: system [Processing]
Hint: widestrs [Processing]
Hint: io [Processing]
Hint: hello [Processing]
CC: stdlib_io.nim
CC: stdlib_system.nim
CC: hello.nim
C:\Users\-\nimcache\hello_d\stdlib_io.nim.c:233:27: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
static N_INLINE(NIM_BOOL, nimAddInt)(NI a, NI b, NI* res);
                          ^
C:\Users\-\nimcache\hello_d\stdlib_io.nim.c:233:50: error: expected ')'
static N_INLINE(NIM_BOOL, nimAddInt)(NI a, NI b, NI* res);
                                                 ^
C:\Users\-\nimcache\hello_d\stdlib_io.nim.c:233:27: note: to match this '('
static N_INLINE(NIM_BOOL, nimAddInt)(NI a, NI b, NI* res);
                          ^
C:\Users\-\nimcache\hello_d\stdlib_io.nim.c:412:27: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
static N_INLINE(NIM_BOOL, nimAddInt)(NI a, NI b, NI* res) {
                          ^
C:\Users\-\nimcache\hello_d\stdlib_io.nim.c:412:50: error: expected ')'
static N_INLINE(NIM_BOOL, nimAddInt)(NI a, NI b, NI* res) {
                                                 ^
C:\Users\-\nimcache\hello_d\stdlib_io.nim.c:412:27: note: to match this '('
static N_INLINE(NIM_BOOL, nimAddInt)(NI a, NI b, NI* res) {
                          ^
C:\Users\-\nimcache\hello_d\stdlib_io.nim.c:412:27: error: definition of builtin function '__builtin_saddll_overflow'
static N_INLINE(NIM_BOOL, nimAddInt)(NI a, NI b, NI* res) {
                          ^
C:\Users\-\nimcache\hello_d\stdlib_io.nim.c:412:27: error: parameter name omitted
C:\Users\-\nimcache\hello_d\stdlib_io.nim.c:425:5: error: use of undeclared identifier 'res'
                (*res) = r;
                  ^
2 warnings and 5 errors generated.

The following command failed:
C:\Program Files\Zig\zig.exe clang -c -nostdinc -fno-spell-checking -target x86_64-unknown-windows-gnu -isystem C:\Program Files\Zig\lib\zig\include -isystem C:\Program Files\Zig\lib\zig\libc\include\x86_64-windows-gnu -isystem C:\Program Files\Zig\lib\zig\libc\include\generic-mingw -isystem C:\Program Files\Zig\lib\zig\libc\include\x86_64-windows-any -isystem C:\Program Files\Zig\lib\zig\libc\include\any-windows-any -Xclang -target-cpu -Xclang x86-64 -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 -MD -MV -MF zig-cache\tmp\wcNP-ErXz0DQ-stdlib_io.nim.o.d -Wno-pragma-pack -fno-omit-frame-pointer -fsanitize=undefined -fsanitize-trap=undefined -D_DEBUG -Og -fstack-protector-strong --param ssp-buffer-size=4 -IC:\Program Files\Nim\lib -IC:\Users\-\Documents\nim-tests -o zig-cache\tmp\wcNP-ErXz0DQ-stdlib_io.nim.o C:\Users\-\nimcache\hello_d\stdlib_io.nim.c
Error: execution of an external compiler program 'zig.exe cc -c -target x86_64-windows-gnu   -I"C:\Program Files\Nim\lib" -IC:\Users\-\Documents\nim-tests -o C:\Users\-\nimcache\hello_d\stdlib_io.nim.c.o C:\Users\-\nimcache\hello_d\stdlib_io.nim.c' failed with exit code: 1



C:\Users\-\Documents\nim-tests>C:\Users\-\nimcache\hello_d\stdlib_system.nim.c:481:27: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
static N_INLINE(NIM_BOOL, nimMulInt)(NI a, NI b, NI* res);
                          ^
C:\Users\-\nimcache\hello_d\stdlib_system.nim.c:481:50: error: expected ')'
static N_INLINE(NIM_BOOL, nimMulInt)(NI a, NI b, NI* res);
                                                 ^
C:\Users\-\nimcache\hello_d\stdlib_system.nim.c:481:27: note: to match this '('
static N_INLINE(NIM_BOOL, nimMulInt)(NI a, NI b, NI* res);
                          ^
C:\Users\-\nimcache\hello_d\stdlib_system.nim.c:487:27: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
static N_INLINE(NIM_BOOL, nimAddInt)(NI a, NI b, NI* res);
                          ^
C:\Users\-\nimcache\hello_d\stdlib_system.nim.c:487:50: error: expected ')'
static N_INLINE(NIM_BOOL, nimAddInt)(NI a, NI b, NI* res);
                                                 ^
C:\Users\-\nimcache\hello_d\stdlib_system.nim.c:487:27: note: to match this '('
static N_INLINE(NIM_BOOL, nimAddInt)(NI a, NI b, NI* res);
                          ^
C:\Users\-\nimcache\hello_d\stdlib_system.nim.c:4880:27: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
static N_INLINE(NIM_BOOL, nimMulInt)(NI a, NI b, NI* res) {
                          ^
C:\Users\-\nimcache\hello_d\stdlib_system.nim.c:4880:50: error: expected ')'
static N_INLINE(NIM_BOOL, nimMulInt)(NI a, NI b, NI* res) {
                                                 ^
C:\Users\-\nimcache\hello_d\stdlib_system.nim.c:4880:27: note: to match this '('
static N_INLINE(NIM_BOOL, nimMulInt)(NI a, NI b, NI* res) {
                          ^
C:\Users\-\nimcache\hello_d\stdlib_system.nim.c:4880:27: error: definition of builtin function '__builtin_smulll_overflow'
static N_INLINE(NIM_BOOL, nimMulInt)(NI a, NI b, NI* res) {
                          ^
C:\Users\-\nimcache\hello_d\stdlib_system.nim.c:4880:27: error: parameter name omitted
C:\Users\-\nimcache\hello_d\stdlib_system.nim.c:4897:5: error: use of undeclared identifier 'res'
                (*res) = r;
                  ^
C:\Users\-\nimcache\hello_d\stdlib_system.nim.c:4910:6: error: use of undeclared identifier 'res'
                        (*res) = r;
                          ^
C:\Users\-\nimcache\hello_d\stdlib_system.nim.c:4948:27: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
static N_INLINE(NIM_BOOL, nimAddInt)(NI a, NI b, NI* res) {
                          ^
C:\Users\-\nimcache\hello_d\stdlib_system.nim.c:4948:50: error: expected ')'
static N_INLINE(NIM_BOOL, nimAddInt)(NI a, NI b, NI* res) {
                                                 ^
C:\Users\-\nimcache\hello_d\stdlib_system.nim.c:4948:27: note: to match this '('
static N_INLINE(NIM_BOOL, nimAddInt)(NI a, NI b, NI* res) {
                          ^
C:\Users\-\nimcache\hello_d\stdlib_system.nim.c:4948:27: error: definition of builtin function '__builtin_saddll_overflow'
static N_INLINE(NIM_BOOL, nimAddInt)(NI a, NI b, NI* res) {
                          ^
C:\Users\-\nimcache\hello_d\stdlib_system.nim.c:4948:27: error: parameter name omitted
C:\Users\-\nimcache\hello_d\stdlib_system.nim.c:4961:5: error: use of undeclared identifier 'res'
                (*res) = r;
                  ^
4 warnings and 11 errors generated.

The following command failed:
C:\Program Files\Zig\zig.exe clang -c -nostdinc -fno-spell-checking -target x86_64-unknown-windows-gnu -isystem C:\Program Files\Zig\lib\zig\include -isystem C:\Program Files\Zig\lib\zig\libc\include\x86_64-windows-gnu -isystem C:\Program Files\Zig\lib\zig\libc\include\generic-mingw -isystem C:\Program Files\Zig\lib\zig\libc\include\x86_64-windows-any -isystem C:\Program Files\Zig\lib\zig\libc\include\any-windows-any -Xclang -target-cpu -Xclang x86-64 -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 -MD -MV -MF zig-cache\tmp\uB0mnCMtBf0w-stdlib_system.nim.o.d -Wno-pragma-pack -fno-omit-frame-pointer -fsanitize=undefined -fsanitize-trap=undefined -D_DEBUG -Og -fstack-protector-strong --param ssp-buffer-size=4 -IC:\Program Files\Nim\lib -IC:\Users\-\Documents\nim-tests -o zig-cache\tmp\uB0mnCMtBf0w-stdlib_system.nim.o C:\Users\-\nimcache\hello_d\stdlib_system.nim.c

It seems, that this doesn't work on linux too: https://forum.nim-lang.org/t/5939#38185 (similiar or same error like mine)

@hessammehr
Copy link
Contributor Author

This goes beyond my knowledge of how the nim compiler works but it seems like the C code produced in this case is different, since compiling it with clang gives the same error.

clang -c    -I/home/group/Code/nim-1.3.1/lib -I/home/group/Code -o /home/group/.cache/nim/nim1_d/stdlib_io.nim.c.o /home/group/.cache/nim/nim1_d/stdlib_io.nim.c
/home/group/.cache/nim/nim1_d/stdlib_io.nim.c:46:27: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
static N_INLINE(NIM_BOOL, nimAddInt)(NI a, NI b, NI* res);
                          ^
/home/group/.cache/nim/nim1_d/stdlib_io.nim.c:46:50: error: expected ')'
static N_INLINE(NIM_BOOL, nimAddInt)(NI a, NI b, NI* res);
                                                 ^
/home/group/.cache/nim/nim1_d/stdlib_io.nim.c:46:27: note: to match this '('
static N_INLINE(NIM_BOOL, nimAddInt)(NI a, NI b, NI* res);
                          ^
/home/group/.cache/nim/nim1_d/stdlib_io.nim.c:78:27: warning: type specifier missing, defaults to 'int' [-Wimplicit-int]
static N_INLINE(NIM_BOOL, nimAddInt)(NI a, NI b, NI* res) {
                          ^
/home/group/.cache/nim/nim1_d/stdlib_io.nim.c:78:50: error: expected ')'
static N_INLINE(NIM_BOOL, nimAddInt)(NI a, NI b, NI* res) {
                                                 ^
/home/group/.cache/nim/nim1_d/stdlib_io.nim.c:78:27: note: to match this '('
static N_INLINE(NIM_BOOL, nimAddInt)(NI a, NI b, NI* res) {
                          ^
/home/group/.cache/nim/nim1_d/stdlib_io.nim.c:78:27: error: definition of builtin function '__builtin_saddll_overflow'
static N_INLINE(NIM_BOOL, nimAddInt)(NI a, NI b, NI* res) {
                          ^
/home/group/.cache/nim/nim1_d/stdlib_io.nim.c:78:27: error: parameter name omitted
/home/group/.cache/nim/nim1_d/stdlib_io.nim.c:91:5: error: use of undeclared identifier 'res'
                (*res) = r;
                  ^
2 warnings and 5 errors generated.

@ghost
Copy link

ghost commented Apr 11, 2020

Ok, thanks, so I guess it's not a problem with zig.

@hessammehr
Copy link
Contributor Author

hessammehr commented Apr 11, 2020

@Tim-St I think I have a fix for your issue. Probably best if you open a new issue since this PR has been closed.
Edit: You can use the branch in the PR below for the time being. Still worth opening an issue I suppose.

@timotheecour
Copy link
Member

FWIW, 0.6.0 is scheduled to be released on Monday.

@hessammehr @andrewrk I've retried now that zig 0.6.0 was released but I'm now hitting 'Unable to find target for this triple (no targets are registered)', see ziglang/zig#5055 ; any idea how to use it on OSX?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants