@@ -19,6 +19,26 @@ code_model: std.builtin.CodeModel,
19
19
omit_frame_pointer : bool ,
20
20
wasi_exec_model : std.builtin.WasiExecModel ,
21
21
22
+ /// Compute an abstract hash representing this `Builtin`. This is *not* a hash
23
+ /// of the resulting file contents.
24
+ pub fn hash (opts : @This ()) [std .Build .Cache .bin_digest_len ]u8 {
25
+ var h : Cache.Hasher = Cache .hasher_init ;
26
+ inline for (@typeInfo (@This ()).@"struct" .fields ) | f | {
27
+ if (comptime std .mem .eql (u8 , f .name , "target" )) {
28
+ // This needs special handling.
29
+ std .hash .autoHash (& h , opts .target .cpu );
30
+ std .hash .autoHash (& h , opts .target .os .tag );
31
+ std .hash .autoHash (& h , opts .target .os .versionRange ());
32
+ std .hash .autoHash (& h , opts .target .abi );
33
+ std .hash .autoHash (& h , opts .target .ofmt );
34
+ std .hash .autoHash (& h , opts .target .dynamic_linker );
35
+ } else {
36
+ std .hash .autoHash (& h , @field (opts , f .name ));
37
+ }
38
+ }
39
+ return h .finalResult ();
40
+ }
41
+
22
42
pub fn generate (opts : @This (), allocator : Allocator ) Allocator .Error ! [:0 ]u8 {
23
43
var buffer = std .ArrayList (u8 ).init (allocator );
24
44
try append (opts , & buffer );
@@ -263,50 +283,66 @@ pub fn append(opts: @This(), buffer: *std.ArrayList(u8)) Allocator.Error!void {
263
283
}
264
284
}
265
285
266
- pub fn populateFile (comp : * Compilation , mod : * Module , file : * File ) ! void {
267
- if (mod .root .statFile (mod .root_src_path )) | stat | {
286
+ /// This essentially takes the place of `Zcu.PerThread.updateFile`, but for 'builtin' modules.
287
+ /// Instead of reading the file from disk, its contents are generated in-memory.
288
+ pub fn populateFile (opts : @This (), gpa : Allocator , file : * File ) Allocator .Error ! void {
289
+ assert (file .is_builtin );
290
+ assert (file .status == .never_loaded );
291
+ assert (file .source == null );
292
+ assert (file .tree == null );
293
+ assert (file .zir == null );
294
+
295
+ file .source = try opts .generate (gpa );
296
+
297
+ log .debug ("parsing and generating 'builtin.zig'" , .{});
298
+
299
+ file .tree = try std .zig .Ast .parse (gpa , file .source .? , .zig );
300
+ assert (file .tree .? .errors .len == 0 ); // builtin.zig must parse
301
+
302
+ file .zir = try AstGen .generate (gpa , file .tree .? );
303
+ assert (! file .zir .? .hasCompileErrors ()); // builtin.zig must not have astgen errors
304
+ file .status = .success ;
305
+ }
306
+
307
+ /// After `populateFile` succeeds, call this function to write the generated file out to disk
308
+ /// if necessary. This is useful for external tooling such as debuggers.
309
+ /// Assumes that `file.mod` is correctly set to the builtin module.
310
+ pub fn updateFileOnDisk (file : * File , comp : * Compilation ) ! void {
311
+ assert (file .is_builtin );
312
+ assert (file .status == .success );
313
+ assert (file .source != null );
314
+
315
+ const root_dir , const sub_path = file .path .openInfo (comp .dirs );
316
+
317
+ if (root_dir .statFile (sub_path )) | stat | {
268
318
if (stat .size != file .source .? .len ) {
269
319
std .log .warn (
270
- "the cached file '{}{s} ' had the wrong size. Expected {d}, found {d}. " ++
320
+ "the cached file '{}' had the wrong size. Expected {d}, found {d}. " ++
271
321
"Overwriting with correct file contents now" ,
272
- .{ mod . root , mod . root_src_path , file .source .? .len , stat .size },
322
+ .{ file . path . fmt ( comp ) , file .source .? .len , stat .size },
273
323
);
274
-
275
- try writeFile (file , mod );
276
324
} else {
277
325
file .stat = .{
278
326
.size = stat .size ,
279
327
.inode = stat .inode ,
280
328
.mtime = stat .mtime ,
281
329
};
330
+ return ;
282
331
}
283
332
} else | err | switch (err ) {
284
- error .BadPathName = > unreachable , // it's always "builtin.zig"
285
- error .NameTooLong = > unreachable , // it's always "builtin.zig"
286
- error .PipeBusy = > unreachable , // it's not a pipe
287
- error .NoDevice = > unreachable , // it's not a pipe
288
- error .WouldBlock = > unreachable , // not asking for non-blocking I/O
333
+ error .FileNotFound = > {},
289
334
290
- error .FileNotFound = > try writeFile (file , mod ),
335
+ error .WouldBlock = > unreachable , // not asking for non-blocking I/O
336
+ error .BadPathName = > unreachable , // it's always "o/digest/builtin.zig"
337
+ error .NameTooLong = > unreachable , // it's always "o/digest/builtin.zig"
291
338
339
+ // We don't expect the file to be a pipe, but can't mark `error.PipeBusy` as `unreachable`,
340
+ // because the user could always replace the file on disk.
292
341
else = > | e | return e ,
293
342
}
294
343
295
- log .debug ("parsing and generating '{s}'" , .{mod .root_src_path });
296
-
297
- file .tree = try std .zig .Ast .parse (comp .gpa , file .source .? , .zig );
298
- assert (file .tree .? .errors .len == 0 ); // builtin.zig must parse
299
-
300
- file .zir = try AstGen .generate (comp .gpa , file .tree .? );
301
- assert (! file .zir .? .hasCompileErrors ()); // builtin.zig must not have astgen errors
302
- file .status = .success ;
303
- // Note that whilst we set `zir` here, we populated `path_digest`
304
- // all the way back in `Package.Module.create`.
305
- }
306
-
307
- fn writeFile (file : * File , mod : * Module ) ! void {
308
- var buf : [std .fs .max_path_bytes ]u8 = undefined ;
309
- var af = try mod .root .atomicFile (mod .root_src_path , .{ .make_path = true }, & buf );
344
+ // `make_path` matters because the dir hasn't actually been created yet.
345
+ var af = try root_dir .atomicFile (sub_path , .{ .make_path = true });
310
346
defer af .deinit ();
311
347
try af .file .writeAll (file .source .? );
312
348
af .finish () catch | err | switch (err ) {
@@ -331,6 +367,7 @@ fn writeFile(file: *File, mod: *Module) !void {
331
367
const builtin = @import ("builtin" );
332
368
const std = @import ("std" );
333
369
const Allocator = std .mem .Allocator ;
370
+ const Cache = std .Build .Cache ;
334
371
const build_options = @import ("build_options" );
335
372
const Module = @import ("Package/Module.zig" );
336
373
const assert = std .debug .assert ;
0 commit comments