Build system: options module api should be modernized

Since I was just stumbling over this again: the build system API to manage comp-time options seems weirdly old-fashioned, did I just not look in the right place, or hasn’t this just not been updated yet?

E.g. currently I need to do:

    // create Zig main module
    const mod_main = b.createModule(.{
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
        .imports = &.{
            .{ .name = "sokol", .module = dep_sokol.module("sokol") },
        },
    });

    // create comptime options module and attach to main module
    const mod_options = b.addOptions();
    mod_options.addOption(bool, "docking", opt_docking);
    mod_main.addOptions("build_options", mod_options);

What I’d rather would like to do:

    const mod_main = b.createModule(.{
        .root_source_file = b.path("src/main.zig"),
        .target = target,
        .optimize = optimize,
        .imports = &.{
            .{ .name = "sokol", .module = dep_sokol.module("sokol") },
            .{ 
                .name = "build_options",
                .module = b.createOptions(&.{
                    .{ .type = bool, .name = "docking", .value = opt_docking },
                    .{ .type = bool, .name = "another_option", .value = false },
                }),
            },
        },
    });

…e.g. a Build.createOptions() should return a *Module and take a slice of options, and removing the special Module.addOptions() functions in favour of providing the options module as a regular import.

Anybody knows if there’s already a ticket for this?

would do the trick?

1 Like

Hmm ok, for getting a Module out of the Options step. But still feels convoluted to create a step first, add each option with a separate function call to the step, and then get a Module out of the step.

I wonder if the Options step is even useful without creating a module from its output. I would probably move all that stuff into a b.createOptionsModule(&.{ ... }) call.

There’s one additional thing you can do with it, which is to get the generated file output as a LazyPath. I haven’t personally seen that used directly, but it’s part of the public interface.

Overall I like that Options works like everything else in the build system: a bit verbose, but explicit. It might be nice to have an opt.addOptions function which took a Zon-like set of key/option pairs, that’s basically sugar but so what. module.addOptions takes the Option struct and does all the writing it out and linking it as a module, so explicitly creating one from it isn’t usually necessary.

I think everything I’ve written which takes options needs them passed to more than one artifact though, at minimum a module and a test. So being able to define it inline the way you illustrate wouldn’t be useful, and I would guess that having more than one artifact take a given Options step is more useful than not.

The current system scales well. You can take a few options and use them within the build system, take test filters and provide them to the .filters argument in b.addTest, and build up a couple possibly-overlapping Options which get farmed out to this or that artifact. So I could see a case for minor consolidation of the most usual uses, but I don’t think what we have has more moving parts than it needs.

3 Likes