authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-05-25 12:51:23-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-05-25 18:54:36-07:00
log9eb85c4e5eb65ae987463af33ca24225f12b3a8b
tree4692117790117cd29eb9022b2c195df1ce2e721d
parentea151030bc4a1366ef3ca0bd1f59d4867a215762

build system: track TODOs outside source code

related to #363

10 files changed, 28 insertions(+), 41 deletions(-)

build.zig-2
...@@ -1525,8 +1525,6 @@ fn generateLangRef(b: *std.Build) !std.Build.LazyPath {...@@ -1525,8 +1525,6 @@ fn generateLangRef(b: *std.Build) !std.Build.LazyPath {
1525 cmd.addArg("--zig");1525 cmd.addArg("--zig");
1526 cmd.addFileArg(.zig_exe);1526 cmd.addFileArg(.zig_exe);
15271527
1528 // TODO: enhance doctest to use "--listen=-" rather than operating in a
1529 // temporary directory
1530 cmd.addArg("--cache-root");1528 cmd.addArg("--cache-root");
1531 cmd.addDirectoryArg(.cache_root);1529 cmd.addDirectoryArg(.cache_root);
15321530
lib/compiler/Maker.zig+3-5
...@@ -184,7 +184,6 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -184,7 +184,6 @@ pub fn main(init: process.Init.Minimal) !void {
184 } else if (mem.eql(u8, arg, "--sysroot")) {184 } else if (mem.eql(u8, arg, "--sysroot")) {
185 graph.sysroot = nextArgOrFatal(args, &arg_idx);185 graph.sysroot = nextArgOrFatal(args, &arg_idx);
186 } else if (mem.eql(u8, arg, "--maxrss")) {186 } else if (mem.eql(u8, arg, "--maxrss")) {
187 // TODO refactor and reuse the fuzz number parsing here
188 const max_rss_text = nextArgOrFatal(args, &arg_idx);187 const max_rss_text = nextArgOrFatal(args, &arg_idx);
189 max_rss = std.fmt.parseIntSizeSuffix(max_rss_text, 10) catch |err|188 max_rss = std.fmt.parseIntSizeSuffix(max_rss_text, 10) catch |err|
190 fatal("invalid byte size {q}: {t}", .{ max_rss_text, err });189 fatal("invalid byte size {q}: {t}", .{ max_rss_text, err });
...@@ -269,7 +268,6 @@ pub fn main(init: process.Init.Minimal) !void {...@@ -269,7 +268,6 @@ pub fn main(init: process.Init.Minimal) !void {
269 graph.build_id = std.zig.BuildId.parse(style) catch |err|268 graph.build_id = std.zig.BuildId.parse(style) catch |err|
270 fatal("unable to parse --build-id style {q}: {t}", .{ style, err });269 fatal("unable to parse --build-id style {q}: {t}", .{ style, err });
271 } else if (mem.eql(u8, arg, "--debounce")) {270 } else if (mem.eql(u8, arg, "--debounce")) {
272 // TODO refactor and reuse the timeout parsing code also here
273 const next_arg = nextArg(args, &arg_idx) orelse271 const next_arg = nextArg(args, &arg_idx) orelse
274 fatalWithHint("expected u16 after {q}", .{arg});272 fatalWithHint("expected u16 after {q}", .{arg});
275 debounce_interval_ms = std.fmt.parseUnsigned(u16, next_arg, 0) catch |err| {273 debounce_interval_ms = std.fmt.parseUnsigned(u16, next_arg, 0) catch |err| {
...@@ -1887,7 +1885,7 @@ pub fn truncatePath(...@@ -1887,7 +1885,7 @@ pub fn truncatePath(
1887) Step.ExtendedMakeError!void {1885) Step.ExtendedMakeError!void {
1888 const graph = maker.graph;1886 const graph = maker.graph;
1889 const io = graph.io;1887 const io = graph.io;
1890 if (graph.verbose) try graph.handleVerbose(.inherit, null, &.{1888 if (graph.verbose) try graph.handleVerbose(null, null, &.{
1891 "truncate", try dest_path.toString(arena),1889 "truncate", try dest_path.toString(arena),
1892 });1890 });
1893 const err = e: {1891 const err = e: {
...@@ -1924,7 +1922,7 @@ pub fn installPath(...@@ -1924,7 +1922,7 @@ pub fn installPath(
1924) Step.ExtendedMakeError!Dir.PrevStatus {1922) Step.ExtendedMakeError!Dir.PrevStatus {
1925 const graph = maker.graph;1923 const graph = maker.graph;
1926 const io = graph.io;1924 const io = graph.io;
1927 if (graph.verbose) try graph.handleVerbose(.inherit, null, &.{1925 if (graph.verbose) try graph.handleVerbose(null, null, &.{
1928 "install", "-C", try src_path.toString(arena), try dest_path.toString(arena),1926 "install", "-C", try src_path.toString(arena), try dest_path.toString(arena),
1929 });1927 });
1930 return Dir.updateFile(1928 return Dir.updateFile(
...@@ -1949,7 +1947,7 @@ pub fn installDir(...@@ -1949,7 +1947,7 @@ pub fn installDir(
1949) Step.ExtendedMakeError!Dir.CreatePathStatus {1947) Step.ExtendedMakeError!Dir.CreatePathStatus {
1950 const graph = maker.graph;1948 const graph = maker.graph;
1951 const io = graph.io;1949 const io = graph.io;
1952 if (graph.verbose) try graph.handleVerbose(.inherit, null, &.{1950 if (graph.verbose) try graph.handleVerbose(null, null, &.{
1953 "install", "-d", try dest_path.toString(arena),1951 "install", "-d", try dest_path.toString(arena),
1954 });1952 });
1955 return dest_path.root_dir.handle.createDirPathStatus(io, dest_path.sub_path, .default_dir) catch |err| {1953 return dest_path.root_dir.handle.createDirPathStatus(io, dest_path.sub_path, .default_dir) catch |err| {
lib/compiler/Maker/Graph.zig+1-1
...@@ -69,7 +69,7 @@ enable_rosetta: bool = false,...@@ -69,7 +69,7 @@ enable_rosetta: bool = false,
69/// before spawning them.69/// before spawning them.
70pub fn handleVerbose(70pub fn handleVerbose(
71 graph: *const Graph,71 graph: *const Graph,
72 cwd: std.process.Child.Cwd,72 cwd: ?[]const u8,
73 opt_env: ?*const std.process.Environ.Map,73 opt_env: ?*const std.process.Environ.Map,
74 argv: []const []const u8,74 argv: []const []const u8,
75) error{OutOfMemory}!void {75) error{OutOfMemory}!void {
lib/compiler/Maker/Step.zig+2-2
...@@ -341,7 +341,7 @@ pub fn captureChildProcess(s: *Step, maker: *Maker, options: CaptureChildProcess...@@ -341,7 +341,7 @@ pub fn captureChildProcess(s: *Step, maker: *Maker, options: CaptureChildProcess
341 s.result_failed_command = try std.zig.allocPrintCmd(gpa, options.argv, .{});341 s.result_failed_command = try std.zig.allocPrintCmd(gpa, options.argv, .{});
342342
343 try handleChildProcUnsupported(s, maker);343 try handleChildProcUnsupported(s, maker);
344 try graph.handleVerbose(.inherit, null, options.argv);344 try graph.handleVerbose(null, null, options.argv);
345345
346 const result = std.process.run(arena, io, .{346 const result = std.process.run(arena, io, .{
347 .argv = options.argv,347 .argv = options.argv,
...@@ -459,7 +459,7 @@ pub fn evalZigProcess(...@@ -459,7 +459,7 @@ pub fn evalZigProcess(
459 assert(argv.len != 0);459 assert(argv.len != 0);
460460
461 try handleChildProcUnsupported(s, maker);461 try handleChildProcUnsupported(s, maker);
462 try graph.handleVerbose(.inherit, null, argv);462 try graph.handleVerbose(null, null, argv);
463463
464 const zp = try gpa.create(ZigProcess);464 const zp = try gpa.create(ZigProcess);
465 defer if (!watch) gpa.destroy(zp);465 defer if (!watch) gpa.destroy(zp);
lib/compiler/Maker/Step/InstallDir.zig-1
...@@ -81,7 +81,6 @@ pub fn make(...@@ -81,7 +81,6 @@ pub fn make(
81 .file => {81 .file => {
82 for (blank_extensions) |ext| {82 for (blank_extensions) |ext| {
83 if (endsWith(u8, entry.path, ext.slice(conf))) {83 if (endsWith(u8, entry.path, ext.slice(conf))) {
84 // TODO check if the file was already there and length 0
85 try maker.truncatePath(arena, dest_path, step_index);84 try maker.truncatePath(arena, dest_path, step_index);
86 continue :next_entry;85 continue :next_entry;
87 }86 }
lib/compiler/Maker/Step/Run.zig+12-8
...@@ -1796,7 +1796,12 @@ fn runCommand(...@@ -1796,7 +1796,12 @@ fn runCommand(
1796 }1796 }
1797 }1797 }
17981798
1799 try graph.handleVerbose(cwd, environ_map, argv);1799 const cwd_string = switch (cwd) {
1800 .path => |p| p,
1801 .dir => unreachable,
1802 .inherit => null,
1803 };
1804 try graph.handleVerbose(cwd_string, environ_map, argv);
18001805
1801 const opt_generic_result = spawnChildAndCollect(1806 const opt_generic_result = spawnChildAndCollect(
1802 run_index,1807 run_index,
...@@ -1812,10 +1817,6 @@ fn runCommand(...@@ -1812,10 +1817,6 @@ fn runCommand(
1812 error.InvalidExe, // cpu arch mismatch1817 error.InvalidExe, // cpu arch mismatch
1813 error.FileNotFound, // can happen with a wrong dynamic linker path1818 error.FileNotFound, // can happen with a wrong dynamic linker path
1814 => interpret: {1819 => interpret: {
1815 // TODO: learn the target from the binary directly rather than from
1816 // relying on it being a Compile step. This will make this logic
1817 // work even for the edge case that the binary was produced by a
1818 // third party.
1819 const producer_index = arg0.producer.value orelse break :interpret;1820 const producer_index = arg0.producer.value orelse break :interpret;
1820 const producer_step = producer_index.ptr(conf);1821 const producer_step = producer_index.ptr(conf);
1821 const producer = producer_step.extended.get(conf.extra).compile;1822 const producer = producer_step.extended.get(conf.extra).compile;
...@@ -1829,7 +1830,6 @@ fn runCommand(...@@ -1829,7 +1830,6 @@ fn runCommand(
1829 const root_target = std.zig.system.resolveTargetQuery(io, other_target_query) catch unreachable;1830 const root_target = std.zig.system.resolveTargetQuery(io, other_target_query) catch unreachable;
1830 const link_libc = maker.stepByIndex(producer_index).extended.compile.is_linking_libc;1831 const link_libc = maker.stepByIndex(producer_index).extended.compile.is_linking_libc;
18311832
1832 // TODO get this from the parent process instead
1833 const host: std.Target = std.zig.system.resolveTargetQuery(io, .{}) catch |he| switch (he) {1833 const host: std.Target = std.zig.system.resolveTargetQuery(io, .{}) catch |he| switch (he) {
1834 error.Canceled => |e| return e,1834 error.Canceled => |e| return e,
1835 else => builtin.target,1835 else => builtin.target,
...@@ -1941,7 +1941,7 @@ fn runCommand(...@@ -1941,7 +1941,7 @@ fn runCommand(
19411941
1942 gpa.free(step.result_failed_command.?);1942 gpa.free(step.result_failed_command.?);
1943 step.result_failed_command = null;1943 step.result_failed_command = null;
1944 try graph.handleVerbose(cwd, environ_map, interp_argv.items);1944 try graph.handleVerbose(cwd_string, environ_map, interp_argv.items);
19451945
1946 break :term spawnChildAndCollect(1946 break :term spawnChildAndCollect(
1947 run_index,1947 run_index,
...@@ -2148,7 +2148,11 @@ fn spawnChildAndCollect(...@@ -2148,7 +2148,11 @@ fn spawnChildAndCollect(
2148 // If an error occurs, it's caused by this command:2148 // If an error occurs, it's caused by this command:
2149 assert(step.result_failed_command == null);2149 assert(step.result_failed_command == null);
2150 step.result_failed_command = try std.zig.allocPrintCmd(gpa, argv, .{2150 step.result_failed_command = try std.zig.allocPrintCmd(gpa, argv, .{
2151 .cwd = child_cwd,2151 .cwd = switch (child_cwd) {
2152 .path => |p| p,
2153 .dir => unreachable,
2154 .inherit => null,
2155 },
2152 .child_env = environ_map,2156 .child_env = environ_map,
2153 .parent_env = &graph.environ_map,2157 .parent_env = &graph.environ_map,
2154 });2158 });
lib/compiler/Maker/WebServer.zig-14
...@@ -225,7 +225,6 @@ pub fn updateStepStatus(...@@ -225,7 +225,6 @@ pub fn updateStepStatus(
225) void {225) void {
226 const maker = ws.maker;226 const maker = ws.maker;
227 const all_steps = maker.step_stack.keys();227 const all_steps = maker.step_stack.keys();
228 // TODO don't do linear search, especially in a hot loop like this
229 const step_idx: u32 = for (all_steps, 0..) |s, i| {228 const step_idx: u32 = for (all_steps, 0..) |s, i| {
230 if (s == step_index) break @intCast(i);229 if (s == step_index) break @intCast(i);
231 } else unreachable;230 } else unreachable;
...@@ -569,16 +568,6 @@ pub fn serveTarFile(ws: *WebServer, request: *http.Server.Request, paths: []cons...@@ -569,16 +568,6 @@ pub fn serveTarFile(ws: *WebServer, request: *http.Server.Request, paths: []cons
569 var read_buffer: [1024]u8 = undefined;568 var read_buffer: [1024]u8 = undefined;
570 var file_reader: Io.File.Reader = .initSize(file, io, &read_buffer, stat.size);569 var file_reader: Io.File.Reader = .initSize(file, io, &read_buffer, stat.size);
571570
572 // TODO: this logic is completely bogus -- obviously so, because `path.root_dir.path` can
573 // be cwd-relative. This is also related to why linkification doesn't work in the fuzzer UI:
574 // it turns out the WASM treats the first path component as the module name, typically
575 // resulting in modules named "" and "src". The compiler needs to tell the build system
576 // about the module graph so that the build system can correctly encode this information in
577 // the tar file.
578 //
579 // Additionally, this needs to ensure that all path separators for both prefix and
580 // sub_path are using the POSIX-style `/` on platforms that don't use it as their native
581 // path separator.
582 archiver.prefix = path.root_dir.path orelse graph.cache.cwd;571 archiver.prefix = path.root_dir.path orelse graph.cache.cwd;
583 try archiver.writeFile(path.sub_path, &file_reader, @intCast(stat.mtime.toSeconds()));572 try archiver.writeFile(path.sub_path, &file_reader, @intCast(stat.mtime.toSeconds()));
584 }573 }
...@@ -799,7 +788,6 @@ pub fn updateTimeReportCompile(ws: *WebServer, opts: struct {...@@ -799,7 +788,6 @@ pub fn updateTimeReportCompile(ws: *WebServer, opts: struct {
799 const io = maker.graph.io;788 const io = maker.graph.io;
800 const all_steps = maker.step_stack.keys();789 const all_steps = maker.step_stack.keys();
801790
802 // TODO don't do linear search
803 const step_idx: u32 = for (all_steps, 0..) |s, i| {791 const step_idx: u32 = for (all_steps, 0..) |s, i| {
804 if (s == opts.compile_step) break @intCast(i);792 if (s == opts.compile_step) break @intCast(i);
805 } else unreachable;793 } else unreachable;
...@@ -843,7 +831,6 @@ pub fn updateTimeReportGeneric(ws: *WebServer, step_index: Configuration.Step.In...@@ -843,7 +831,6 @@ pub fn updateTimeReportGeneric(ws: *WebServer, step_index: Configuration.Step.In
843 const io = maker.graph.io;831 const io = maker.graph.io;
844 const all_steps = maker.step_stack.keys();832 const all_steps = maker.step_stack.keys();
845833
846 // TODO don't do linear search
847 const step_idx: u32 = for (all_steps, 0..) |s, i| {834 const step_idx: u32 = for (all_steps, 0..) |s, i| {
848 if (s == step_index) break @intCast(i);835 if (s == step_index) break @intCast(i);
849 } else unreachable;836 } else unreachable;
...@@ -882,7 +869,6 @@ pub fn updateTimeReportRunTest(...@@ -882,7 +869,6 @@ pub fn updateTimeReportRunTest(
882 const io = maker.graph.io;869 const io = maker.graph.io;
883 const all_steps = maker.step_stack.keys();870 const all_steps = maker.step_stack.keys();
884871
885 // TODO don't do linear search
886 const step_idx: u32 = for (all_steps, 0..) |s, i| {872 const step_idx: u32 = for (all_steps, 0..) |s, i| {
887 if (s == run_step_index) break @intCast(i);873 if (s == run_step_index) break @intCast(i);
888 } else unreachable;874 } else unreachable;
lib/std/Build.zig+5-1
...@@ -1890,7 +1890,11 @@ pub fn runFallible(b: *Build, argv: []const []const u8, options: RunOptions) Run...@@ -1890,7 +1890,11 @@ pub fn runFallible(b: *Build, argv: []const []const u8, options: RunOptions) Run
1890 const arena = graph.arena;1890 const arena = graph.arena;
18911891
1892 const print_opts: std.zig.AllocPrintCmdOptions = .{1892 const print_opts: std.zig.AllocPrintCmdOptions = .{
1893 .cwd = options.cwd,1893 .cwd = switch (options.cwd) {
1894 .inherit => null,
1895 .path => |p| p,
1896 .dir => null, // Unknown without changing function signature of runFallible.
1897 },
1894 .child_env = options.environ_map,1898 .child_env = options.environ_map,
1895 .parent_env = &graph.environ_map,1899 .parent_env = &graph.environ_map,
1896 };1900 };
lib/std/Build/Configuration.zig+2-2
...@@ -3099,7 +3099,7 @@ pub const Storage = enum {...@@ -3099,7 +3099,7 @@ pub const Storage = enum {
3099 .value = if (match) dataField(buffer, i, container, Field.Value) else null,3099 .value = if (match) dataField(buffer, i, container, Field.Value) else null,
3100 };3100 };
3101 },3101 },
3102 .extended => @compileError("TODO"),3102 .extended => @compileError("unimplemented"),
3103 .length_prefixed_list => {3103 .length_prefixed_list => {
3104 const n = @divExact(@sizeOf(Field.Elem), @sizeOf(u32));3104 const n = @divExact(@sizeOf(Field.Elem), @sizeOf(u32));
3105 const data_start = i.* + 1;3105 const data_start = i.* + 1;
...@@ -3260,7 +3260,7 @@ pub const Storage = enum {...@@ -3260,7 +3260,7 @@ pub const Storage = enum {
3260 .flag_union => return switch (value.u) {3260 .flag_union => return switch (value.u) {
3261 inline else => |x| setExtraField(buffer, i, @TypeOf(x), x),3261 inline else => |x| setExtraField(buffer, i, @TypeOf(x), x),
3262 },3262 },
3263 .extended => @compileError("TODO"),3263 .extended => @compileError("unimplemented"),
3264 .flag_length_prefixed_list => {3264 .flag_length_prefixed_list => {
3265 const len: u32 = @intCast(value.slice.len);3265 const len: u32 = @intCast(value.slice.len);
3266 if (len == 0) return 0; // Flag bit hides the length prefix.3266 if (len == 0) return 0; // Flag bit hides the length prefix.
lib/std/zig.zig+3-5
...@@ -1168,7 +1168,7 @@ pub const ClangCliParam = struct {...@@ -1168,7 +1168,7 @@ pub const ClangCliParam = struct {
1168};1168};
11691169
1170pub const AllocPrintCmdOptions = struct {1170pub const AllocPrintCmdOptions = struct {
1171 cwd: std.process.Child.Cwd = .inherit,1171 cwd: ?[]const u8 = null,
1172 parent_env: ?*const std.process.Environ.Map = null,1172 parent_env: ?*const std.process.Environ.Map = null,
1173 child_env: ?*const std.process.Environ.Map = null,1173 child_env: ?*const std.process.Environ.Map = null,
1174};1174};
...@@ -1212,10 +1212,8 @@ pub fn allocPrintCmd(gpa: Allocator, argv: []const []const u8, options: AllocPri...@@ -1212,10 +1212,8 @@ pub fn allocPrintCmd(gpa: Allocator, argv: []const []const u8, options: AllocPri
1212 var aw: Io.Writer.Allocating = .init(gpa);1212 var aw: Io.Writer.Allocating = .init(gpa);
1213 defer aw.deinit();1213 defer aw.deinit();
1214 const writer = &aw.writer;1214 const writer = &aw.writer;
1215 switch (options.cwd) {1215 if (options.cwd) |path| {
1216 .inherit => {},1216 writer.print("cd {s} && ", .{path}) catch return error.OutOfMemory;
1217 .path => |path| writer.print("cd {s} && ", .{path}) catch return error.OutOfMemory,
1218 .dir => @panic("TODO"),
1219 }1217 }
1220 if (options.child_env) |child_env| {1218 if (options.child_env) |child_env| {
1221 for (child_env.keys(), child_env.values()) |key, value| {1219 for (child_env.keys(), child_env.values()) |key, value| {