I've been confused by the statement that "Zig can compile C Code" for quite some time and reading a couple of blog posts hasn't made it much clearer.
Does the Zig Project include a full blown C Compiler? Is it the Zig Compiler with some sort of adaptation to compile C code? Or does it use something like Clang behind the curtains? (In this case it would be responsible for some other parts of the compilation process)
Zig embeds clang to compile C code. This doesn't add a new dependency since Zig already depends on LLVM. If there is a future where the self-hosted Zig backend is good enough to not depend on LLVM anymore, there might be a reason to use a C compiler written in Zig (possibly https://github.com/Vexu/arocc)
Also worth noting that Zig embeds C stdlib source code (musl if I'm not mistaken). That means it is easier to cross compile C projects using zig since you don't need to install a cross toolchain. This is why some golang/rust projects use Zig when they need to cross compile.
This isn't quite correct. Yes, it can output C code; however the result is not very readable at all, and fails the DFSG on generated code. It _is_ useful for compiling Zig code to targets which aren't supported by LLVM, however.
Do you have a reference for this? Does it use a C backend that is part of LLVM, or is it something Zig-specific? What are its limitations? Can it compile libraries to C, or only entire applications?
I have wanted Rust and Zig to support compile-to-C for a while, so this is exciting news for me.
One thing that would particularly interest me is if functions intended to be inlined could be emitted into .h files.
1. It uses LLVM as the default backend, in which case that handles C as well
2. Optionally, and in the future by default, the Zig backend (a different one from the LLVM one) includes a C compiler (?)
Something like that. Its very powerful and it has the best C integration of any language in my experience (better than C++ since it effectively namespaces C headers).
Thanks for the answer but some things are still not entirely clear.
Who would be doing the parsing of C code for instance? Clang is also based LLVM but it is responsible for a load of C-specific stuff like parsing the language and feeding it into LLVM for instance.
I've got little experience with this stuff so I'm not sure if my questions even make that much sense.
(Edit: I believe ptato has answered my question above.)
You can invoke `zig cc` with the same flags that you would pass to `clang`. Zig cc takes your arguments, inspects them and applies some transformations and then Zig invokes its internal copy of clang with the resulting flags. One example of transformation is enabling ubsan when building in debug mode, another is `-target` which makes Zig add some sysroot flags to enable cross-compilation.
In this case all the file operations are handled by clang, Zig basically just sets up all the advanced flags for you when it makes sense to do so. One last example of CLI rewriting is related to the caching system: Zig cc knows how to cache a build by passing to clang the same kind of flags that cmake (or other build systems) would.
There's another C-related feature of Zig that works differently: `@cImport()`, which is a builtin that allows you to import C header files directly into a Zig script, in order to use from Zig all the types exposed by the header file. This one translates the C syntax in equivalent Zig syntax. I believe it uses clang's code to parse the C code into an AST, but then it's all Zig logic from there.
Lastly, we have a C frontend project going (arocc, linked by ptato) on that we plan to eventually upstream into Zig. This would be a replacement for clang and would work by parsing the C code and translating it into Zig IR, similarly to how the D programming language does it. The only limitation of this approach is that it would only support C, not C++, so we would either have to still keep clang around for C++, or ditch clang but then lose C++ compilation support. That said, even in the case where we keep clang around for C++ support, it would be worth having a custom C frontend for the Zig compiler in order to have more fine-grained control over the compilation process than what we can get from clang, plus the fact that it would make debug builds faster, since we could avoid invoking LLVM completely in that case (ie debug builds) even if you depend on C code.
How does this work on the assembly support side? I can see inline assembly, something called global assembly, but is Zig build also able to build standalone assembly main.asm type files?
I'd like to add the link to the use examples demonstrating features of zig for c and c++ compilation available with the default zig installation which aren't directly available after installing clang:
Sorry, I wasn’t specific. I was talking about how cImport works in Zig. I didn’t know `zig cc` worked differently.
“ Zig’s @cImport builtin is unique in that it takes in an expression, which can only take in @cInclude, @cDefine, and @cUndef. This works similarly to translate-c, translating C code to Zig under the hood.”
https://ziglearn.org/chapter-4/
Does the Zig Project include a full blown C Compiler? Is it the Zig Compiler with some sort of adaptation to compile C code? Or does it use something like Clang behind the curtains? (In this case it would be responsible for some other parts of the compilation process)