authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-05-06 23:17:34-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2026-05-25 18:54:35-07:00
logaffe5ed867009c889f2df7b624387c2bceefcc0e
treefd99f28828e8eaf77cbf82c37f4f2078f4acf77b
parentd3ec255a1f7cd38164de816462c29de4a2981490

std.Build: port UpdateSourceFiles step to new system


11 files changed, 293 insertions(+), 209 deletions(-)

BRANCH_TODO+2
......@@ -28,6 +28,8 @@
2828* no more "artifact arg" to run step. if you want to run the post-install binary, get the lazy path
2929 from the install step.
3030* fmt step: import zig fmt code directly rather than child proc
31* UpdateSourceFiles: introduce Group
32* WriteFiles: introduce Group
3133
3234## Already Filed Followup Issues
3335* build system fmt step with check=false does not acquire a write lock on source files #35204
lib/compiler/Maker/Step.zig+4-3
......@@ -22,6 +22,7 @@ pub const Compile = @import("Step/Compile.zig");
2222pub const Run = @import("Step/Run.zig");
2323pub const InstallArtifact = @import("Step/InstallArtifact.zig");
2424pub const InstallFile = @import("Step/InstallFile.zig");
25pub const UpdateSourceFiles = @import("Step/UpdateSourceFiles.zig");
2526
2627/// Avoid false sharing.
2728_: void align(std.atomic.cache_line) = {},
......@@ -75,13 +76,13 @@ pub const Extended = union(enum) {
7576 install_artifact: InstallArtifact,
7677 install_dir: Todo,
7778 install_file: InstallFile,
78 objcopy: Todo,
79 obj_copy: Todo,
7980 options: Todo,
8081 remove_dir: Todo,
8182 run: Run,
8283 top_level: TopLevel,
8384 translate_c: Todo,
84 update_source_files: Todo,
85 update_source_files: UpdateSourceFiles,
8586 write_file: Todo,
8687
8788 pub fn init(tag: Configuration.Step.Tag) Extended {
......@@ -95,7 +96,7 @@ pub const Extended = union(enum) {
9596 .install_artifact => .{ .install_artifact = .{} },
9697 .install_dir => .{ .install_dir = .{} },
9798 .install_file => .{ .install_file = .{} },
98 .objcopy => .{ .objcopy = .{} },
99 .obj_copy => .{ .obj_copy = .{} },
99100 .options => .{ .options = .{} },
100101 .remove_dir => .{ .remove_dir = .{} },
101102 .run => .{ .run = .{} },
lib/compiler/Maker/Step/ObjCopy.zig created+142
......@@ -0,0 +1,142 @@
1const ObjCopy = @This();
2
3const std = @import("std");
4const Io = std.Io;
5const allocPrint = std.fmt.allocPrint;
6const Configuration = std.Build.Configuration;
7
8const Step = @import("../Step.zig");
9const Maker = @import("../../Maker.zig");
10
11pub fn make(
12 obj_copy: *ObjCopy,
13 step_index: Configuration.Step.Index,
14 maker: *Maker,
15 progress_node: std.Progress.Node,
16) Step.ExtendedMakeError!void {
17 _ = obj_copy;
18 const graph = maker.graph;
19 const arena = maker.graph.arena; // TODO don't leak into process arena
20 const io = graph.io;
21 const step = maker.stepByIndex(step_index);
22 const conf = &maker.scanned_config.configuration;
23 const conf_step = step_index.ptr(conf);
24 const conf_oc = conf_step.extended.get(conf.extra).obj_copy;
25 const cache_root = graph.local_cache_root;
26
27 try step.singleUnchangingWatchInput(maker, arena, conf_oc.input_file);
28
29 var man = graph.cache.obtain();
30 defer man.deinit();
31
32 const src_path = try maker.resolveLazyPathIndex(arena, conf_oc.input_file, step_index);
33 _ = try man.addFilePath(src_path, null);
34 man.hash.addOptionalBytes(conf_oc.only_section);
35 man.hash.addOptional(conf_oc.pad_to);
36 man.hash.addOptional(conf_oc.format);
37 man.hash.add(conf_oc.compress_debug);
38 man.hash.add(conf_oc.strip);
39 man.hash.add(conf_oc.output_file_debug != null);
40
41 if (try step.cacheHit(&man)) {
42 // Cache hit, skip subprocess execution.
43 const digest = man.final();
44 conf_oc.output_file.path = try cache_root.join(arena, &.{
45 "o", &digest, conf_oc.basename,
46 });
47 if (conf_oc.output_file_debug) |*file| {
48 file.path = try cache_root.join(arena, &.{
49 "o", &digest, try allocPrint(arena, "{s}.debug", .{conf_oc.basename}),
50 });
51 }
52 return;
53 }
54
55 const digest = man.final();
56 const cache_path = "o" ++ Io.Dir.path.sep_str ++ digest;
57 const full_dest_path = try cache_root.join(arena, &.{ cache_path, conf_oc.basename });
58 const full_dest_path_debug = try cache_root.join(arena, &.{
59 cache_path, try allocPrint(arena, "{s}.debug", .{conf_oc.basename}),
60 });
61 cache_root.handle.createDirPath(io, cache_path) catch |err|
62 return step.fail("unable to make path {s}: {t}", .{ cache_path, err });
63
64 var argv: std.ArrayList([]const u8) = .empty;
65 try argv.ensureUnusedCapacity(arena, 11);
66
67 argv.addManyAsArrayAssumeCapacity(2).* = .{ graph.zig_exe, "objcopy" };
68
69 if (conf_oc.only_section) |only_section|
70 argv.addManyAsArrayAssumeCapacity(2).* = .{ "-j", only_section };
71
72 switch (conf_oc.strip) {
73 .none => {},
74 .debug => argv.appendAssumeCapacity("--strip-debug"),
75 .debug_and_symbols => argv.appendAssumeCapacity("--strip-all"),
76 }
77
78 if (conf_oc.pad_to) |pad_to| {
79 argv.addManyAsArrayAssumeCapacity(2).* = .{
80 "--pad-to", try allocPrint(arena, "{d}", .{pad_to}),
81 };
82 }
83
84 if (conf_oc.format) |format| {
85 argv.addManyAsArrayAssumeCapacity(2).* = .{
86 "-O",
87 switch (format) {
88 .bin => "binary",
89 .hex => "hex",
90 .elf => "elf",
91 },
92 };
93 }
94
95 if (conf_oc.compress_debug)
96 argv.appendAssumeCapacity("--compress-debug-sections");
97
98 if (conf_oc.output_file_debug != null)
99 argv.appendAssumeCapacity(try allocPrint(arena, "--extract-to={s}", .{full_dest_path_debug}));
100
101 try argv.ensureUnusedCapacity(arena, 9);
102
103 if (conf_oc.add_section) |section| {
104 argv.appendAssumeCapacity("--add-section");
105 argv.appendAssumeCapacity(try allocPrint(arena, "{s}={f}", .{
106 section.section_name, try maker.resolveLazyPathIndex(arena, section.file_path, step_index),
107 }));
108 }
109
110 if (conf_oc.set_section_alignment) |set_align| {
111 argv.appendAssumeCapacity("--set-section-alignment");
112 argv.appendAssumeCapacity(try allocPrint(arena, "{s}={d}", .{ set_align.section_name, set_align.alignment }));
113 }
114
115 if (conf_oc.set_section_flags) |set_flags| {
116 const f = set_flags.flags;
117 // trailing comma is allowed
118 argv.appendAssumeCapacity("--set-section-flags");
119 argv.appendAssumeCapacity(try allocPrint(arena, "{s}={s}{s}{s}{s}{s}{s}{s}{s}{s}", .{
120 set_flags.section_name,
121 if (f.alloc) "alloc," else "",
122 if (f.contents) "contents," else "",
123 if (f.load) "load," else "",
124 if (f.readonly) "readonly," else "",
125 if (f.code) "code," else "",
126 if (f.exclude) "exclude," else "",
127 if (f.large) "large," else "",
128 if (f.merge) "merge," else "",
129 if (f.strings) "strings," else "",
130 }));
131 }
132
133 argv.appendAssumeCapacity(src_path);
134 argv.appendAssumeCapacity(full_dest_path);
135
136 argv.appendAssumeCapacity("--listen=-");
137 _ = try Step.evalZigProcess(step_index, maker, argv.items, progress_node, false);
138
139 conf_oc.output_file.path = full_dest_path;
140 if (conf_oc.output_file_debug) |*file| file.path = full_dest_path_debug;
141 try man.writeManifest();
142}
lib/compiler/Maker/Step/UpdateSourceFiles.zig created+87
......@@ -0,0 +1,87 @@
1const UpdateSourceFiles = @This();
2
3const std = @import("std");
4const Io = std.Io;
5const Path = std.Build.Cache.Path;
6const allocPrint = std.fmt.allocPrint;
7const Configuration = std.Build.Configuration;
8
9const Step = @import("../Step.zig");
10const Maker = @import("../../Maker.zig");
11
12pub fn make(
13 usf: *UpdateSourceFiles,
14 step_index: Configuration.Step.Index,
15 maker: *Maker,
16 progress_node: std.Progress.Node,
17) Step.ExtendedMakeError!void {
18 _ = usf;
19 const graph = maker.graph;
20 const arena = maker.graph.arena; // TODO don't leak into process arena
21 const io = graph.io;
22 const step = maker.stepByIndex(step_index);
23 const conf = &maker.scanned_config.configuration;
24 const conf_step = step_index.ptr(conf);
25 const conf_usf = conf_step.extended.get(conf.extra).update_source_files;
26 const build_root = graph.build_root_directory;
27
28 if (conf_step.owner != .root)
29 return step.fail(maker, "non-root package attempted to update its source files", .{});
30
31 var any_miss = false;
32
33 progress_node.setEstimatedTotalItems(conf_usf.embeds.slice.len + conf_usf.copies.slice.len);
34
35 for (conf_usf.embeds.slice) |*embed| {
36 const dest_path: Path = .{
37 .root_dir = build_root,
38 .sub_path = embed.dest_path.slice(conf),
39 };
40 if (Io.Dir.path.dirname(dest_path.sub_path)) |dirname| {
41 const dirname_path: Path = .{
42 .root_dir = build_root,
43 .sub_path = dirname,
44 };
45 dirname_path.root_dir.handle.createDirPath(io, dirname_path.sub_path) catch |err|
46 return step.fail(maker, "failed to create path {f}: {t}", .{ dirname_path, err });
47 }
48 dest_path.root_dir.handle.writeFile(io, .{
49 .sub_path = dest_path.sub_path,
50 .data = embed.bytes.slice(conf),
51 }) catch |err| return step.fail(maker, "failed to write file {f}: {t}", .{ dest_path, err });
52 any_miss = true;
53 progress_node.completeOne();
54 }
55
56 for (conf_usf.copies.slice) |*copy| {
57 const dest_path: Path = .{
58 .root_dir = build_root,
59 .sub_path = copy.dest_path.slice(conf),
60 };
61 if (Io.Dir.path.dirname(dest_path.sub_path)) |dirname| {
62 const dirname_path: Path = .{
63 .root_dir = build_root,
64 .sub_path = dirname,
65 };
66 dirname_path.root_dir.handle.createDirPath(io, dirname_path.sub_path) catch |err|
67 return step.fail(maker, "failed to create path {f}: {t}", .{ dirname_path, err });
68 }
69 const src_lazy_path = copy.src_path.get(conf);
70 const source_path = try maker.resolveLazyPath(arena, src_lazy_path, step_index);
71 if (!step.inputs.populated()) try step.addWatchInput(maker, arena, src_lazy_path);
72
73 const prev_status = source_path.root_dir.handle.updateFile(
74 io,
75 source_path.sub_path,
76 dest_path.root_dir.handle,
77 dest_path.sub_path,
78 .{},
79 ) catch |err| return step.fail(maker, "unable to update file from {f} to {f}: {t}", .{
80 source_path, dest_path, err,
81 });
82 any_miss = any_miss or prev_status == .stale;
83 progress_node.completeOne();
84 }
85
86 step.result_cached = !any_miss;
87}
lib/compiler/configurer.zig+1-1
......@@ -967,7 +967,7 @@ fn serialize(b: *std.Build, wc: *Configuration.Wip, writer: *Io.Writer) !void {
967967 },
968968 .check_file => @panic("TODO"),
969969 .config_header => @panic("TODO"),
970 .objcopy => @panic("TODO"),
970 .obj_copy => @panic("TODO"),
971971 .options => @panic("TODO"),
972972 },
973973 });
lib/std/Build/Configuration.zig+21-5
......@@ -456,7 +456,7 @@ pub const Step = extern struct {
456456 install_artifact: InstallArtifact,
457457 install_dir: InstallDir,
458458 install_file: InstallFile,
459 objcopy: Objcopy,
459 obj_copy: ObjCopy,
460460 options: Options,
461461 remove_dir: RemoveDir,
462462 run: Run,
......@@ -491,7 +491,7 @@ pub const Step = extern struct {
491491 install_artifact,
492492 install_dir,
493493 install_file,
494 objcopy,
494 obj_copy,
495495 options,
496496 remove_dir,
497497 run,
......@@ -1100,11 +1100,11 @@ pub const Step = extern struct {
11001100 };
11011101 };
11021102
1103 pub const Objcopy = struct {
1103 pub const ObjCopy = struct {
11041104 flags: @This().Flags,
11051105
11061106 pub const Flags = packed struct(u32) {
1107 tag: Tag = .objcopy,
1107 tag: Tag = .obj_copy,
11081108 _: u27 = 0,
11091109 };
11101110 };
......@@ -1147,10 +1147,26 @@ pub const Step = extern struct {
11471147
11481148 pub const UpdateSourceFiles = struct {
11491149 flags: @This().Flags,
1150 embeds: Storage.FlagLengthPrefixedList(.flags, .embeds, Embed),
1151 copies: Storage.FlagLengthPrefixedList(.flags, .copies, Copy),
1152
1153 pub const Embed = extern struct {
1154 /// Relative to build root.
1155 dest_path: String,
1156 bytes: Bytes,
1157 };
1158
1159 pub const Copy = extern struct {
1160 /// Relative to build root.
1161 dest_path: String,
1162 src_path: LazyPath.Index,
1163 };
11501164
11511165 pub const Flags = packed struct(u32) {
11521166 tag: Tag = .update_source_files,
1153 _: u27 = 0,
1167 embeds: bool,
1168 copies: bool,
1169 _: u25 = 0,
11541170 };
11551171 };
11561172
lib/std/Build/Step.zig+1-1
......@@ -72,7 +72,7 @@ pub fn Type(comptime tag: Tag) type {
7272 .run => Run,
7373 .check_file => CheckFile,
7474 .config_header => ConfigHeader,
75 .objcopy => ObjCopy,
75 .obj_copy => ObjCopy,
7676 .options => Options,
7777 };
7878}
lib/std/Build/Step/ObjCopy.zig+31-148
......@@ -1,17 +1,26 @@
1const std = @import("std");
21const ObjCopy = @This();
32
4const Allocator = std.mem.Allocator;
5const ArenaAllocator = std.heap.ArenaAllocator;
6const File = std.Io.File;
7const InstallDir = std.Build.InstallDir;
3const std = @import("std");
84const Step = std.Build.Step;
9const elf = std.elf;
10const fs = std.fs;
11const sort = std.sort;
125const Configuration = std.Build.Configuration;
136
14pub const base_tag: Step.Tag = .objcopy;
7step: Step,
8input_file: std.Build.LazyPath,
9basename: []const u8,
10output_file: Configuration.GeneratedFileIndex,
11output_file_debug: Configuration.OptionalGeneratedFileIndex,
12
13format: ?RawFormat,
14only_section: ?[]const u8,
15pad_to: ?u64,
16strip: Strip,
17compress_debug: bool,
18
19add_section: ?AddSection,
20set_section_alignment: ?SetSectionAlignment,
21set_section_flags: ?SetSectionFlags,
22
23pub const base_tag: Step.Tag = .obj_copy;
1524
1625pub const RawFormat = enum {
1726 bin,
......@@ -28,28 +37,20 @@ pub const Strip = enum {
2837pub const SectionFlags = packed struct {
2938 /// add SHF_ALLOC
3039 alloc: bool = false,
31
3240 /// if section is SHT_NOBITS, set SHT_PROGBITS, otherwise do nothing
3341 contents: bool = false,
34
3542 /// if section is SHT_NOBITS, set SHT_PROGBITS, otherwise do nothing (same as contents)
3643 load: bool = false,
37
3844 /// readonly: clear default SHF_WRITE flag
3945 readonly: bool = false,
40
4146 /// add SHF_EXECINSTR
4247 code: bool = false,
43
4448 /// add SHF_EXCLUDE
4549 exclude: bool = false,
46
4750 /// add SHF_X86_64_LARGE. Fatal error if target is not x86_64
4851 large: bool = false,
49
5052 /// add SHF_MERGE
5153 merge: bool = false,
52
5354 /// add SHF_STRINGS
5455 strings: bool = false,
5556};
......@@ -69,22 +70,6 @@ pub const SetSectionFlags = struct {
6970 flags: SectionFlags,
7071};
7172
72step: Step,
73input_file: std.Build.LazyPath,
74basename: []const u8,
75output_file: Configuration.GeneratedFileIndex,
76output_file_debug: Configuration.OptionalGeneratedFileIndex,
77
78format: ?RawFormat,
79only_section: ?[]const u8,
80pad_to: ?u64,
81strip: Strip,
82compress_debug: bool,
83
84add_section: ?AddSection,
85set_section_alignment: ?SetSectionAlignment,
86set_section_flags: ?SetSectionFlags,
87
8873pub const Options = struct {
8974 basename: ?[]const u8 = null,
9075 format: ?RawFormat = null,
......@@ -111,20 +96,19 @@ pub fn create(
11196) *ObjCopy {
11297 const graph = owner.graph;
11398 const arena = graph.arena;
114
115 const objcopy = arena.create(ObjCopy) catch @panic("OOM");
116 objcopy.* = ObjCopy{
117 .step = Step.init(.{
99 const obj_copy = graph.create(ObjCopy);
100 obj_copy.* = .{
101 .step = .init(.{
118102 .tag = base_tag,
119103 .name = owner.fmt("objcopy {f}", .{input_file.fmt(graph)}),
120104 .owner = owner,
121 .makeFn = make,
122105 }),
123106 .input_file = input_file,
124 .basename = options.basename orelse std.fmt.allocPrint("{f}", .{input_file.fmt(graph)}) catch @panic("OOM"),
125 .output_file = graph.addGeneratedFile(&objcopy.step),
107 .basename = options.basename orelse
108 std.fmt.allocPrint(arena, "{f}", .{input_file.fmt(graph)}) catch @panic("OOM"),
109 .output_file = graph.addGeneratedFile(&obj_copy.step),
126110 .output_file_debug = if (options.strip != .none and options.extract_to_separate_file)
127 .init(graph.addGeneratedFile(&objcopy.step))
111 .init(graph.addGeneratedFile(&obj_copy.step))
128112 else
129113 .none,
130114 .format = options.format,
......@@ -136,115 +120,14 @@ pub fn create(
136120 .set_section_alignment = options.set_section_alignment,
137121 .set_section_flags = options.set_section_flags,
138122 };
139 input_file.addStepDependencies(&objcopy.step);
140 return objcopy;
123 input_file.addStepDependencies(&obj_copy.step);
124 return obj_copy;
141125}
142126
143pub fn getOutput(objcopy: *const ObjCopy) std.Build.LazyPath {
144 return .{ .generated = .{ .index = objcopy.output_file } };
145}
146pub fn getOutputSeparatedDebug(objcopy: *const ObjCopy) ?std.Build.LazyPath {
147 return if (objcopy.output_file_debug.unwrap()) |index| .{ .generated = .{ .index = index } } else null;
127pub fn getOutput(obj_copy: *const ObjCopy) std.Build.LazyPath {
128 return .{ .generated = .{ .index = obj_copy.output_file } };
148129}
149130
150fn make(step: *Step, options: Step.MakeOptions) !void {
151 const prog_node = options.progress_node;
152 const b = step.owner;
153 const io = b.graph.io;
154 const objcopy: *ObjCopy = @fieldParentPtr("step", step);
155 try step.singleUnchangingWatchInput(objcopy.input_file);
156
157 var man = b.graph.cache.obtain();
158 defer man.deinit();
159
160 const full_src_path = objcopy.input_file.getPath2(b, step);
161 _ = try man.addFile(full_src_path, null);
162 man.hash.addOptionalBytes(objcopy.only_section);
163 man.hash.addOptional(objcopy.pad_to);
164 man.hash.addOptional(objcopy.format);
165 man.hash.add(objcopy.compress_debug);
166 man.hash.add(objcopy.strip);
167 man.hash.add(objcopy.output_file_debug != null);
168
169 if (try step.cacheHit(&man)) {
170 // Cache hit, skip subprocess execution.
171 const digest = man.final();
172 objcopy.output_file.path = try b.cache_root.join(b.allocator, &.{
173 "o", &digest, objcopy.basename,
174 });
175 if (objcopy.output_file_debug) |*file| {
176 file.path = try b.cache_root.join(b.allocator, &.{
177 "o", &digest, b.fmt("{s}.debug", .{objcopy.basename}),
178 });
179 }
180 return;
181 }
182
183 const digest = man.final();
184 const cache_path = "o" ++ fs.path.sep_str ++ digest;
185 const full_dest_path = try b.cache_root.join(b.allocator, &.{ cache_path, objcopy.basename });
186 const full_dest_path_debug = try b.cache_root.join(b.allocator, &.{ cache_path, b.fmt("{s}.debug", .{objcopy.basename}) });
187 b.cache_root.handle.createDirPath(io, cache_path) catch |err| {
188 return step.fail("unable to make path {s}: {s}", .{ cache_path, @errorName(err) });
189 };
190
191 var argv = std.array_list.Managed([]const u8).init(b.allocator);
192 try argv.appendSlice(&.{ b.graph.zig_exe, "objcopy" });
193
194 if (objcopy.only_section) |only_section| {
195 try argv.appendSlice(&.{ "-j", only_section });
196 }
197 switch (objcopy.strip) {
198 .none => {},
199 .debug => try argv.appendSlice(&.{"--strip-debug"}),
200 .debug_and_symbols => try argv.appendSlice(&.{"--strip-all"}),
201 }
202 if (objcopy.pad_to) |pad_to| {
203 try argv.appendSlice(&.{ "--pad-to", b.fmt("{d}", .{pad_to}) });
204 }
205 if (objcopy.format) |format| switch (format) {
206 .bin => try argv.appendSlice(&.{ "-O", "binary" }),
207 .hex => try argv.appendSlice(&.{ "-O", "hex" }),
208 .elf => try argv.appendSlice(&.{ "-O", "elf" }),
209 };
210 if (objcopy.compress_debug) {
211 try argv.appendSlice(&.{"--compress-debug-sections"});
212 }
213 if (objcopy.output_file_debug != null) {
214 try argv.appendSlice(&.{b.fmt("--extract-to={s}", .{full_dest_path_debug})});
215 }
216 if (objcopy.add_section) |section| {
217 try argv.append("--add-section");
218 try argv.appendSlice(&.{b.fmt("{s}={s}", .{ section.section_name, section.file_path.getPath2(b, step) })});
219 }
220 if (objcopy.set_section_alignment) |set_align| {
221 try argv.append("--set-section-alignment");
222 try argv.appendSlice(&.{b.fmt("{s}={d}", .{ set_align.section_name, set_align.alignment })});
223 }
224 if (objcopy.set_section_flags) |set_flags| {
225 const f = set_flags.flags;
226 // trailing comma is allowed
227 try argv.append("--set-section-flags");
228 try argv.appendSlice(&.{b.fmt("{s}={s}{s}{s}{s}{s}{s}{s}{s}{s}", .{
229 set_flags.section_name,
230 if (f.alloc) "alloc," else "",
231 if (f.contents) "contents," else "",
232 if (f.load) "load," else "",
233 if (f.readonly) "readonly," else "",
234 if (f.code) "code," else "",
235 if (f.exclude) "exclude," else "",
236 if (f.large) "large," else "",
237 if (f.merge) "merge," else "",
238 if (f.strings) "strings," else "",
239 })});
240 }
241
242 try argv.appendSlice(&.{ full_src_path, full_dest_path });
243
244 try argv.append("--listen=-");
245 _ = try step.evalZigProcess(argv.items, prog_node, false, options.web_server, options.gpa);
246
247 objcopy.output_file.path = full_dest_path;
248 if (objcopy.output_file_debug) |*file| file.path = full_dest_path_debug;
249 try man.writeManifest();
131pub fn getOutputSeparatedDebug(obj_copy: *const ObjCopy) ?std.Build.LazyPath {
132 return if (obj_copy.output_file_debug.unwrap()) |index| .{ .generated = .{ .index = index } } else null;
250133}
lib/std/Build/Step/Run.zig+2-2
......@@ -421,7 +421,7 @@ pub fn addPrefixedOutputDirectoryArg(
421421 output.* = .{
422422 .prefix = graph.dupeString(prefix),
423423 .basename = graph.dupeString(basename),
424 .generated_file = .{ .step = &run.step },
424 .generated_file = graph.addGeneratedFile(&run.step),
425425 };
426426 run.argv.append(arena, .{ .output_directory = output }) catch @panic("OOM");
427427
......@@ -429,7 +429,7 @@ pub fn addPrefixedOutputDirectoryArg(
429429 run.setName(std.fmt.allocPrint(arena, "{s} ({s})", .{ run.step.name, basename }) catch @panic("OOM"));
430430 }
431431
432 return .{ .generated = .{ .file = &output.generated_file } };
432 return .{ .generated = .{ .index = output.generated_file } };
433433}
434434
435435pub fn addDirectoryArg(run: *Run, lazy_directory: std.Build.LazyPath) void {
lib/std/Build/Step/TranslateC.zig+1-1
......@@ -31,7 +31,7 @@ pub fn create(owner: *std.Build, options: Options) *TranslateC {
3131 const graph = owner.graph;
3232 const arena = graph.arena;
3333 const translate_c = arena.create(TranslateC) catch @panic("OOM");
34 const source = options.root_source_file.dupe(owner);
34 const source = options.root_source_file.dupe(graph);
3535 translate_c.* = .{
3636 .step = Step.init(.{
3737 .tag = base_tag,
lib/std/Build/Step/UpdateSourceFiles.zig+1-48
......@@ -29,11 +29,10 @@ pub const Contents = union(enum) {
2929pub fn create(owner: *std.Build) *UpdateSourceFiles {
3030 const usf = owner.allocator.create(UpdateSourceFiles) catch @panic("OOM");
3131 usf.* = .{
32 .step = Step.init(.{
32 .step = .init(.{
3333 .tag = base_tag,
3434 .name = "UpdateSourceFiles",
3535 .owner = owner,
36 .makeFn = make,
3736 }),
3837 .output_source_files = .empty,
3938 };
......@@ -68,49 +67,3 @@ pub fn addBytesToSource(usf: *UpdateSourceFiles, bytes: []const u8, sub_path: []
6867 .sub_path = sub_path,
6968 }) catch @panic("OOM");
7069}
71
72fn make(step: *Step, options: Step.MakeOptions) !void {
73 _ = options;
74 const b = step.owner;
75 const io = b.graph.io;
76 const usf: *UpdateSourceFiles = @fieldParentPtr("step", step);
77
78 var any_miss = false;
79 for (usf.output_source_files.items) |output_source_file| {
80 if (fs.path.dirname(output_source_file.sub_path)) |dirname| {
81 b.build_root.handle.createDirPath(io, dirname) catch |err| {
82 return step.fail("unable to make path '{f}{s}': {t}", .{ b.build_root, dirname, err });
83 };
84 }
85 switch (output_source_file.contents) {
86 .bytes => |bytes| {
87 b.build_root.handle.writeFile(io, .{ .sub_path = output_source_file.sub_path, .data = bytes }) catch |err| {
88 return step.fail("unable to write file '{f}{s}': {t}", .{
89 b.build_root, output_source_file.sub_path, err,
90 });
91 };
92 any_miss = true;
93 },
94 .copy => |file_source| {
95 if (!step.inputs.populated()) try step.addWatchInput(file_source);
96
97 const source_path = file_source.getPath2(b, step);
98 const prev_status = Io.Dir.updateFile(
99 .cwd(),
100 io,
101 source_path,
102 b.build_root.handle,
103 output_source_file.sub_path,
104 .{},
105 ) catch |err| {
106 return step.fail("unable to update file from '{s}' to '{f}{s}': {t}", .{
107 source_path, b.build_root, output_source_file.sub_path, err,
108 });
109 };
110 any_miss = any_miss or prev_status == .stale;
111 },
112 }
113 }
114
115 step.result_cached = !any_miss;
116}