Skip to content

Commit 268887a

Browse files
committed
std.Build: Add a finalize function to Build.Steps
It is called after the user has fully configured the steps in the build() function.
1 parent d91d6ed commit 268887a

File tree

3 files changed

+77
-21
lines changed

3 files changed

+77
-21
lines changed

lib/compiler/build_runner.zig

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,10 @@ pub fn main() !void {
335335
try builder.runBuild(root);
336336
}
337337

338+
for (builder.top_level_steps.values()) |s| {
339+
try finalizeSteps(&s.step);
340+
}
341+
338342
if (graph.needed_lazy_dependencies.entries.len != 0) {
339343
var buffer: std.ArrayListUnmanaged(u8) = .{};
340344
for (graph.needed_lazy_dependencies.keys()) |k| {
@@ -635,6 +639,7 @@ fn runStepNames(
635639
test_count += s.test_results.test_count;
636640

637641
switch (s.state) {
642+
.unfinalized => unreachable,
638643
.precheck_unstarted => unreachable,
639644
.precheck_started => unreachable,
640645
.running => unreachable,
@@ -780,6 +785,7 @@ fn printStepStatus(
780785
run: *const Run,
781786
) !void {
782787
switch (s.state) {
788+
.unfinalized => unreachable,
783789
.precheck_unstarted => unreachable,
784790
.precheck_started => unreachable,
785791
.precheck_done => unreachable,
@@ -977,6 +983,34 @@ fn printTreeStep(
977983
}
978984
}
979985

986+
/// Traverse the dependency graph after the user build() call,
987+
/// this allows for checks and postprocessing after the steps are fully configured by the user.
988+
fn finalizeSteps(
989+
s: *Step,
990+
) !void {
991+
switch (s.state) {
992+
.unfinalized => {
993+
try s.finalize();
994+
s.state = .precheck_unstarted;
995+
996+
for (s.dependencies.items) |dep| {
997+
try finalizeSteps(dep);
998+
}
999+
},
1000+
1001+
.precheck_unstarted => {},
1002+
1003+
.precheck_started => unreachable,
1004+
.precheck_done => unreachable,
1005+
.dependency_failure => unreachable,
1006+
.running => unreachable,
1007+
.success => unreachable,
1008+
.failure => unreachable,
1009+
.skipped => unreachable,
1010+
.skipped_oom => unreachable,
1011+
}
1012+
}
1013+
9801014
/// Traverse the dependency graph depth-first and make it undirected by having
9811015
/// steps know their dependants (they only know dependencies at start).
9821016
/// Along the way, check that there is no dependency loop, and record the steps
@@ -995,6 +1029,7 @@ fn constructGraphAndCheckForDependencyLoop(
9951029
rand: std.Random,
9961030
) !void {
9971031
switch (s.state) {
1032+
.unfinalized => unreachable,
9981033
.precheck_started => {
9991034
std.debug.print("dependency loop detected:\n {s}\n", .{s.name});
10001035
return error.DependencyLoopDetected;
@@ -1057,6 +1092,7 @@ fn workerMakeOneStep(
10571092
// dependency is not finished yet.
10581093
return;
10591094
},
1095+
.unfinalized => unreachable,
10601096
.precheck_unstarted => unreachable,
10611097
.precheck_started => unreachable,
10621098
}

lib/std/Build/Step.zig

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
id: Id,
22
name: []const u8,
33
owner: *Build,
4+
finalizeFn: FinalizeFn,
45
makeFn: MakeFn,
56

67
dependencies: std.ArrayList(*Step),
@@ -68,6 +69,8 @@ pub const TestResults = struct {
6869
}
6970
};
7071

72+
pub const FinalizeFn = *const fn (step: *Step) anyerror!void;
73+
7174
pub const MakeOptions = struct {
7275
progress_node: std.Progress.Node,
7376
thread_pool: *std.Thread.Pool,
@@ -77,6 +80,7 @@ pub const MakeOptions = struct {
7780
pub const MakeFn = *const fn (step: *Step, options: MakeOptions) anyerror!void;
7881

7982
pub const State = enum {
83+
unfinalized,
8084
precheck_unstarted,
8185
precheck_started,
8286
/// This is also used to indicate "dirty" steps that have been modified
@@ -183,6 +187,7 @@ pub const StepOptions = struct {
183187
id: Id,
184188
name: []const u8,
185189
owner: *Build,
190+
finalizeFn: FinalizeFn = finalizeNoOp,
186191
makeFn: MakeFn = makeNoOp,
187192
first_ret_addr: ?usize = null,
188193
max_rss: usize = 0,
@@ -195,11 +200,12 @@ pub fn init(options: StepOptions) Step {
195200
.id = options.id,
196201
.name = arena.dupe(u8, options.name) catch @panic("OOM"),
197202
.owner = options.owner,
203+
.finalizeFn = options.finalizeFn,
198204
.makeFn = options.makeFn,
199205
.dependencies = std.ArrayList(*Step).init(arena),
200206
.dependants = .{},
201207
.inputs = Inputs.init,
202-
.state = .precheck_unstarted,
208+
.state = .unfinalized,
203209
.max_rss = options.max_rss,
204210
.debug_stack_trace = blk: {
205211
const addresses = arena.alloc(usize, options.owner.debug_stack_frames_count) catch @panic("OOM");
@@ -222,6 +228,11 @@ pub fn init(options: StepOptions) Step {
222228
};
223229
}
224230

231+
pub fn finalize(s: *Step) !void {
232+
assert(s.state == .unfinalized);
233+
try s.finalizeFn(s);
234+
}
235+
225236
/// If the Step's `make` function reports `error.MakeFailed`, it indicates they
226237
/// have already reported the error. Otherwise, we add a simple error report
227238
/// here.
@@ -266,6 +277,10 @@ pub fn getStackTrace(s: *Step) ?std.builtin.StackTrace {
266277
};
267278
}
268279

280+
fn finalizeNoOp(step: *Step) anyerror!void {
281+
_ = step;
282+
}
283+
269284
fn makeNoOp(step: *Step, options: MakeOptions) anyerror!void {
270285
_ = options;
271286

lib/std/Build/Step/Compile.zig

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -207,9 +207,9 @@ generated_h: ?*GeneratedFile,
207207
/// Defaults to `std.math.maxInt(u16)`
208208
error_limit: ?u32 = null,
209209

210-
/// Computed during make().
210+
/// Computed during finalize().
211211
is_linking_libc: bool = false,
212-
/// Computed during make().
212+
/// Computed during finalize().
213213
is_linking_libcpp: bool = false,
214214

215215
no_builtin: bool = false,
@@ -393,6 +393,7 @@ pub fn create(owner: *std.Build, options: Options) *Compile {
393393
.id = base_id,
394394
.name = step_name,
395395
.owner = owner,
396+
.finalizeFn = finalize,
396397
.makeFn = make,
397398
.max_rss = options.max_rss,
398399
}),
@@ -1095,24 +1096,6 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
10951096
// emitted if there is nothing to link.
10961097
var total_linker_objects: usize = @intFromBool(compile.root_module.root_source_file != null);
10971098

1098-
{
1099-
// Fully recursive iteration including dynamic libraries to detect
1100-
// libc and libc++ linkage.
1101-
var dep_it = compile.root_module.iterateDependencies(compile, true);
1102-
while (dep_it.next()) |key| {
1103-
if (key.module.link_libc == true) compile.is_linking_libc = true;
1104-
if (key.module.link_libcpp == true) compile.is_linking_libcpp = true;
1105-
}
1106-
}
1107-
1108-
if (compile.kind == .pch) {
1109-
// precompiled headers must have a single input header file.
1110-
var it = compile.root_module.iterateDependencies(compile, false);
1111-
const link_objects = it.next().?.module.link_objects;
1112-
assert(link_objects.items.len == 1 and link_objects.items[0] == .c_source_file);
1113-
assert(it.next() == null);
1114-
}
1115-
11161099
var cli_named_modules = try CliNamedModules.init(arena, &compile.root_module);
11171100

11181101
// For this loop, don't chase dynamic libraries because their link
@@ -1839,6 +1822,28 @@ fn getZigArgs(compile: *Compile, fuzz: bool) ![][]const u8 {
18391822
return try zig_args.toOwnedSlice();
18401823
}
18411824

1825+
fn finalize(step: *Step) !void {
1826+
const compile: *Compile = @fieldParentPtr("step", step);
1827+
1828+
{
1829+
// Fully recursive iteration including dynamic libraries to detect
1830+
// libc and libc++ linkage.
1831+
var dep_it = compile.root_module.iterateDependencies(compile, true);
1832+
while (dep_it.next()) |key| {
1833+
if (key.module.link_libc == true) compile.is_linking_libc = true;
1834+
if (key.module.link_libcpp == true) compile.is_linking_libcpp = true;
1835+
}
1836+
}
1837+
1838+
if (compile.kind == .pch) {
1839+
// precompiled headers must have a single input header file.
1840+
var it = compile.root_module.iterateDependencies(compile, false);
1841+
const link_objects = it.next().?.module.link_objects;
1842+
assert(link_objects.items.len == 1 and link_objects.items[0] == .c_source_file);
1843+
assert(it.next() == null);
1844+
}
1845+
}
1846+
18421847
fn make(step: *Step, options: Step.MakeOptions) !void {
18431848
const b = step.owner;
18441849
const compile: *Compile = @fieldParentPtr("step", step);

0 commit comments

Comments
 (0)