Zig 0.17.0-dev (Split by item)

This is an example of documentation generated by ZigDoc, an alternative to Zig's built-in Auto Doc feature. See also examples in other modes/formats. The project being documented here (as the example) is the Zig library itself.

make

ConfigHeader.make
pub fn make(
    config_header: *ConfigHeader,
    step_index: Configuration.Step.Index,
    maker: *Maker,
    progress_node: std.Progress.Node,
) Step.ExtendedMakeError!void

File

lib/compiler/Maker/Step/ConfigHeader.zig:23

Code

pub fn make(
    config_header: *ConfigHeader,
    step_index: Configuration.Step.Index,
    maker: *Maker,
    progress_node: std.Progress.Node,
) Step.ExtendedMakeError!void {
    _ = config_header;
    const graph = maker.graph;
    const step = maker.stepByIndex(step_index);
    const io = graph.io;
    const arena = graph.arena; // TODO don't leak into the process arena
    const conf = &maker.scanned_config.configuration;
    const conf_step = step_index.ptr(conf);
    const conf_ch = conf_step.extended.get(conf.extra).config_header;
    const cache_root = graph.local_cache_root;

    const input_size_limit: Io.Limit = if (conf_ch.input_size_limit.value) |x| .limited64(x) else .unlimited;
    const include_guard_override: ?[]const u8 = if (conf_ch.include_guard.value) |s| s.slice(conf) else null;
    const include_path: []const u8 = conf_ch.include_path.slice(conf);
    const template_file = if (conf_ch.template_file.value) |lp|
        try maker.resolveLazyPathIndex(arena, lp, step_index)
    else
        null;
    const value_pairs = conf_ch.values.slice;

    if (conf_ch.template_file.value) |lp| try step.singleUnchangingWatchInput(maker, arena, lp.get(conf));

    var value_map: ValueMap = .empty;
    try value_map.ensureTotalCapacity(arena, value_pairs.len);
    for (value_pairs) |pair| value_map.putAssumeCapacityNoClobber(pair.key.slice(conf), false);

    var man = graph.cache.obtain();
    defer man.deinit();

    // Random bytes to make ConfigHeader unique. Refresh this with new
    // random bytes when ConfigHeader implementation is modified in a
    // non-backwards-compatible way.
    man.hash.add(@as(u32, 0xdef08d23));
    man.hash.add(@as(u32, @bitCast(conf_ch.flags)));
    man.hash.addBytes(include_path);
    man.hash.addOptionalBytes(include_guard_override);

    var aw: Writer.Allocating = .init(arena);
    defer aw.deinit();

    switch (conf_ch.flags.style) {
        .autoconf_undef => {
            const tf = template_file.?;
            const contents = tf.root_dir.handle.readFileAlloc(io, tf.sub_path, arena, input_size_limit) catch |err|
                return step.fail(maker, "unable to read autoconf input file {f}: {t}", .{ tf, err });
            renderAutoConfUndef(maker, step, contents, &aw.writer, value_pairs, &value_map, tf) catch |err| switch (err) {
                error.WriteFailed => return error.OutOfMemory,
                else => |e| return e,
            };
        },
        .autoconf_at => {
            const tf = template_file.?;
            const contents = tf.root_dir.handle.readFileAlloc(io, tf.sub_path, arena, input_size_limit) catch |err|
                return step.fail(maker, "unable to read autoconf input file {f}: {t}", .{ tf, err });
            renderAutoconfAt(maker, step, contents, &aw, value_pairs, &value_map, tf) catch |err| switch (err) {
                error.WriteFailed => return error.OutOfMemory,
                else => |e| return e,
            };
        },
        .cmake => {
            const tf = template_file.?;
            const contents = tf.root_dir.handle.readFileAlloc(io, tf.sub_path, arena, input_size_limit) catch |err|
                return step.fail(maker, "unable to read cmake input file {f}: {t}", .{ tf, err });
            renderCmake(arena, maker, step, contents, &aw.writer, value_pairs, &value_map, tf) catch |err| switch (err) {
                error.WriteFailed => return error.OutOfMemory,
                else => |e| return e,
            };
        },
        .blank => {
            renderBlank(conf, &aw.writer, value_pairs, &value_map, include_path, include_guard_override) catch |err| switch (err) {
                error.WriteFailed => return error.OutOfMemory,
                else => |e| return e,
            };
        },
        .nasm => {
            renderNasm(conf, &aw.writer, value_pairs, &value_map) catch |err| switch (err) {
                error.WriteFailed => return error.OutOfMemory,
                else => |e| return e,
            };
        },
    }

    const output = aw.written();
    man.hash.addBytes(output);

    if (try step.cacheHit(maker, &man, progress_node)) {
        const digest = man.final();
        maker.generatedPath(conf_ch.generated_dir).* = .{
            .root_dir = cache_root,
            .sub_path = try Io.Dir.path.join(arena, &.{ "o", &digest }),
        };
        return;
    }

    const digest = man.final();

    // If output_path has directory parts, deal with them.  Example:
    // output_dir is zig-cache/o/HASH
    // output_path is libavutil/avconfig.h
    // We want to open directory zig-cache/o/HASH/libavutil/
    // but keep output_dir as zig-cache/o/HASH for -I include
    const out_path: Path = .{
        .root_dir = cache_root,
        .sub_path = try Io.Dir.path.join(arena, &.{ "o", &digest, conf_ch.include_path.slice(conf) }),
    };
    const out_path_dirname = out_path.dirname().?;

    out_path_dirname.root_dir.handle.createDirPath(io, out_path_dirname.sub_path) catch |err|
        return step.fail(maker, "unable to make path {f}: {t}", .{ out_path_dirname, err });

    out_path.root_dir.handle.writeFile(io, .{ .sub_path = out_path.sub_path, .data = output }) catch |err|
        return step.fail(maker, "unable to write file {f}: {t}", .{ out_path, err });

    maker.generatedPath(conf_ch.generated_dir).* = .{
        .root_dir = cache_root,
        .sub_path = try Io.Dir.path.join(arena, &.{ "o", &digest }),
    };

    try step.writeManifest(maker, &man);
}