From caddbbc315e834241c6ae7e22434b574c589e5fc Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Sun, 16 Oct 2022 12:46:39 -0700 Subject: build: avoid compiling self-hosted twice build.zig: add a 'compile' step to compile the self-hosted compiler without installing it. Compilation: set cache mode to whole when using the LLVM backend and --enable-cache is passed. This makes `zig build` act the same as it does with stage1. Upside is that a second invocation of `zig build` on an unmodified source tree will avoid redoing the compilation again. Downside is that it will proliferate more garbage in the project-local cache (same as stage1). This can eventually be fixed when Zig's incremental compilation is more robust; we can go back to having LLVM use CacheMode.incremental and rely on it detecting no changes and avoiding doing the flush() step. --- src/Compilation.zig | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'src/Compilation.zig') diff --git a/src/Compilation.zig b/src/Compilation.zig index 0ff9481875..659cfda9bd 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -1109,11 +1109,6 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { const use_stage1 = options.use_stage1 orelse false; - const cache_mode = if (use_stage1 and !options.disable_lld_caching) - CacheMode.whole - else - options.cache_mode; - // Make a decision on whether to use LLVM or our own backend. const use_llvm = build_options.have_llvm and blk: { if (options.use_llvm) |explicit| @@ -1154,6 +1149,14 @@ pub fn create(gpa: Allocator, options: InitOptions) !*Compilation { } } + // TODO: once we support incremental compilation for the LLVM backend via + // saving the LLVM module into a bitcode file and restoring it, along with + // compiler state, the second clause here can be removed so that incremental + // cache mode is used for LLVM backend too. We need some fuzz testing before + // that can be enabled. + const cache_mode = if ((use_stage1 and !options.disable_lld_caching) or + (use_llvm and !options.disable_lld_caching)) CacheMode.whole else options.cache_mode; + const tsan = options.want_tsan orelse false; // TSAN is implemented in C++ so it requires linking libc++. const link_libcpp = options.link_libcpp or tsan; -- cgit v1.2.3 From cb635e084b0c36e3c7a6bf63f49f7e7e9918532d Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 17 Oct 2022 16:54:52 -0700 Subject: stage2: better handling of CacheMode.whole on Windows Windows gives AccessDenied if you delete a directory which contains open file handles. This could be triggered when using CacheMode.whole when cross compiling macho test binaries. --- src/Compilation.zig | 16 ++++++++++++++-- src/link.zig | 14 ++++++-------- 2 files changed, 20 insertions(+), 10 deletions(-) (limited to 'src/Compilation.zig') diff --git a/src/Compilation.zig b/src/Compilation.zig index 659cfda9bd..52acf1f031 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -2390,9 +2390,21 @@ pub fn update(comp: *Compilation) !void { const o_sub_path = try std.fs.path.join(comp.gpa, &[_][]const u8{ "o", &digest }); defer comp.gpa.free(o_sub_path); + // Work around windows `AccessDenied` if any files within this directory are open + // by doing the makeExecutable/makeWritable dance. + const need_writable_dance = builtin.os.tag == .windows and comp.bin_file.file != null; + if (need_writable_dance) { + try comp.bin_file.makeExecutable(); + } + try comp.bin_file.renameTmpIntoCache(comp.local_cache_directory, tmp_dir_sub_path, o_sub_path); comp.wholeCacheModeSetBinFilePath(&digest); + // Has to be after the `wholeCacheModeSetBinFilePath` above. + if (need_writable_dance) { + try comp.bin_file.makeWritable(); + } + // This is intentionally sandwiched between renameTmpIntoCache() and writeManifest(). if (comp.bin_file.options.module) |module| { // We need to set the zig_cache_artifact_directory for -femit-asm, -femit-llvm-ir, @@ -3207,8 +3219,8 @@ fn processOneJob(comp: *Compilation, job: Job) !void { // TODO Surface more error details. comp.lockAndSetMiscFailure( .mingw_crt_file, - "unable to build mingw-w64 CRT file: {s}", - .{@errorName(err)}, + "unable to build mingw-w64 CRT file {s}: {s}", + .{ @tagName(crt_file), @errorName(err) }, ); }; }, diff --git a/src/link.zig b/src/link.zig index 0b6ffa8bf4..1b5ce2246b 100644 --- a/src/link.zig +++ b/src/link.zig @@ -403,10 +403,8 @@ pub const File = struct { try emit.directory.handle.copyFile(emit.sub_path, emit.directory.handle, emit.sub_path, .{}); } } - if (base.intermediary_basename == null) { - f.close(); - base.file = null; - } + f.close(); + base.file = null; }, .coff, .elf, .plan9, .wasm => if (base.file) |f| { if (base.intermediary_basename != null) { @@ -777,7 +775,7 @@ pub const File = struct { _ = base; while (true) { if (builtin.os.tag == .windows) { - // workaround windows `renameW` can't fail with `PathAlreadyExists` + // Work around windows `renameW` can't fail with `PathAlreadyExists` // See https://github.com/ziglang/zig/issues/8362 if (cache_directory.handle.access(o_sub_path, .{})) |_| { try cache_directory.handle.deleteTree(o_sub_path); @@ -791,9 +789,9 @@ pub const File = struct { tmp_dir_sub_path, cache_directory.handle, o_sub_path, - ) catch |err| switch (err) { - error.AccessDenied => unreachable, // We are most likely trying to move a dir with open handles to its resources - else => |e| return e, + ) catch |err| { + log.err("unable to rename cache dir {s} to {s}: {s}", .{ tmp_dir_sub_path, o_sub_path, @errorName(err) }); + return err; }; break; } else { -- cgit v1.2.3