Zig is not just a programming language but also a toolchain that can help you maintain and gradually modernize existing C/C++ projects, based on your needs. In this series we're using Redis, a popular in-memory key value store written in C, as an example of a real project that can be maintained with Zig. You can read more in "Maintain it with Zig".
Zig is a programming language with no runtime, a focus on simplicity, and great C interoperability. Zig bundles LLVM to create optimized release builds and so it's also a full-fledged C/C++ compiler.
zig cc and
zig c++, two commands that expose an interface flag-compatible with clang, allowing you to use the Zig compiler as a drop-in replacement for your existing C/C++ compiler.
For a more complete overview you can check out https://ziglang.org.
As we'll see in the next posts in this series, there are a few different reasons to consider making Zig your default C/C++ compiler, but for now let's just focus on some basic advantages that you can get without any extra effort.
Zig is distributed as a ~40MB archive (by comparison LLVM is about 200MB). Unzip it and you're good to go. No extra dependencies needed. The only (optional) extra step is to include
zig to your
PATH, to be able to invoke compilation from any directory.
This is great for creating build pipelines, for example: no complex Chef scripts, Docker containers or VM images. Just download, unzip and run.
Making a change to a single compilation unit should not trigger a full recompilation of the entire project. If you're using a build system like Make, then you're good, but if you're just using a simple build script that invokes the compiler directly, you're out of luck... unless you use Zig.
Zig keeps track of all dependencies for each compilation unit and can compile your project incrementally without requiring any configuration or external build system.
By default Zig enables all the features present in your CPU (e.g. SSE, AVX), producing more efficient binaries out of the box than other compilers. In debug builds Zig also enables UBSAN by default.
Finally, all of this is especially relevant when it comes to common libraries like libc, libcxx, compiler-rt, tsan, libunwind. All these libraries are bundled in Zig in source form and gain native improvements when being built for your native target.
Let's see how hard it is to compile Redis with Zig. Note that Redis doesn't support Windows so you will need a Linux/macOS/BSD host to reproduce the following steps.
Read the getting started guide to learn how to get a copy of Zig. You can choose between downloading a tarball directly and using a package manager.
To be able to follow along and reproduce this blog post, you will need to use Zig 0.8.1 and commit
be6ce8a of Redis. Both Zig and Redis are being actively developed and over time things will change, potentially breaking the code in this series. Of course the same general approach will keep working over time but this is the only way of guaranteeing that you can follow along and have everything work first try.
You can get a copy of Redis by cloning the official repository.
git clone https://github.com/redis/redis.git # Don't forget to checkout the right commit git checkout be6ce8a
If you read Redis' README you can see that to build it all you need to do is call
make. To make
make use Zig, all you have to do is specify a couple of variables when invoking the command.
make CC="zig cc" CXX="zig c++"
If you're wondering why we are also specifying a C++ compiler, it's because
jemalloc, one of Redis' optional dependencies, is a C++ project.
If everything went well, you should see a message inviting you to run the tests and freshly build executables inside
If you got something wrong, make sure to run
make distclean before trying again.
That's all you need to do to use Zig as a C/C++ compiler. It's almost funny how minimal is the how-to part of this post, but that's kinda the point.
The next part of this series will introduce a much more interesting concept: cross-compilation, which will allow you to create a Linux executable from Windows and/or from x86_64 to ARM, etc.