"run always" step in build.zig?

In build.zig, how can I define a step that should always run? Specifically, in a library I want to build (if not cached) and run an executable (code gen) every time the library is installed or any other step is called.

I hope this makes sense at all - I feel a bit lost right now, not sure if it’s the right direction to look at in the first place (wrong paradigm ?!).

You create your prepare step, and then add your dependencies. For example: run_exe and install depend on prepare.

const prepare = b.addSystemCommand(&.{

1 Like

Thanks a lot @dimdin, saved my evening ^^

follow-up question :wink:

while this works for the library itself (i.e. if I run zig build within its directory), it does not seem to be called if the library is used in another package (an executable that’s using the library). Any advice on that?

To make this more concrete, the library’s build.zig creates a zig file x.zig in a code-gen step, which is then used by the library (its content more precisely). Now if I use the library in another package via the zon file, I get the error that the file (which should have been generated) does not exists; something like

‘/home/user/.cache/zig/p/12203042f80f7ed28c195e927c02503440d93879951a4ce26c79a9c57ab20f9714ea/lib/x.zig’: FileNotFound

Could you share your build.zig files for both projects?


Note that unless you need the actual generated Zig files in your source directory, you can generate them and add them to the modules that need them directly without having to write them out with a addWriteFiles. So for example in your library build.zig:

const out_file_p = run_gen_prefix.addOutputFileArg("_tzdb_prefix.zig");
zdt_module.addAnonymousImport("tzdb_prefix", .{
    .root_source_file = out_file_p,

Then in the modules where you added the anonymous import

const tzdb_prefix = @import("tzdb_prefix");

Aside from @import it works for @embedFile too. This also establishes a dependency between the modules where you add the anonymous import and the generated output file, so you don’t have to use dependOn explicitly for these cases.


ah, that seems more like what I’m looking for, thanks a lot!

Now that I get this right, using the anonymous import (without copying the output to the lib) only makes sense if the file is generated on install? I.e. generated files from steps that have to be called explicitly (such as the database update in my case), wouldn’t work since the import wouldn’t actually be there if I use the library as a dependency?

Bear in mind these build system details are fairly new (and still morphing) so I may be wrong here; but if the module you’re providing in your library (i.e. zdt) has an anonymous import of an output file being generated in another step, when that provided module needs to build, the generated output file must be there, be it a cached version if nothing has changed or the generation runs again, no matter what.

1 Like

Right, documentation feels kind of sparse on the build system, and 0.11 stable and 0.12.0-dev seem to have diverged significantly in that matter (the details at least). I chose to stay on track with the dev version, but docs/articles/blog-posts often times refer to the stable version. So not sure if that was the right decision…

For my specific case, I have another build step which should not be triggered during installation of the lib, and the anonymous import doesn’t seem to work there. But that doesn’t matter here, works fine as-is, just tried it out of curiosity.

1 Like

My advice when trying to grok build step graphs and how individual steps are affected by caching is to run zig build with --summary all, which will print out a graph of steps with statuses like “success”, “cached”, “skipped”, etc. This is especially helpful if you use a lot of generated LazyPaths.

I also encourage you to briefly look at how the make functions of common steps like Step.Run and the various install steps are implemented, it might help explain how those steps determine whether a step should be cached or not.