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".
What is 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 has 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.
Why not just stick with gcc/clang/msvc?
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.
Ease of setup
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.
Caching system
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.
Better defaults
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.
Compiling Redis with Zig
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.
Download Zig
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.
⚠️ VERY IMPORTANT NOTE ⚠️
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.
Get Redis
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
Compile!
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 src
.
If you got something wrong, make sure to run make distclean
before trying again.
What's next?
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.
Top comments (2)
E:\DawgZig\redis>make CC="zig cc" CXX="zig c++"
cd src && C:/ProgramData/chocolatey/lib/make/tools/install/bin/make.exe all
make[1]: Entering directory 'E:/DawgZig/redis/src'
process_begin: CreateProcess(NULL, sh -c ./mkreleasehdr.sh, ...) failed.
Makefile:15: pipe: No error
what's this error about?
I'm excited to follow along this (PS: I've watched all your YouTube videos 😁). I feel like you're one of the man reasons I have an eye on zig.