Compiling programs in Zig
Up to now, we have used the zig command to run the examples with zig run file.zig. If we type zig --help, we will see the following output:
|
$ zig --help |
|
Usage: zig [command] [options] Commands: build Build project from build.zig fetch Copy a package into global cache and print its hash init Initialize a Zig package in the current directory build-exe Create executable from source or object files build-lib Create library from source or object files build-obj Create object from source or object files test Perform unit testing test-obj Create object for unit testing run Create executable and run immediately ast-check Look for simple compile errors in any set of files fmt Reformat Zig source into canonical form reduce Minimize a bug report translate-c Convert C code to Zig code ar Use Zig as a drop-in archiver cc Use Zig as a drop-in C compiler c++ Use Zig as a drop-in C++ compiler dlltool Use Zig as a drop-in dlltool.exe lib Use Zig as a drop-in lib.exe ranlib Use Zig as a drop-in ranlib objcopy Use Zig as a drop-in objcopy rc Use Zig as a drop-in rc.exe env Print lib path, std path, cache directory, and version help Print this help and exit std View standard library documentation in a browser libc Display native libc paths file or validate one targets List available compilation targets version Print version number and exit zen Print Zen of Zig and exit General Options: -h, --help Print command-specific usage |
There is quite a lot of information to start with, but we will focus mainly on the lines that contain the word build.
Compiling a simple executable: build-exe
If we want to compile a plain executable, we use:
zig build-exe file.zig
This command creates an executable in the current working directory (cwd). The executable will have the same name as the file.zig, but without the .zig extension. On Windows, I assume it will have the .exe extension.
If we look at the help for zig build-exe itself with zig build-exe | more (more is used to view the entire output gradually), we will see this:
|
$ zig build-exe --help | more |
|
Usage: zig build-exe [options] [files]
... Per-Module Compile Options: -O [mode] Choose what to optimize for Debug (default) Optimizations off, safety on ReleaseFast Optimize for performance, safety off ReleaseSafe Optimize for performance, safety on ReleaseSmall Optimize for small binary, safety off ... etc. |
This means that we can specify, using the -O option followed by a mode, how Zig will optimize the final executable.
Compilation modes
- Debug: not optimized but safe
- ReleaseFast: fast but unsafe
- ReleaseSafe: fast and safe
- ReleaseSmall: reduced size but unsafe
Unsafe here means that runtime safety checks are disabled.
For example: overflow detection in arithmetic operations, out-of-bounds checks on arrays and slices, detection of null pointer usage, and access to invalid memory.
In unsafe mode, if the program has a bug of this kind, you will get undefined behavior instead of a failure with a clear message when the runtime error occurs.
For example, the program might crash or -even worse- keep running with corrupted data. Caution: Zig will not warn about these failures at compile time, even if you have used the safe mode.
The usual approach is that while developing your program, you first use Debug mode: you write tests, try everything that needs to be tested, and only afterwards create an executable using the ReleaseFast or ReleaseSmall option.