Commit c6a895f667

Andrew Kelley <andrew@ziglang.org>
2023-02-13 21:10:20
extract some logic from std.Build to build_runner.zig
1 parent a2c6ecd
Changed files (2)
lib/std/Build.zig
@@ -67,7 +67,7 @@ invalid_user_input: bool,
 zig_exe: []const u8,
 default_step: *Step,
 env_map: *EnvMap,
-top_level_steps: ArrayList(*TopLevelStep),
+top_level_steps: std.StringArrayHashMapUnmanaged(*TopLevelStep),
 install_prefix: []const u8,
 dest_dir: ?[]const u8,
 lib_dir: []const u8,
@@ -217,7 +217,7 @@ pub fn create(
         .user_input_options = UserInputOptionsMap.init(allocator),
         .available_options_map = AvailableOptionsMap.init(allocator),
         .available_options_list = ArrayList(AvailableOption).init(allocator),
-        .top_level_steps = ArrayList(*TopLevelStep).init(allocator),
+        .top_level_steps = .{},
         .default_step = undefined,
         .env_map = env_map,
         .search_prefixes = ArrayList([]const u8).init(allocator),
@@ -241,8 +241,8 @@ pub fn create(
         .host = host,
         .modules = std.StringArrayHashMap(*Module).init(allocator),
     };
-    try self.top_level_steps.append(&self.install_tls);
-    try self.top_level_steps.append(&self.uninstall_tls);
+    try self.top_level_steps.put(allocator, self.install_tls.step.name, &self.install_tls);
+    try self.top_level_steps.put(allocator, self.uninstall_tls.step.name, &self.uninstall_tls);
     self.default_step = &self.install_tls.step;
     return self;
 }
@@ -288,7 +288,7 @@ fn createChildOnly(parent: *Build, dep_name: []const u8, build_root: Cache.Direc
         .zig_exe = parent.zig_exe,
         .default_step = undefined,
         .env_map = parent.env_map,
-        .top_level_steps = ArrayList(*TopLevelStep).init(allocator),
+        .top_level_steps = .{},
         .install_prefix = undefined,
         .dest_dir = parent.dest_dir,
         .lib_dir = parent.lib_dir,
@@ -316,8 +316,8 @@ fn createChildOnly(parent: *Build, dep_name: []const u8, build_root: Cache.Direc
         .dep_prefix = parent.fmt("{s}{s}.", .{ parent.dep_prefix, dep_name }),
         .modules = std.StringArrayHashMap(*Module).init(allocator),
     };
-    try child.top_level_steps.append(&child.install_tls);
-    try child.top_level_steps.append(&child.uninstall_tls);
+    try child.top_level_steps.put(allocator, child.install_tls.step.name, &child.install_tls);
+    try child.top_level_steps.put(allocator, child.uninstall_tls.step.name, &child.uninstall_tls);
     child.default_step = &child.install_tls.step;
     return child;
 }
@@ -389,10 +389,10 @@ fn applyArgs(b: *Build, args: anytype) !void {
     b.resolveInstallPrefix(install_prefix, .{});
 }
 
-pub fn destroy(self: *Build) void {
-    self.env_map.deinit();
-    self.top_level_steps.deinit();
-    self.allocator.destroy(self);
+pub fn destroy(b: *Build) void {
+    b.env_map.deinit();
+    b.top_level_steps.deinit(b.allocator);
+    b.allocator.destroy(b);
 }
 
 /// This function is intended to be called by lib/build_runner.zig, not a build.zig file.
@@ -698,24 +698,6 @@ pub fn addTranslateC(self: *Build, options: TranslateCStep.Options) *TranslateCS
     return TranslateCStep.create(self, options);
 }
 
-pub fn make(self: *Build, step_names: []const []const u8) !void {
-    var wanted_steps = ArrayList(*Step).init(self.allocator);
-    defer wanted_steps.deinit();
-
-    if (step_names.len == 0) {
-        try wanted_steps.append(self.default_step);
-    } else {
-        for (step_names) |step_name| {
-            const s = try self.getTopLevelStepByName(step_name);
-            try wanted_steps.append(s);
-        }
-    }
-
-    for (wanted_steps.items) |s| {
-        try self.makeOneStep(s);
-    }
-}
-
 pub fn getInstallStep(self: *Build) *Step {
     return &self.install_tls.step;
 }
@@ -739,37 +721,6 @@ fn makeUninstall(uninstall_step: *Step) anyerror!void {
     // TODO remove empty directories
 }
 
-fn makeOneStep(self: *Build, s: *Step) anyerror!void {
-    if (s.loop_flag) {
-        log.err("Dependency loop detected:\n  {s}", .{s.name});
-        return error.DependencyLoopDetected;
-    }
-    s.loop_flag = true;
-
-    for (s.dependencies.items) |dep| {
-        self.makeOneStep(dep) catch |err| {
-            if (err == error.DependencyLoopDetected) {
-                log.err("  {s}", .{s.name});
-            }
-            return err;
-        };
-    }
-
-    s.loop_flag = false;
-
-    try s.make();
-}
-
-fn getTopLevelStepByName(self: *Build, name: []const u8) !*Step {
-    for (self.top_level_steps.items) |top_level_step| {
-        if (mem.eql(u8, top_level_step.step.name, name)) {
-            return &top_level_step.step;
-        }
-    }
-    log.err("Cannot run step '{s}' because it does not exist", .{name});
-    return error.InvalidStepName;
-}
-
 pub fn option(self: *Build, comptime T: type, name_raw: []const u8, description_raw: []const u8) ?T {
     const name = self.dupe(name_raw);
     const description = self.dupe(description_raw);
@@ -910,7 +861,7 @@ pub fn step(self: *Build, name: []const u8, description: []const u8) *Step {
         .step = Step.initNoOp(.top_level, name, self.allocator),
         .description = self.dupe(description),
     };
-    self.top_level_steps.append(step_info) catch @panic("OOM");
+    self.top_level_steps.put(self.allocator, step_info.step.name, step_info) catch @panic("OOM");
     return &step_info.step;
 }
 
lib/build_runner.zig
@@ -92,23 +92,23 @@ pub fn main() !void {
     // before arg parsing, check for the NO_COLOR environment variable
     // if it exists, default the color setting to .off
     // explicit --color arguments will still override this setting.
-    builder.color = if (std.process.hasEnvVarConstant("NO_COLOR")) .off else .auto;
+    builder.color = if (process.hasEnvVarConstant("NO_COLOR")) .off else .auto;
 
     while (nextArg(args, &arg_idx)) |arg| {
         if (mem.startsWith(u8, arg, "-D")) {
             const option_contents = arg[2..];
             if (option_contents.len == 0) {
                 std.debug.print("Expected option name after '-D'\n\n", .{});
-                return usageAndErr(builder, false, stderr_stream);
+                usageAndErr(builder, false, stderr_stream);
             }
             if (mem.indexOfScalar(u8, option_contents, '=')) |name_end| {
                 const option_name = option_contents[0..name_end];
                 const option_value = option_contents[name_end + 1 ..];
                 if (try builder.addUserInputOption(option_name, option_value))
-                    return usageAndErr(builder, false, stderr_stream);
+                    usageAndErr(builder, false, stderr_stream);
             } else {
                 if (try builder.addUserInputFlag(option_contents))
-                    return usageAndErr(builder, false, stderr_stream);
+                    usageAndErr(builder, false, stderr_stream);
             }
         } else if (mem.startsWith(u8, arg, "-")) {
             if (mem.eql(u8, arg, "--verbose")) {
@@ -118,61 +118,61 @@ pub fn main() !void {
             } else if (mem.eql(u8, arg, "-p") or mem.eql(u8, arg, "--prefix")) {
                 install_prefix = nextArg(args, &arg_idx) orelse {
                     std.debug.print("Expected argument after {s}\n\n", .{arg});
-                    return usageAndErr(builder, false, stderr_stream);
+                    usageAndErr(builder, false, stderr_stream);
                 };
             } else if (mem.eql(u8, arg, "-l") or mem.eql(u8, arg, "--list-steps")) {
                 return steps(builder, false, stdout_stream);
             } else if (mem.eql(u8, arg, "--prefix-lib-dir")) {
                 dir_list.lib_dir = nextArg(args, &arg_idx) orelse {
                     std.debug.print("Expected argument after {s}\n\n", .{arg});
-                    return usageAndErr(builder, false, stderr_stream);
+                    usageAndErr(builder, false, stderr_stream);
                 };
             } else if (mem.eql(u8, arg, "--prefix-exe-dir")) {
                 dir_list.exe_dir = nextArg(args, &arg_idx) orelse {
                     std.debug.print("Expected argument after {s}\n\n", .{arg});
-                    return usageAndErr(builder, false, stderr_stream);
+                    usageAndErr(builder, false, stderr_stream);
                 };
             } else if (mem.eql(u8, arg, "--prefix-include-dir")) {
                 dir_list.include_dir = nextArg(args, &arg_idx) orelse {
                     std.debug.print("Expected argument after {s}\n\n", .{arg});
-                    return usageAndErr(builder, false, stderr_stream);
+                    usageAndErr(builder, false, stderr_stream);
                 };
             } else if (mem.eql(u8, arg, "--sysroot")) {
                 const sysroot = nextArg(args, &arg_idx) orelse {
                     std.debug.print("Expected argument after --sysroot\n\n", .{});
-                    return usageAndErr(builder, false, stderr_stream);
+                    usageAndErr(builder, false, stderr_stream);
                 };
                 builder.sysroot = sysroot;
             } else if (mem.eql(u8, arg, "--search-prefix")) {
                 const search_prefix = nextArg(args, &arg_idx) orelse {
                     std.debug.print("Expected argument after --search-prefix\n\n", .{});
-                    return usageAndErr(builder, false, stderr_stream);
+                    usageAndErr(builder, false, stderr_stream);
                 };
                 builder.addSearchPrefix(search_prefix);
             } else if (mem.eql(u8, arg, "--libc")) {
                 const libc_file = nextArg(args, &arg_idx) orelse {
                     std.debug.print("Expected argument after --libc\n\n", .{});
-                    return usageAndErr(builder, false, stderr_stream);
+                    usageAndErr(builder, false, stderr_stream);
                 };
                 builder.libc_file = libc_file;
             } else if (mem.eql(u8, arg, "--color")) {
                 const next_arg = nextArg(args, &arg_idx) orelse {
                     std.debug.print("expected [auto|on|off] after --color", .{});
-                    return usageAndErr(builder, false, stderr_stream);
+                    usageAndErr(builder, false, stderr_stream);
                 };
                 builder.color = std.meta.stringToEnum(@TypeOf(builder.color), next_arg) orelse {
                     std.debug.print("expected [auto|on|off] after --color, found '{s}'", .{next_arg});
-                    return usageAndErr(builder, false, stderr_stream);
+                    usageAndErr(builder, false, stderr_stream);
                 };
             } else if (mem.eql(u8, arg, "--zig-lib-dir")) {
                 builder.zig_lib_dir = nextArg(args, &arg_idx) orelse {
                     std.debug.print("Expected argument after --zig-lib-dir\n\n", .{});
-                    return usageAndErr(builder, false, stderr_stream);
+                    usageAndErr(builder, false, stderr_stream);
                 };
             } else if (mem.eql(u8, arg, "--debug-log")) {
                 const next_arg = nextArg(args, &arg_idx) orelse {
                     std.debug.print("Expected argument after {s}\n\n", .{arg});
-                    return usageAndErr(builder, false, stderr_stream);
+                    usageAndErr(builder, false, stderr_stream);
                 };
                 try debug_log_scopes.append(next_arg);
             } else if (mem.eql(u8, arg, "--debug-compile-errors")) {
@@ -180,7 +180,7 @@ pub fn main() !void {
             } else if (mem.eql(u8, arg, "--glibc-runtimes")) {
                 builder.glibc_runtimes_dir = nextArg(args, &arg_idx) orelse {
                     std.debug.print("Expected argument after --glibc-runtimes\n\n", .{});
-                    return usageAndErr(builder, false, stderr_stream);
+                    usageAndErr(builder, false, stderr_stream);
                 };
             } else if (mem.eql(u8, arg, "--verbose-link")) {
                 builder.verbose_link = true;
@@ -231,7 +231,7 @@ pub fn main() !void {
                 break;
             } else {
                 std.debug.print("Unrecognized argument: {s}\n\n", .{arg});
-                return usageAndErr(builder, false, stderr_stream);
+                usageAndErr(builder, false, stderr_stream);
             }
         } else {
             try targets.append(arg);
@@ -243,13 +243,10 @@ pub fn main() !void {
     try builder.runBuild(root);
 
     if (builder.validateUserInputDidItFail())
-        return usageAndErr(builder, true, stderr_stream);
+        usageAndErr(builder, true, stderr_stream);
 
-    builder.make(targets.items) catch |err| {
+    make(builder, targets.items) catch |err| {
         switch (err) {
-            error.InvalidStepName => {
-                return usageAndErr(builder, true, stderr_stream);
-            },
             error.UncleanExit => process.exit(1),
             // This error is intended to indicate that the step has already
             // logged an error message and so printing the error return trace
@@ -261,6 +258,48 @@ pub fn main() !void {
     };
 }
 
+fn make(b: *std.Build, step_names: []const []const u8) !void {
+    var wanted_steps = ArrayList(*std.Build.Step).init(b.allocator);
+    defer wanted_steps.deinit();
+
+    if (step_names.len == 0) {
+        try wanted_steps.append(b.default_step);
+    } else {
+        for (step_names) |step_name| {
+            const s = b.top_level_steps.get(step_name) orelse {
+                std.debug.print("no step named '{s}'. Access the help menu with 'zig build -h'\n", .{step_name});
+                process.exit(1);
+            };
+            try wanted_steps.append(&s.step);
+        }
+    }
+
+    for (wanted_steps.items) |s| {
+        try makeOneStep(b, s);
+    }
+}
+
+fn makeOneStep(b: *std.Build, s: *std.Build.Step) anyerror!void {
+    if (s.loop_flag) {
+        std.debug.print("dependency loop detected:\n  {s}\n", .{s.name});
+        return error.DependencyLoopDetected;
+    }
+    s.loop_flag = true;
+
+    for (s.dependencies.items) |dep| {
+        makeOneStep(b, dep) catch |err| {
+            if (err == error.DependencyLoopDetected) {
+                std.debug.print("  {s}\n", .{s.name});
+            }
+            return err;
+        };
+    }
+
+    s.loop_flag = false;
+
+    try s.make();
+}
+
 fn steps(builder: *std.Build, already_ran_build: bool, out_stream: anytype) !void {
     // run the build script to collect the options
     if (!already_ran_build) {
@@ -269,7 +308,7 @@ fn steps(builder: *std.Build, already_ran_build: bool, out_stream: anytype) !voi
     }
 
     const allocator = builder.allocator;
-    for (builder.top_level_steps.items) |top_level_step| {
+    for (builder.top_level_steps.values()) |top_level_step| {
         const name = if (&top_level_step.step == builder.default_step)
             try fmt.allocPrint(allocator, "{s} (default)", .{top_level_step.step.name})
         else
@@ -374,7 +413,7 @@ fn usage(builder: *std.Build, already_ran_build: bool, out_stream: anytype) !voi
     );
 }
 
-fn usageAndErr(builder: *std.Build, already_ran_build: bool, out_stream: anytype) void {
+fn usageAndErr(builder: *std.Build, already_ran_build: bool, out_stream: anytype) noreturn {
     usage(builder, already_ran_build, out_stream) catch {};
     process.exit(1);
 }