DEV Community

Alex Spinov
Alex Spinov

Posted on

Zig Has a Free API: The C Replacement That Cross-Compiles to 40+ Targets

Zig is a systems programming language designed as a better C. It cross-compiles to 40+ targets out of the box, has no hidden control flow, no hidden allocations, and can directly import C headers.

Why Zig?

  • Cross-compilation — target any OS/arch from any OS, built-in
  • C interop — import C headers directly, no bindings
  • No hidden allocations — you control every allocation
  • Comptime — compile-time code execution (replaces macros/generics)
  • Drop-in C compilerzig cc replaces gcc/clang with cross-compile

Install

# macOS
brew install zig

# Linux
snap install zig --classic

# Or download from ziglang.org
curl -L https://ziglang.org/download/0.13.0/zig-linux-x86_64-0.13.0.tar.xz | tar xJ
Enter fullscreen mode Exit fullscreen mode

Hello World

// hello.zig
const std = @import("std");

pub fn main() void {
    std.debug.print("Hello, {s}!\n", .{"World"});
}
Enter fullscreen mode Exit fullscreen mode
zig build-exe hello.zig
./hello

# Cross compile to Linux ARM (from macOS!)
zig build-exe hello.zig -target aarch64-linux

# Cross compile to Windows
zig build-exe hello.zig -target x86_64-windows
Enter fullscreen mode Exit fullscreen mode

HTTP Server (std.http)

const std = @import("std");
const net = std.net;
const http = std.http;

pub fn main() !void {
    var server = http.Server.init(.{ .reuse_address = true });
    defer server.deinit();

    const address = net.Address.parseIp("0.0.0.0", 8080) catch unreachable;
    try server.listen(address);

    std.debug.print("Listening on :8080\n", .{});

    while (true) {
        var response = try server.accept();
        defer response.deinit();

        try response.headers.append("Content-Type", "application/json");
        try response.do();

        const body = \\
            \\{"status": "ok", "message": "Hello from Zig!"}
        ;
        _ = try response.write(body);
        try response.finish();
    }
}
Enter fullscreen mode Exit fullscreen mode

Comptime (Compile-Time Execution)

// Generic data structure — computed at compile time
fn ArrayList(comptime T: type) type {
    return struct {
        items: []T,
        capacity: usize,
        allocator: std.mem.Allocator,

        pub fn init(allocator: std.mem.Allocator) @This() {
            return .{
                .items = &.{},
                .capacity = 0,
                .allocator = allocator,
            };
        }

        pub fn append(self: *@This(), item: T) !void {
            // ... implementation
        }
    };
}

// Compile-time string formatting
fn endpoint(comptime path: []const u8) []const u8 {
    return "/api/v1" ++ path;
}

// Used at compile time — zero runtime cost
const users_path = endpoint("/users"); // "/api/v1/users"
Enter fullscreen mode Exit fullscreen mode

C Interop (Zero-Cost)

// Import C headers directly!
const c = @cImport({
    @cInclude("sqlite3.h");
});

pub fn main() !void {
    var db: ?*c.sqlite3 = null;
    const rc = c.sqlite3_open(":memory:", &db);
    if (rc != c.SQLITE_OK) {
        std.debug.print("Error: {s}\n", .{c.sqlite3_errmsg(db)});
        return;
    }
    defer _ = c.sqlite3_close(db);

    std.debug.print("SQLite version: {s}\n", .{c.sqlite3_version});
}
Enter fullscreen mode Exit fullscreen mode
# Build with C library linking
zig build-exe main.zig -lsqlite3 -lc

# Use zig as a C compiler (with cross-compile!)
zig cc -o hello hello.c -target aarch64-linux
Enter fullscreen mode Exit fullscreen mode

Key Features

Feature Details
Targets 40+ (x86, ARM, MIPS, WASM, etc.)
Safety Optional runtime safety checks
C interop Direct @cImport, no bindings
Allocators Explicit, pluggable
Build system Built-in (build.zig)
Package manager Built-in

Resources


Building systems software? I create custom tools and data solutions. Check my Apify actors or email spinov001@gmail.com.

Top comments (0)