Pass types from build system?

Say I have a library with a tagged union Message, and I have 300 structs with methods which accept Message. I want Message to be a comptime user provided type, but I don’t want to make each struct generic (ie pub const Foo(comptime T: type) type)

This is trivial to do within the library if I were to make each struct generic, or at least under a common namespace

const MessageHandler(comptime T: type) type {
    return struct {
        const MessageType = T;
        
        pub const OtherMessageHandler = @import("other_handler.zig").OtherHandler(T);

        // ...
    }

It is also trivial to swap out the globally defined event within the library depending on some other comptime build option:

const Message = switch (build_option.message_type) {
    .a => @import("a.zig").TaggedUnionA,
    .b => @import("b.zig").TaggedUnionB,
};

What I am wondering - is there a way I can have a user provide a type through the build system to add into the switch?

const Message = switch (build_option.message_type) {
    .a => @import("a.zig").TaggedUnionA,
    .b => @import("b.zig").TaggedUnionB,
    .c => build_option.user_type,
};

An idea is to create a module message that contains the Message and use it like:

const Message = @import("message").Message;

In your build.zig:

const msg_path = b.option([]const u8, "path", "specify the path to a zig file with pub Module") orelse "src/root.zig";
const msg_mod = b.createModule({
    .root_source_file = b.file(msg_path),
});
exe.root_module.addImport("message", msg_mod);
1 Like