Understanding `zig build-exe`
In the previous section, we used this command:
Understanding zig build-exe
In the previous section, we used this command:
zig run hello.zig
That command compiles your Zig file and runs it immediately.
Now we will look at a different command:
zig build-exe hello.zig
This command compiles your Zig file and creates an executable file.
An executable file is a program you can run directly from your operating system.
Source File and Executable File
Start with this file:
hello.zig
Inside it, write:
const std = @import("std");
pub fn main() void {
std.debug.print("Hello, executable!\n", .{});
}
Now run:
zig build-exe hello.zig
Zig reads hello.zig, checks the code, compiles it, links it, and creates an executable.
On Linux and macOS, the result is usually:
hello
You run it with:
./hello
On Windows, the result is usually:
hello.exe
You run it with:
.\hello.exe
The source file is the text you write.
The executable file is the program Zig creates.
What build-exe Means
The command has two parts:
zig build-exe hello.zig
The first part is:
zig
This runs the Zig tool.
The second part is:
build-exe
This tells Zig what kind of output you want.
The third part is:
hello.zig
This is the input file.
So the command means:
Use Zig to build an executable from hello.zig.
Compile and Link
When you run zig build-exe, Zig does more than one thing.
First, it compiles your Zig code. Compilation checks the source code and turns it into lower-level machine instructions.
Second, it links the program. Linking connects your code with the pieces it needs from libraries and the operating system.
For a small program, this feels like one step. Internally, it has several stages.
You do not need to understand every stage yet. For now, remember this:
Source code goes in.
Executable program comes out.
zig run vs zig build-exe
Both commands compile code, but they are used for different situations.
| Command | What it does | When to use it |
|---|---|---|
zig run hello.zig |
Compile and run immediately | Quick experiments |
zig build-exe hello.zig |
Compile and save executable | Creating a program file |
When learning, zig run is convenient.
When you want a real output file, use zig build-exe.
Running the Executable
After building, you run the executable directly.
On Linux and macOS:
./hello
The ./ means “run the file named hello in the current directory.”
This is needed because most Unix-like shells do not automatically search the current directory for programs.
On Windows PowerShell:
.\hello.exe
The .\ means the same idea: run the file in the current directory.
Choosing an Output Name
By default, Zig uses the source file name.
If the input is:
hello.zig
the output is usually:
hello
or:
hello.exe
You can choose a different output name with -femit-bin.
zig build-exe hello.zig -femit-bin=myprogram
Now the output is named:
myprogram
On Windows, you may choose:
zig build-exe hello.zig -femit-bin=myprogram.exe
This is useful when the file name and program name should be different.
Build Modes
Zig can build the same program in different modes.
A build mode controls safety checks, optimization, and debugging information.
The most common modes are:
| Mode | Purpose |
|---|---|
Debug |
Best for development and learning |
ReleaseSafe |
Optimized, but keeps many safety checks |
ReleaseFast |
Optimized for speed |
ReleaseSmall |
Optimized for small binary size |
By default, Zig builds in debug mode.
Debug mode is best while learning because it keeps helpful checks and better debugging information.
To build in release-fast mode:
zig build-exe hello.zig -O ReleaseFast
To build in release-safe mode:
zig build-exe hello.zig -O ReleaseSafe
To build in release-small mode:
zig build-exe hello.zig -O ReleaseSmall
For now, use the default mode unless you have a reason to change it.
What Debug Mode Gives You
Debug mode is slower than release mode, but it is better for learning.
It helps catch mistakes such as:
| Mistake | Example |
|---|---|
| Integer overflow | A number becomes too large for its type |
| Invalid array access | Code reads outside an array |
| Reaching impossible code | Code reaches unreachable |
| Better stack traces | Error messages are easier to inspect |
Speed matters later. Correctness matters first.
Use debug builds while writing and testing code.
A Simple Error Example
Try this program:
const std = @import("std");
pub fn main() void {
const items = [_]u8{ 1, 2, 3 };
std.debug.print("{}\n", .{items[10]});
}
Build and run it:
zig build-exe hello.zig
./hello
The array has only three elements, but the program tries to access index 10.
In debug mode, Zig can catch this kind of error instead of silently continuing with invalid memory.
This is one reason debug builds are useful.
Cross Compilation Preview
One powerful feature of zig build-exe is cross compilation.
Cross compilation means building a program for a different platform.
For example, on one machine you can ask Zig to build for Linux:
zig build-exe hello.zig -target x86_64-linux
Or for Windows:
zig build-exe hello.zig -target x86_64-windows
Or for macOS on Apple Silicon:
zig build-exe hello.zig -target aarch64-macos
You do not need to master this now. The important idea is that Zig treats cross compilation as a normal compiler feature, not an advanced trick.
Common Beginner Problems
If you run:
zig build-exe hello.zig
and see an error like:
error: file not found
make sure your terminal is in the same directory as hello.zig.
You can list files in the current directory.
On macOS and Linux:
ls
On Windows PowerShell:
dir
If you build successfully but cannot run the program, check the file name.
On Linux and macOS, use:
./hello
On Windows, use:
.\hello.exe
If you type only:
hello
on Linux or macOS, the shell may not find it. Use ./hello.
Mental Model
zig build-exe is the direct way to turn one Zig source file into one executable program.
You give Zig a .zig file.
Zig gives you a program file.
That is the basic build path:
hello.zig -> compiler -> hello
Later, when projects become larger, we will use zig build and a build.zig file. But zig build-exe is the simplest place to start because it shows the core idea without extra project structure.