DoxigAlpha

option

Creates a configuration option to be passed to the build.zig script. When a user directly runs zig build, they can set these options with -D arguments. When a project depends on a Zig package as a dependency, it programmatically sets these options when calling the dependency's build.zig script as a function. null is returned when an option is left to default.

Function parameters

Parameters

#
b:*Build
T:type
name_raw:[]const u8
description_raw:[]const u8

Type definitions in this namespace

Types

#
Graph
Shared state among all Build instances.
GeneratedFile
A file that is generated by a build step.
LazyPath
A reference to an existing or future path.
ResolvedTarget
A pair of target query and fully resolved target.

Functions in this namespace

Functions

#
resolveInstallPrefix
This function is intended to be called by lib/build_runner.zig, not a build.zig file.
addOptions
Create a set of key-value pairs that can be converted into a Zig source
addTest
Creates an executable containing unit tests.
addModule
This function creates a module and adds it to the package's module set, making
createModule
This function creates a private module, to be used by the current package,
addSystemCommand
Initializes a `Step.Run` with argv, which must at least have the path to the
addRunArtifact
Creates a `Step.Run` with an executable built with `addExecutable`.
addConfigHeader
Using the `values` provided, produces a C header file, possibly based on a
dupe
Allocator.dupe without the need to handle out of memory.
dupeStrings
Duplicates an array of strings without the need to handle out of memory.
dupePath
Duplicates a path and converts all slashes to the OS's canonical path separator.
option
Creates a configuration option to be passed to the build.zig script.
standardTargetOptions
Exposes standard `zig build` options for choosing a target and additionally
parseTargetQuery
Obtain a target query from a string, reporting diagnostics to stderr if the
standardTargetOptionsQueryOnly
Exposes standard `zig build` options for choosing a target.
installArtifact
This creates the install step and adds it to the dependencies of the
addInstallArtifact
This merely creates the step; it does not add it to the dependencies of the
installFile
`dest_rel_path` is relative to prefix path
installBinFile
`dest_rel_path` is relative to bin path
installLibFile
`dest_rel_path` is relative to lib path
addInstallFile
`dest_rel_path` is relative to install prefix path
addInstallBinFile
`dest_rel_path` is relative to bin path
addInstallLibFile
`dest_rel_path` is relative to lib path
addInstallHeaderFile
`dest_rel_path` is relative to header path
path
References a file or directory relative to the source root.
pathFromRoot
This is low-level implementation details of the build system, not meant to
run
This is a helper function to be called from build.zig scripts, *not* from
lazyDependency
When this function is called, it means that the current build does, in
lazyImport
In a build.zig file, this function is to `@import` what `lazyDependency` is to `dependency`.
dumpBadGetPathHelp
In this function the stderr mutex has already been locked.
makeTempPath
This function is intended to be called in the `configure` phase only.
resolveTargetQuery
Converts a target query into a fully resolved target that can be passed to

Error sets in this namespace

Error Sets

#

Source

Implementation

#
pub fn option(b: *Build, comptime T: type, name_raw: []const u8, description_raw: []const u8) ?T {
    const name = b.dupe(name_raw);
    const description = b.dupe(description_raw);
    const type_id = comptime typeToEnum(T);
    const enum_options = if (type_id == .@"enum" or type_id == .enum_list) blk: {
        const EnumType = if (type_id == .enum_list) @typeInfo(T).pointer.child else T;
        const fields = comptime std.meta.fields(EnumType);
        var options = std.array_list.Managed([]const u8).initCapacity(b.allocator, fields.len) catch @panic("OOM");

        inline for (fields) |field| {
            options.appendAssumeCapacity(field.name);
        }

        break :blk options.toOwnedSlice() catch @panic("OOM");
    } else null;
    const available_option = AvailableOption{
        .name = name,
        .type_id = type_id,
        .description = description,
        .enum_options = enum_options,
    };
    if ((b.available_options_map.fetchPut(name, available_option) catch @panic("OOM")) != null) {
        panic("Option '{s}' declared twice", .{name});
    }
    b.available_options_list.append(available_option) catch @panic("OOM");

    const option_ptr = b.user_input_options.getPtr(name) orelse return null;
    option_ptr.used = true;
    switch (type_id) {
        .bool => switch (option_ptr.value) {
            .flag => return true,
            .scalar => |s| {
                if (mem.eql(u8, s, "true")) {
                    return true;
                } else if (mem.eql(u8, s, "false")) {
                    return false;
                } else {
                    log.err("Expected -D{s} to be a boolean, but received '{s}'", .{ name, s });
                    b.markInvalidUserInput();
                    return null;
                }
            },
            .list, .map, .lazy_path, .lazy_path_list => {
                log.err("Expected -D{s} to be a boolean, but received a {s}.", .{
                    name, @tagName(option_ptr.value),
                });
                b.markInvalidUserInput();
                return null;
            },
        },
        .int => switch (option_ptr.value) {
            .flag, .list, .map, .lazy_path, .lazy_path_list => {
                log.err("Expected -D{s} to be an integer, but received a {s}.", .{
                    name, @tagName(option_ptr.value),
                });
                b.markInvalidUserInput();
                return null;
            },
            .scalar => |s| {
                const n = std.fmt.parseInt(T, s, 10) catch |err| switch (err) {
                    error.Overflow => {
                        log.err("-D{s} value {s} cannot fit into type {s}.", .{ name, s, @typeName(T) });
                        b.markInvalidUserInput();
                        return null;
                    },
                    else => {
                        log.err("Expected -D{s} to be an integer of type {s}.", .{ name, @typeName(T) });
                        b.markInvalidUserInput();
                        return null;
                    },
                };
                return n;
            },
        },
        .float => switch (option_ptr.value) {
            .flag, .map, .list, .lazy_path, .lazy_path_list => {
                log.err("Expected -D{s} to be a float, but received a {s}.", .{
                    name, @tagName(option_ptr.value),
                });
                b.markInvalidUserInput();
                return null;
            },
            .scalar => |s| {
                const n = std.fmt.parseFloat(T, s) catch {
                    log.err("Expected -D{s} to be a float of type {s}.", .{ name, @typeName(T) });
                    b.markInvalidUserInput();
                    return null;
                };
                return n;
            },
        },
        .@"enum" => switch (option_ptr.value) {
            .flag, .map, .list, .lazy_path, .lazy_path_list => {
                log.err("Expected -D{s} to be an enum, but received a {s}.", .{
                    name, @tagName(option_ptr.value),
                });
                b.markInvalidUserInput();
                return null;
            },
            .scalar => |s| {
                if (std.meta.stringToEnum(T, s)) |enum_lit| {
                    return enum_lit;
                } else {
                    log.err("Expected -D{s} to be of type {s}.", .{ name, @typeName(T) });
                    b.markInvalidUserInput();
                    return null;
                }
            },
        },
        .string => switch (option_ptr.value) {
            .flag, .list, .map, .lazy_path, .lazy_path_list => {
                log.err("Expected -D{s} to be a string, but received a {s}.", .{
                    name, @tagName(option_ptr.value),
                });
                b.markInvalidUserInput();
                return null;
            },
            .scalar => |s| return s,
        },
        .build_id => switch (option_ptr.value) {
            .flag, .map, .list, .lazy_path, .lazy_path_list => {
                log.err("Expected -D{s} to be an enum, but received a {s}.", .{
                    name, @tagName(option_ptr.value),
                });
                b.markInvalidUserInput();
                return null;
            },
            .scalar => |s| {
                if (std.zig.BuildId.parse(s)) |build_id| {
                    return build_id;
                } else |err| {
                    log.err("unable to parse option '-D{s}': {s}", .{ name, @errorName(err) });
                    b.markInvalidUserInput();
                    return null;
                }
            },
        },
        .list => switch (option_ptr.value) {
            .flag, .map, .lazy_path, .lazy_path_list => {
                log.err("Expected -D{s} to be a list, but received a {s}.", .{
                    name, @tagName(option_ptr.value),
                });
                b.markInvalidUserInput();
                return null;
            },
            .scalar => |s| {
                return b.allocator.dupe([]const u8, &[_][]const u8{s}) catch @panic("OOM");
            },
            .list => |lst| return lst.items,
        },
        .enum_list => switch (option_ptr.value) {
            .flag, .map, .lazy_path, .lazy_path_list => {
                log.err("Expected -D{s} to be a list, but received a {s}.", .{
                    name, @tagName(option_ptr.value),
                });
                b.markInvalidUserInput();
                return null;
            },
            .scalar => |s| {
                const Child = @typeInfo(T).pointer.child;
                const value = std.meta.stringToEnum(Child, s) orelse {
                    log.err("Expected -D{s} to be of type {s}.", .{ name, @typeName(Child) });
                    b.markInvalidUserInput();
                    return null;
                };
                return b.allocator.dupe(Child, &[_]Child{value}) catch @panic("OOM");
            },
            .list => |lst| {
                const Child = @typeInfo(T).pointer.child;
                const new_list = b.allocator.alloc(Child, lst.items.len) catch @panic("OOM");
                for (new_list, lst.items) |*new_item, str| {
                    new_item.* = std.meta.stringToEnum(Child, str) orelse {
                        log.err("Expected -D{s} to be of type {s}.", .{ name, @typeName(Child) });
                        b.markInvalidUserInput();
                        b.allocator.free(new_list);
                        return null;
                    };
                }
                return new_list;
            },
        },
        .lazy_path => switch (option_ptr.value) {
            .scalar => |s| return .{ .cwd_relative = s },
            .lazy_path => |lp| return lp,
            .flag, .map, .list, .lazy_path_list => {
                log.err("Expected -D{s} to be a path, but received a {s}.", .{
                    name, @tagName(option_ptr.value),
                });
                b.markInvalidUserInput();
                return null;
            },
        },
        .lazy_path_list => switch (option_ptr.value) {
            .scalar => |s| return b.allocator.dupe(LazyPath, &[_]LazyPath{.{ .cwd_relative = s }}) catch @panic("OOM"),
            .lazy_path => |lp| return b.allocator.dupe(LazyPath, &[_]LazyPath{lp}) catch @panic("OOM"),
            .list => |lst| {
                const new_list = b.allocator.alloc(LazyPath, lst.items.len) catch @panic("OOM");
                for (new_list, lst.items) |*new_item, str| {
                    new_item.* = .{ .cwd_relative = str };
                }
                return new_list;
            },
            .lazy_path_list => |lp_list| return lp_list.items,
            .flag, .map => {
                log.err("Expected -D{s} to be a path, but received a {s}.", .{
                    name, @tagName(option_ptr.value),
                });
                b.markInvalidUserInput();
                return null;
            },
        },
    }
}