authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-03-03 17:29:59-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-03-15 10:48:13-07:00
log405bf1b091bd1dba3a2c904c70aa562f41a6b3a3
treebb6c29c2c49af3d7d545d3f7971ad3788ec2e758
parent2cc33f5f4e0b55dcc1fb7cc4fb5d3b565b3a50d2

std.Build.ConfigHeaderStep: integrate with the cache system


2 files changed, 34 insertions(+), 42 deletions(-)

lib/std/Build/ConfigHeaderStep.zig+34-41
......@@ -1,9 +1,3 @@
1const std = @import("../std.zig");
2const ConfigHeaderStep = @This();
3const Step = std.Build.Step;
4
5pub const base_id: Step.Id = .config_header;
6
71pub const Style = union(enum) {
82 /// The configure format supported by autotools. It uses `#undef foo` to
93 /// mark lines that can be substituted with different values.
......@@ -41,6 +35,8 @@ style: Style,
4135max_bytes: usize,
4236include_path: []const u8,
4337
38pub const base_id: Step.Id = .config_header;
39
4440pub const Options = struct {
4541 style: Style = .blank,
4642 max_bytes: usize = 2 * 1024 * 1024,
......@@ -162,23 +158,15 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
162158 const b = step.owner;
163159 const self = @fieldParentPtr(ConfigHeaderStep, "step", step);
164160 const gpa = b.allocator;
161 const arena = b.allocator;
165162
166 // The cache is used here not really as a way to speed things up - because writing
167 // the data to a file would probably be very fast - but as a way to find a canonical
168 // location to put build artifacts.
163 var man = b.cache.obtain();
164 defer man.deinit();
169165
170 // If, for example, a hard-coded path was used as the location to put ConfigHeaderStep
171 // files, then two ConfigHeaderStep executing in parallel might clobber each other.
172
173 // TODO port the cache system from the compiler to zig std lib. Until then
174 // we construct the path directly, and no "cache hit" detection happens;
175 // the files are always written.
176 // Note there is very similar code over in WriteFileStep
177 const Hasher = std.crypto.auth.siphash.SipHash128(1, 3);
178166 // Random bytes to make ConfigHeaderStep unique. Refresh this with new
179167 // random bytes when ConfigHeaderStep implementation is modified in a
180168 // non-backwards-compatible way.
181 var hash = Hasher.init("PGuDTpidxyMqnkGM");
169 man.hash.add(@as(u32, 0xdef08d23));
182170
183171 var output = std.ArrayList(u8).init(gpa);
184172 defer output.deinit();
......@@ -191,13 +179,13 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
191179 .autoconf => |file_source| {
192180 try output.appendSlice(c_generated_line);
193181 const src_path = file_source.getPath(b);
194 const contents = try std.fs.cwd().readFileAlloc(gpa, src_path, self.max_bytes);
182 const contents = try std.fs.cwd().readFileAlloc(arena, src_path, self.max_bytes);
195183 try render_autoconf(step, contents, &output, self.values, src_path);
196184 },
197185 .cmake => |file_source| {
198186 try output.appendSlice(c_generated_line);
199187 const src_path = file_source.getPath(b);
200 const contents = try std.fs.cwd().readFileAlloc(gpa, src_path, self.max_bytes);
188 const contents = try std.fs.cwd().readFileAlloc(arena, src_path, self.max_bytes);
201189 try render_cmake(step, contents, &output, self.values, src_path);
202190 },
203191 .blank => {
......@@ -210,39 +198,40 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
210198 },
211199 }
212200
213 hash.update(output.items);
201 man.hash.addBytes(output.items);
214202
215 var digest: [16]u8 = undefined;
216 hash.final(&digest);
217 var hash_basename: [digest.len * 2]u8 = undefined;
218 _ = std.fmt.bufPrint(
219 &hash_basename,
220 "{s}",
221 .{std.fmt.fmtSliceHexLower(&digest)},
222 ) catch unreachable;
203 if (try step.cacheHit(&man)) {
204 const digest = man.final();
205 self.output_file.path = try b.cache_root.join(arena, &.{
206 "o", &digest, self.include_path,
207 });
208 return;
209 }
223210
224 const output_dir = try b.cache_root.join(gpa, &.{ "o", &hash_basename });
211 const digest = man.final();
225212
226213 // If output_path has directory parts, deal with them. Example:
227214 // output_dir is zig-cache/o/HASH
228215 // output_path is libavutil/avconfig.h
229216 // We want to open directory zig-cache/o/HASH/libavutil/
230217 // but keep output_dir as zig-cache/o/HASH for -I include
231 const sub_dir_path = if (std.fs.path.dirname(self.include_path)) |d|
232 try std.fs.path.join(gpa, &.{ output_dir, d })
233 else
234 output_dir;
218 const sub_path = try std.fs.path.join(arena, &.{ "o", &digest, self.include_path });
219 const sub_path_dirname = std.fs.path.dirname(sub_path).?;
235220
236 var dir = std.fs.cwd().makeOpenPath(sub_dir_path, .{}) catch |err| {
237 return step.fail("unable to make path '{s}': {s}", .{ output_dir, @errorName(err) });
221 b.cache_root.handle.makePath(sub_path_dirname) catch |err| {
222 return step.fail("unable to make path '{}{s}': {s}", .{
223 b.cache_root, sub_path_dirname, @errorName(err),
224 });
238225 };
239 defer dir.close();
240226
241 try dir.writeFile(std.fs.path.basename(self.include_path), output.items);
227 b.cache_root.handle.writeFile(sub_path, output.items) catch |err| {
228 return step.fail("unable to write file '{}{s}': {s}", .{
229 b.cache_root, sub_path, @errorName(err),
230 });
231 };
242232
243 self.output_file.path = try std.fs.path.join(b.allocator, &.{
244 output_dir, self.include_path,
245 });
233 self.output_file.path = try b.cache_root.join(arena, &.{sub_path});
234 try man.writeManifest();
246235}
247236
248237fn render_autoconf(
......@@ -442,3 +431,7 @@ fn renderValueNasm(output: *std.ArrayList(u8), name: []const u8, value: Value) !
442431 },
443432 }
444433}
434
435const std = @import("../std.zig");
436const ConfigHeaderStep = @This();
437const Step = std.Build.Step;
lib/std/Build/WriteFileStep.zig-1
......@@ -187,7 +187,6 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void {
187187 }
188188
189189 if (try step.cacheHit(&man)) {
190 // Cache hit, skip writing file data.
191190 const digest = man.final();
192191 for (wf.files.items) |file| {
193192 file.generated_file.path = try b.cache_root.join(