| ... | @@ -1,9 +1,3 @@ | ... | @@ -1,9 +1,3 @@ |
| 1 | const std = @import("../std.zig"); | | |
| 2 | const ConfigHeaderStep = @This(); | | |
| 3 | const Step = std.Build.Step; | | |
| 4 | | | |
| 5 | pub const base_id: Step.Id = .config_header; | | |
| 6 | | | |
| 7 | pub const Style = union(enum) { | 1 | pub const Style = union(enum) { |
| 8 | /// The configure format supported by autotools. It uses `#undef foo` to | 2 | /// The configure format supported by autotools. It uses `#undef foo` to |
| 9 | /// mark lines that can be substituted with different values. | 3 | /// mark lines that can be substituted with different values. |
| ... | @@ -41,6 +35,8 @@ style: Style, | ... | @@ -41,6 +35,8 @@ style: Style, |
| 41 | max_bytes: usize, | 35 | max_bytes: usize, |
| 42 | include_path: []const u8, | 36 | include_path: []const u8, |
| 43 | | 37 | |
| | 38 | pub const base_id: Step.Id = .config_header; |
| | 39 | |
| 44 | pub const Options = struct { | 40 | pub const Options = struct { |
| 45 | style: Style = .blank, | 41 | style: Style = .blank, |
| 46 | max_bytes: usize = 2 * 1024 * 1024, | 42 | max_bytes: usize = 2 * 1024 * 1024, |
| ... | @@ -162,23 +158,15 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { | ... | @@ -162,23 +158,15 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 162 | const b = step.owner; | 158 | const b = step.owner; |
| 163 | const self = @fieldParentPtr(ConfigHeaderStep, "step", step); | 159 | const self = @fieldParentPtr(ConfigHeaderStep, "step", step); |
| 164 | const gpa = b.allocator; | 160 | const gpa = b.allocator; |
| | 161 | const arena = b.allocator; |
| 165 | | 162 | |
| 166 | // The cache is used here not really as a way to speed things up - because writing | 163 | var man = b.cache.obtain(); |
| 167 | // the data to a file would probably be very fast - but as a way to find a canonical | 164 | defer man.deinit(); |
| 168 | // location to put build artifacts. | | |
| 169 | | 165 | |
| 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); | | |
| 178 | // Random bytes to make ConfigHeaderStep unique. Refresh this with new | 166 | // Random bytes to make ConfigHeaderStep unique. Refresh this with new |
| 179 | // random bytes when ConfigHeaderStep implementation is modified in a | 167 | // random bytes when ConfigHeaderStep implementation is modified in a |
| 180 | // non-backwards-compatible way. | 168 | // non-backwards-compatible way. |
| 181 | var hash = Hasher.init("PGuDTpidxyMqnkGM"); | 169 | man.hash.add(@as(u32, 0xdef08d23)); |
| 182 | | 170 | |
| 183 | var output = std.ArrayList(u8).init(gpa); | 171 | var output = std.ArrayList(u8).init(gpa); |
| 184 | defer output.deinit(); | 172 | defer output.deinit(); |
| ... | @@ -191,13 +179,13 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { | ... | @@ -191,13 +179,13 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 191 | .autoconf => |file_source| { | 179 | .autoconf => |file_source| { |
| 192 | try output.appendSlice(c_generated_line); | 180 | try output.appendSlice(c_generated_line); |
| 193 | const src_path = file_source.getPath(b); | 181 | 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); |
| 195 | try render_autoconf(step, contents, &output, self.values, src_path); | 183 | try render_autoconf(step, contents, &output, self.values, src_path); |
| 196 | }, | 184 | }, |
| 197 | .cmake => |file_source| { | 185 | .cmake => |file_source| { |
| 198 | try output.appendSlice(c_generated_line); | 186 | try output.appendSlice(c_generated_line); |
| 199 | const src_path = file_source.getPath(b); | 187 | 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); |
| 201 | try render_cmake(step, contents, &output, self.values, src_path); | 189 | try render_cmake(step, contents, &output, self.values, src_path); |
| 202 | }, | 190 | }, |
| 203 | .blank => { | 191 | .blank => { |
| ... | @@ -210,39 +198,40 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { | ... | @@ -210,39 +198,40 @@ fn make(step: *Step, prog_node: *std.Progress.Node) !void { |
| 210 | }, | 198 | }, |
| 211 | } | 199 | } |
| 212 | | 200 | |
| 213 | hash.update(output.items); | 201 | man.hash.addBytes(output.items); |
| 214 | | 202 | |
| 215 | var digest: [16]u8 = undefined; | 203 | if (try step.cacheHit(&man)) { |
| 216 | hash.final(&digest); | 204 | const digest = man.final(); |
| 217 | var hash_basename: [digest.len * 2]u8 = undefined; | 205 | self.output_file.path = try b.cache_root.join(arena, &.{ |
| 218 | _ = std.fmt.bufPrint( | 206 | "o", &digest, self.include_path, |
| 219 | &hash_basename, | 207 | }); |
| 220 | "{s}", | 208 | return; |
| 221 | .{std.fmt.fmtSliceHexLower(&digest)}, | 209 | } |
| 222 | ) catch unreachable; | | |
| 223 | | 210 | |
| 224 | const output_dir = try b.cache_root.join(gpa, &.{ "o", &hash_basename }); | 211 | const digest = man.final(); |
| 225 | | 212 | |
| 226 | // If output_path has directory parts, deal with them. Example: | 213 | // If output_path has directory parts, deal with them. Example: |
| 227 | // output_dir is zig-cache/o/HASH | 214 | // output_dir is zig-cache/o/HASH |
| 228 | // output_path is libavutil/avconfig.h | 215 | // output_path is libavutil/avconfig.h |
| 229 | // We want to open directory zig-cache/o/HASH/libavutil/ | 216 | // We want to open directory zig-cache/o/HASH/libavutil/ |
| 230 | // but keep output_dir as zig-cache/o/HASH for -I include | 217 | // 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| | 218 | const sub_path = try std.fs.path.join(arena, &.{ "o", &digest, self.include_path }); |
| 232 | try std.fs.path.join(gpa, &.{ output_dir, d }) | 219 | const sub_path_dirname = std.fs.path.dirname(sub_path).?; |
| 233 | else | | |
| 234 | output_dir; | | |
| 235 | | 220 | |
| 236 | var dir = std.fs.cwd().makeOpenPath(sub_dir_path, .{}) catch |err| { | 221 | b.cache_root.handle.makePath(sub_path_dirname) catch |err| { |
| 237 | return step.fail("unable to make path '{s}': {s}", .{ output_dir, @errorName(err) }); | 222 | return step.fail("unable to make path '{}{s}': {s}", .{ |
| | 223 | b.cache_root, sub_path_dirname, @errorName(err), |
| | 224 | }); |
| 238 | }; | 225 | }; |
| 239 | defer dir.close(); | | |
| 240 | | 226 | |
| 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 | }; |
| 242 | | 232 | |
| 243 | self.output_file.path = try std.fs.path.join(b.allocator, &.{ | 233 | self.output_file.path = try b.cache_root.join(arena, &.{sub_path}); |
| 244 | output_dir, self.include_path, | 234 | try man.writeManifest(); |
| 245 | }); | | |
| 246 | } | 235 | } |
| 247 | | 236 | |
| 248 | fn render_autoconf( | 237 | fn render_autoconf( |
| ... | @@ -442,3 +431,7 @@ fn renderValueNasm(output: *std.ArrayList(u8), name: []const u8, value: Value) ! | ... | @@ -442,3 +431,7 @@ fn renderValueNasm(output: *std.ArrayList(u8), name: []const u8, value: Value) ! |
| 442 | }, | 431 | }, |
| 443 | } | 432 | } |
| 444 | } | 433 | } |
| | 434 | |
| | 435 | const std = @import("../std.zig"); |
| | 436 | const ConfigHeaderStep = @This(); |
| | 437 | const Step = std.Build.Step; |