Skip to content

Custom build file

Chung Leong edited this page Apr 4, 2024 · 3 revisions

Zigar uses a special build.zig when compiling your Zig files. There are occasions when you might to customize the build settings. For instance, when you're employing third-party packages.

Copy and paste the following code into a build.zig in the same directory as your Zig module (potentially alongside a build.zig.zon) and make the necessary changes:

const std = @import("std");
const cfg = @import("./build-cfg.zig");

pub fn build(b: *std.Build) void {
    const target = b.standardTargetOptions(.{});
    const optimize = b.standardOptimizeOption(.{});
    const lib = b.addSharedLibrary(.{
        .name = cfg.module_name,
        .root_source_file = .{ .path = cfg.stub_path },
        .target = target,
        .optimize = optimize,
    });
    const imports = .{};
    if (@hasDecl(std.Build.Step.Compile, "addModule")) {
        // Zig 0.11.0
        lib.addModule("exporter", b.createModule(.{
            .source_file = .{ .path = cfg.exporter_path },
        }));
        lib.addModule("module", b.createModule(.{
            .source_file = .{ .path = cfg.module_path },
            .dependencies = &imports,
        }));
    } else if (@hasField(std.Build.Step.Compile, "root_module")) {
        // Zig 0.12.0
        lib.root_module.addImport("exporter", b.createModule(.{
            .root_source_file = .{ .path = cfg.exporter_path },
        }));
        lib.root_module.addImport("module", b.createModule(.{
            .root_source_file = .{ .path = cfg.module_path },
            .imports = &imports,
        }));
        if (cfg.is_wasm) {
            // WASM needs to be compiled as exe
            lib.kind = .exe;
            lib.linkage = .static;
            lib.entry = .disabled;
        }
    }
    if (cfg.is_wasm) {
        lib.rdynamic = true;
        lib.wasi_exec_model = .reactor;
    }
    if (cfg.use_libc) {
        lib.linkLibC();
    }
    const wf = b.addWriteFiles();
    wf.addCopyFileToSource(lib.getEmittedBin(), cfg.output_path);
    wf.step.dependOn(&lib.step);
    b.getInstallStep().dependOn(&wf.step);
}

Adding a package

Place dependent packages in the imports tuple. Example:

    const ziglyph = b.dependency("ziglyph", .{
        .target = target,
        .optimize = optimize,
    });
    const imports = .{
        .{ .name = "ziglyph", .module = ziglyph.module("ziglyph") },
    };

Adding a C source file

Call addIncludePath to add directories holding expected header files. Call addCSourceFile to add the source file itself.

    lib.addIncludePath(.{ .path = "./libx/include" });
    lib.addCSourceFile(.{ .file = .{ .path = "./libx/src/main.c" }, .flags = &.{} });

Fields in build-cfg.zig

output_path

The full path to the .so, .dylib, or .dll. file being generated.

module_name

The name of the module, i.e. the name of the Zig file without the extension.

module_path

The full path to the Zig file specified in the import statement (directly or indirectly through sourceFiles).

module_dir

The full path to the parent directory of module_path.

exporter_path

The full path to the Zigar exporter.

stub_path

The full path to the Zigar module entry point.

use_libc

Whether the C standard library should be linked in. Corresponds to the useLibc configuration option. Relevant only for compilation to WASM. Always true for node-zigar.

is_wasm

Whether the target archecture is WebAssembly.