In zigclc I had a struct Releases in main.zig which had grown to the point where I wanted to factor it out, including its sub types, to a separate file. The following steps document what I did (for Releases, replace that name everywhere with the object of your refactoring), and might help you if you are in the same situation, especially the first time around. There are likely other ways to go about this and steps that can be combined, but this worked for me.
The zigclc project is build with build.zig and zig build. If you use zig build-exe you can still factor out a file and use the first few steps, but you will have to stop as indicated below.
Running zig build --watch --error-style verbose_clear or zig build test --watch --error-style verbose_clear helps continously checking on compilability (mind the underscore in verbose_clear)
-
start with compiling and working code
-
make sure you can roll back any changes: check your code into your VCS and/or use an editor that can revert changes from before saving a file
-
clean up the internal dependencies within
main.zig. If some function or other struct is referenced both fromReleases’ functions as well as from other parts ofmain.zig, you may want to factor those out first, if they are not going to reside in the new file along withReleases. -
decide on the new file name, keeping in mind the recommended file naming conventions:
If the file (implicitly a struct) has top level fields, it should be named like any other struct with fields using
TitleCasesince I am factoring out a struct
Releases, the filename should beReleases.zig -
cut the code for the
Releasesstruct, including any other code (structs,fns, etc) it depends on frommain.zig -
paste the cut code in
Releases.zigand save -
insert
const Releases = @import("Releases.zig").Releases;into yourmain.zig -
save, and if you get errors, because of stuff missing from
Releases.ziglike missingconst std = @import("std");and derivatives such asconst Io = std.Io;add those toReleases.zig -
add
pubto anything inReleases.zigthe compiler complains about: if missing, add it toconst Releases = structitself, and any functions (init(),deinit(), etc.) used frommain.zig -
add other lines like
const SomeStruct = @import("Releases.zig").SomeStruct;, andconst some_fun = @import("Releases.zig").some_fun;, tomain.zig, if appropriate, to get everything to compile again -
when things compile (and test and run) as expected, commit the changes
-
in
Releases.zigat the top of the file addconst Releases = @This();and an empty line following it (so it stands out), remove the lineconst Releases = struct {and the line with the corresponding closing};(leave the lines in between as is even if they are indented.); save the file -
in
main.zigremove the.Releasesfromconst Releases = @import("Releases.zig").Releases;(i.e. make itconst Releases = @import("Releases.zig");). Savemain.zigand everything should compile again. -
If you have additional imports from
Releases.ziginmain.zigyou can change them, e.g. fromconst SomeStruct = @import("Releases.zig").SomeStruct;toconst SomeStruct = Releases.SomeStruct; -
Things should compile (again), so commit.
This is as far as you can go when you use zig build-exe, if you use zig build you can make
Releases.zig into a separately compiled module:
- In
main.zigchangeconst Releases = @import("Releases.zig");toconst Releases = @import("Releases");and save. This will get you ano module named 'Releases'error. - In
build.zigto thefn build()body:
const Releases = b.addModule("Releases", .{
.root_source_file = b.path("src/Releases.zig"),
});
and to .imports in b.createModule(.{ })
.{ .name = "Releases", .module = Releases },
( the name after const and .module have to be the same, but don’t necessarily have to be Releases).
- Save
build.zig, and if you are runningzig build --watchrestart it, as it doesn't do so onbuild.zig` changes. - Everything should compile again, commit.