Run arbitary step whenever a module gets imported

So, I wanted to expose a module through b.addModule but there is a specific step needed to be done, like generating a file and copying it to a specific location may be a bootstrap location, for generating a zig file one can follow steps here Build System Tricks but I needed to copy it to a location(let’s not focus on why, let’s say for some c/c++ and zig bridging, some glue code).

const fake_generated_file = b.allocator.create(std.Build.GeneratedFile) catch @panic("OOM");
fake_generated_file.step = arbitary_step; // step1
fake_generated_file.path = "build.zig.zon"; // any file which exists
const step2 = std.Build.LazyPath{ .generated = .{ .file = fake_generated_file } };
module.import_table.put(b.allocator, "__bootstrap__", b.createModule(.{ .root_source_file = step2 })) catch @panic("OOM");

Now whenever that module gets imported to any other package/executable/module that arbitary_step will be ran, it can be anything RemoveDir or Run. I am not sure if this is intended, if it was then shouldn’t it be more obvious? Or may be it shouldn’t be possible. But then again this could lead to something like the xz backdoor where you trust a famous module but one day it does something like this it can be obscured more I believe, but again it’s a useful feature to copy a bootstrapped file src.

There is an issue related to this:

btw. within build logic just declare your build function with a !void return type and you can use try to return the error, that is simpler than catch @panic("OOM") and also allows calling code to handle things, if for example the caller picks a tiny fixed size allocator or something like that.
I think using @panic("OOM") habitually is not a good idea, because it removes so much flexibility for how the code can be used and called.

1 Like