Seth Barrett

Daily Blog Post: September 10th, 2023

Zig

September 10th, 2023

Part 9: Modules and Packages in Zig

Welcome to the ninth installment of our "Getting Started with Zig on MacOS" series. In this part, we'll explore how to organize your Zig code into modules and packages. Modules help you structure your code within a project, while packages enable you to create reusable components and import external libraries.

Organizing Code into Modules

Modules in Zig provide a way to organize your code within a project. A module can contain functions, types, and other declarations. You can create modules using the pub mod syntax. Here's an example of organizing code into modules:

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

pub fn add(a: i32, b: i32) i32 {
    return a + b;
}

pub fn subtract(a: i32, b: i32) i32 {
    return a - b;
}

// main.zig
const math = @import("math.zig");

fn main() void {
    const result1 = math.add(10, 5);
    const result2 = math.subtract(10, 5);
    // ...
}

In this example, we create a module named math.zig to organize mathematical functions. We then import and use those functions in the main.zig file.

Creating and Using Packages

Packages in Zig allow you to create reusable components that can be shared across multiple projects. A package is a directory containing Zig source files and a build.zig file that defines the package's build configuration. You can use the @import directive to import functions and types from a package. Here's a simplified example of creating and using a package:

my_package/
    build.zig
    my_module.zig

# build.zig
const Builder = @import("std").build.Builder;
  
pub fn build(b: *Builder) void {
    const target = b.standardTargetOptions(.{});
    const mode = b.standardReleaseOptions();

    const exe = b.addExecutable("my_program", "my_module.zig");
    exe.setTarget(target);
    exe.setBuildMode(mode);
    exe.install();
}

In this example, we create a package named my_package with a build.zig file to configure the build process. The my_module.zig file contains the module we want to make available to other projects.

To use this package in another project, you can import it using @import:

const my_module = @import("my_package/my_module.zig");

fn main() void {
    const result = my_module.someFunction();
    // ...
}

Importing External Libraries

Zig allows you to import external libraries into your project. You can use the @cImport directive to import C libraries and use their functions and types. Here's an example of importing an external C library:

const std = @import("std");
const libc = @cImport({
    @cInclude("stdlib.h");
    @cInclude("stdio.h");
});

pub fn main() void {
    const ptr = libc.malloc(std.sizeOf(c_void));
    libc.free(ptr);
}

In this example, we import the C standard library functions malloc and free and use them in our Zig code.

What's Next?

In this part, you've learned about modules and packages in Zig, as well as how to organize your code, create reusable components, and import external libraries. These concepts are essential for structuring your Zig projects efficiently.

In Part 10, we'll explore testing and debugging techniques in Zig, helping you ensure the reliability and quality of your code. Stay tuned for more Zig insights and practical examples. Happy coding!