diff options
| author | Andrew Kelley <andrew@ziglang.org> | 2020-09-25 18:01:35 -0700 |
|---|---|---|
| committer | Andrew Kelley <andrew@ziglang.org> | 2020-09-25 18:01:35 -0700 |
| commit | 70d7d7e919d7f297e63ca421f6be5925259136e2 (patch) | |
| tree | 1635b864f21a78a8d273fa9a946191a8b9796e8b /src/Compilation.zig | |
| parent | 670e7d456c24a8597af6b3809bf1e9ea68746ade (diff) | |
| download | zig-70d7d7e919d7f297e63ca421f6be5925259136e2.tar.gz zig-70d7d7e919d7f297e63ca421f6be5925259136e2.zip | |
stage2: disable lld caching when output dir is owned by user
Normally when using LLD to link, Zig uses a file named "lld.id" in the
same directory as the output binary which contains the hash of the link
operation, allowing Zig to skip linking when the hash would be unchanged.
In the case that the output binary is being emitted into a directory which
is externally modified - essentially anything other than zig-cache - then
this flag would be set to disable this machinery to avoid false positives.
* Better defaults when using -fno-LLVM
* Fix compiler_rt and libc static libraries were getting a .zig
extension instead of .a extension.
* when using the stage1 backend, put the object file next to the
stage1.id file in the cache directory. this prevents an object file
from polluting the cwd when using zig from the CLI.
Diffstat (limited to 'src/Compilation.zig')
| -rw-r--r-- | src/Compilation.zig | 84 |
1 files changed, 51 insertions, 33 deletions
diff --git a/src/Compilation.zig b/src/Compilation.zig index a522a4173c..c28b27b588 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -3,10 +3,11 @@ const Compilation = @This(); const std = @import("std"); const mem = std.mem; const Allocator = std.mem.Allocator; -const Value = @import("value.zig").Value; const assert = std.debug.assert; const log = std.log.scoped(.compilation); const Target = std.Target; + +const Value = @import("value.zig").Value; const target_util = @import("target.zig"); const Package = @import("Package.zig"); const link = @import("link.zig"); @@ -286,6 +287,13 @@ pub const InitOptions = struct { emit_h: ?EmitLoc = null, link_mode: ?std.builtin.LinkMode = null, dll_export_fns: ?bool = false, + /// Normally when using LLD to link, Zig uses a file named "lld.id" in the + /// same directory as the output binary which contains the hash of the link + /// operation, allowing Zig to skip linking when the hash would be unchanged. + /// In the case that the output binary is being emitted into a directory which + /// is externally modified - essentially anything other than zig-cache - then + /// this flag would be set to disable this machinery to avoid false positives. + disable_lld_caching: bool = false, object_format: ?std.builtin.ObjectFormat = null, optimize_mode: std.builtin.Mode = .Debug, keep_source_files_loaded: bool = false, @@ -371,6 +379,26 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { const ofmt = options.object_format orelse options.target.getObjectFormat(); + // Make a decision on whether to use LLVM or our own backend. + const use_llvm = if (options.use_llvm) |explicit| explicit else blk: { + // If we have no zig code to compile, no need for LLVM. + if (options.root_pkg == null) + break :blk false; + + // If we are the stage1 compiler, we depend on the stage1 c++ llvm backend + // to compile zig code. + if (build_options.is_stage1) + break :blk true; + + // We would want to prefer LLVM for release builds when it is available, however + // we don't have an LLVM backend yet :) + // We would also want to prefer LLVM for architectures that we don't have self-hosted support for too. + break :blk false; + }; + if (!use_llvm and options.machine_code_model != .default) { + return error.MachineCodeModelNotSupported; + } + // Make a decision on whether to use LLD or our own linker. const use_lld = if (options.use_lld) |explicit| explicit else blk: { if (!build_options.have_llvm) @@ -393,7 +421,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { break :blk true; } - if (build_options.is_stage1) { + if (use_llvm) { // If stage1 generates an object file, self-hosted linker is not // yet sophisticated enough to handle that. break :blk options.root_pkg != null; @@ -402,25 +430,6 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { break :blk false; }; - // Make a decision on whether to use LLVM or our own backend. - const use_llvm = if (options.use_llvm) |explicit| explicit else blk: { - // If we have no zig code to compile, no need for LLVM. - if (options.root_pkg == null) - break :blk false; - - // If we are the stage1 compiler, we depend on the stage1 c++ llvm backend - // to compile zig code. - if (build_options.is_stage1) - break :blk true; - - // We would want to prefer LLVM for release builds when it is available, however - // we don't have an LLVM backend yet :) - // We would also want to prefer LLVM for architectures that we don't have self-hosted support for too. - break :blk false; - }; - if (!use_llvm and options.machine_code_model != .default) { - return error.MachineCodeModelNotSupported; - } const link_libc = options.link_libc or (is_exe_or_dyn_lib and target_util.osRequiresLibC(options.target)); @@ -720,6 +729,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { .llvm_cpu_features = llvm_cpu_features, .is_compiler_rt_or_libc = options.is_compiler_rt_or_libc, .each_lib_rpath = options.each_lib_rpath orelse false, + .disable_lld_caching = options.disable_lld_caching, }); errdefer bin_file.destroy(); comp.* = .{ @@ -2288,7 +2298,7 @@ pub fn updateSubCompilation(sub_compilation: *Compilation) !void { } } -fn buildStaticLibFromZig(comp: *Compilation, basename: []const u8, out: *?CRTFile) !void { +fn buildStaticLibFromZig(comp: *Compilation, src_basename: []const u8, out: *?CRTFile) !void { const tracy = trace(@src()); defer tracy.end(); @@ -2304,12 +2314,20 @@ fn buildStaticLibFromZig(comp: *Compilation, basename: []const u8, out: *?CRTFil .path = special_path, .handle = special_dir, }, - .root_src_path = basename, + .root_src_path = src_basename, }; + const root_name = mem.split(src_basename, ".").next().?; + const target = comp.getTarget(); + const bin_basename = try std.zig.binNameAlloc(comp.gpa, .{ + .root_name = root_name, + .target = target, + .output_mode = .Lib, + }); + defer comp.gpa.free(bin_basename); const emit_bin = Compilation.EmitLoc{ .directory = null, // Put it in the cache directory. - .basename = basename, + .basename = bin_basename, }; const optimize_mode: std.builtin.Mode = blk: { if (comp.is_test) @@ -2323,8 +2341,8 @@ fn buildStaticLibFromZig(comp: *Compilation, basename: []const u8, out: *?CRTFil .global_cache_directory = comp.global_cache_directory, .local_cache_directory = comp.global_cache_directory, .zig_lib_directory = comp.zig_lib_directory, - .target = comp.getTarget(), - .root_name = mem.split(basename, ".").next().?, + .target = target, + .root_name = root_name, .root_pkg = &root_pkg, .output_mode = .Lib, .rand = comp.rand, @@ -2358,7 +2376,9 @@ fn buildStaticLibFromZig(comp: *Compilation, basename: []const u8, out: *?CRTFil assert(out.* == null); out.* = Compilation.CRTFile{ - .full_object_path = try sub_compilation.bin_file.options.directory.join(comp.gpa, &[_][]const u8{basename}), + .full_object_path = try sub_compilation.bin_file.options.directory.join(comp.gpa, &[_][]const u8{ + sub_compilation.bin_file.options.sub_path, + }), .lock = sub_compilation.bin_file.toOwnedLock(), }; } @@ -2461,7 +2481,7 @@ fn updateStage1Module(comp: *Compilation) !void { ) orelse return error.OutOfMemory; const stage1_pkg = try createStage1Pkg(arena, "root", mod.root_pkg, null); - const output_dir = comp.bin_file.options.directory.path orelse "."; + const output_dir = directory.path orelse "."; const test_filter = comp.test_filter orelse ""[0..0]; const test_name_prefix = comp.test_name_prefix orelse ""[0..0]; stage1_module.* = .{ @@ -2617,13 +2637,11 @@ pub fn build_crt_file( try sub_compilation.updateSubCompilation(); try comp.crt_files.ensureCapacity(comp.gpa, comp.crt_files.count() + 1); - const artifact_path = if (sub_compilation.bin_file.options.directory.path) |p| - try std.fs.path.join(comp.gpa, &[_][]const u8{ p, basename }) - else - try comp.gpa.dupe(u8, basename); comp.crt_files.putAssumeCapacityNoClobber(basename, .{ - .full_object_path = artifact_path, + .full_object_path = try sub_compilation.bin_file.options.directory.join(comp.gpa, &[_][]const u8{ + sub_compilation.bin_file.options.sub_path, + }), .lock = sub_compilation.bin_file.toOwnedLock(), }); } |
