From 2fae28b6afc0e5411c9a9a9def43eeb59fba840f Mon Sep 17 00:00:00 2001 From: Alexandros Naskos Date: Sat, 7 Nov 2020 11:03:13 +0200 Subject: [PATCH 1/2] Added bundle-compiler-rt flag --- src/Compilation.zig | 49 ++++++++++++++++++++++++++++++++++++++------- src/link.zig | 7 ++++++- src/main.zig | 6 ++++++ 3 files changed, 54 insertions(+), 8 deletions(-) diff --git a/src/Compilation.zig b/src/Compilation.zig index a66df1db7b..fe67cf31b7 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -93,6 +93,9 @@ libc_static_lib: ?CRTFile = null, /// Populated when we build the libcompiler_rt static library. A Job to build this is placed in the queue /// and resolved before calling linker.flush(). compiler_rt_static_lib: ?CRTFile = null, +/// Populated when we build the compiler_rt_obj object. A Job to build this is placed in the queue +/// and resolved before calling linker.flush(). +compiler_rt_obj: ?CRTFile = null, glibc_so_files: ?glibc.BuiltSharedObjects = null, @@ -166,6 +169,8 @@ const Job = union(enum) { libssp: void, /// needed when producing a dynamic library or executable libcompiler_rt: void, + /// needed when producing a static library with bundle-compiler-rt + compiler_rt_obj: void, /// needed when not linking libc and using LLVM for code generation because it generates /// calls to, for example, memcpy and memset. zig_libc: void, @@ -387,6 +392,7 @@ pub const InitOptions = struct { parent_compilation_link_libc: bool = false, stack_size_override: ?u64 = null, image_base_override: ?u64 = null, + bundle_compiler_rt: bool = false, self_exe_path: ?[]const u8 = null, version: ?std.builtin.Version = null, libc_installation: ?*const LibCInstallation = null, @@ -404,6 +410,10 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { .Obj, .Exe => false, .Lib => (options.link_mode orelse .Static) == .Dynamic, }; + const is_static_lib = switch (options.output_mode) { + .Obj, .Exe => false, + .Lib => (options.link_mode orelse .Static) == .Static, + }; const is_exe_or_dyn_lib = switch (options.output_mode) { .Obj => false, .Lib => is_dyn_lib, @@ -821,6 +831,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { .z_defs = options.linker_z_defs, .stack_size_override = options.stack_size_override, .image_base_override = options.image_base_override, + .bundle_compiler_rt = options.bundle_compiler_rt, .linker_script = options.linker_script, .version_script = options.version_script, .gc_sections = options.linker_gc_sections, @@ -967,10 +978,18 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { try comp.work_queue.writeItem(.libcxxabi); } - const needs_compiler_rt_and_c = is_exe_or_dyn_lib or + const needs_libc = is_exe_or_dyn_lib or (comp.getTarget().isWasm() and comp.bin_file.options.output_mode != .Obj); - if (needs_compiler_rt_and_c and build_options.is_stage1) { - try comp.work_queue.writeItem(.{ .libcompiler_rt = {} }); + const needs_compiler_rt = options.bundle_compiler_rt or needs_libc; + + if (needs_compiler_rt and build_options.is_stage1) { + if (is_static_lib) { + try comp.work_queue.writeItem(.{ .compiler_rt_obj = {} }); + } else { + try comp.work_queue.writeItem(.{ .libcompiler_rt = {} }); + } + } + if (needs_libc and build_options.is_stage1) { // MinGW provides no libssp, use our own implementation. if (comp.getTarget().isMinGW()) { try comp.work_queue.writeItem(.{ .libssp = {} }); @@ -1380,6 +1399,12 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor fatal("unable to build compiler_rt: {}", .{@errorName(err)}); }; }, + .compiler_rt_obj => { + self.buildOutputFromZig("compiler_rt.zig", .Obj, &self.compiler_rt_obj) catch |err| { + // TODO Expose this as a normal compile error rather than crashing here. + fatal("unable to build compiler_rt: {}", .{@errorName(err)}); + }; + }, .libssp => { self.buildStaticLibFromZig("ssp.zig", &self.libssp_static_lib) catch |err| { // TODO Expose this as a normal compile error rather than crashing here. @@ -2551,10 +2576,16 @@ pub fn updateSubCompilation(sub_compilation: *Compilation) !void { } } -fn buildStaticLibFromZig(comp: *Compilation, src_basename: []const u8, out: *?CRTFile) !void { +fn buildOutputFromZig( + comp: *Compilation, + src_basename: []const u8, + output_mode: std.builtin.OutputMode, + out: *?CRTFile, +) !void { const tracy = trace(@src()); defer tracy.end(); + std.debug.assert(output_mode != .Exe); const special_sub = "std" ++ std.fs.path.sep_str ++ "special"; const special_path = try comp.zig_lib_directory.join(comp.gpa, &[_][]const u8{special_sub}); defer comp.gpa.free(special_path); @@ -2571,11 +2602,11 @@ fn buildStaticLibFromZig(comp: *Compilation, src_basename: []const u8, out: *?CR }; const root_name = mem.split(src_basename, ".").next().?; const target = comp.getTarget(); - const output_mode: std.builtin.OutputMode = if (target.cpu.arch.isWasm()) .Obj else .Lib; + const fixed_output_mode = if (target.cpu.arch.isWasm()) .Obj else output_mode; const bin_basename = try std.zig.binNameAlloc(comp.gpa, .{ .root_name = root_name, .target = target, - .output_mode = output_mode, + .output_mode = fixed_output_mode, }); defer comp.gpa.free(bin_basename); @@ -2598,7 +2629,7 @@ fn buildStaticLibFromZig(comp: *Compilation, src_basename: []const u8, out: *?CR .target = target, .root_name = root_name, .root_pkg = &root_pkg, - .output_mode = output_mode, + .output_mode = fixed_output_mode, .rand = comp.rand, .libc_installation = comp.bin_file.options.libc_installation, .emit_bin = emit_bin, @@ -2639,6 +2670,10 @@ fn buildStaticLibFromZig(comp: *Compilation, src_basename: []const u8, out: *?CR }; } +fn buildStaticLibFromZig(comp: *Compilation, src_basename: []const u8, out: *?CRTFile) !void { + return buildOutputFromZig(comp, src_basename, .Lib, out); +} + fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node) !void { const tracy = trace(@src()); defer tracy.end(); diff --git a/src/link.zig b/src/link.zig index 21022a760a..c24c003073 100644 --- a/src/link.zig +++ b/src/link.zig @@ -46,6 +46,7 @@ pub const Options = struct { entry_addr: ?u64 = null, stack_size_override: ?u64, image_base_override: ?u64, + bundle_compiler_rt: bool, /// Set to `true` to omit debug info. strip: bool, /// If this is true then this link code is responsible for outputting an object @@ -518,7 +519,8 @@ pub const File = struct { var object_files = std.ArrayList([*:0]const u8).init(base.allocator); defer object_files.deinit(); - try object_files.ensureCapacity(base.options.objects.len + comp.c_object_table.items().len + 1); + try object_files.ensureCapacity(base.options.objects.len + comp.c_object_table.items().len + + 1 + @boolToInt(base.options.bundle_compiler_rt)); for (base.options.objects) |obj_path| { object_files.appendAssumeCapacity(try arena.dupeZ(u8, obj_path)); } @@ -528,6 +530,9 @@ pub const File = struct { if (module_obj_path) |p| { object_files.appendAssumeCapacity(try arena.dupeZ(u8, p)); } + if (base.options.bundle_compiler_rt) { + object_files.appendAssumeCapacity(try arena.dupeZ(u8, comp.compiler_rt_obj.?.full_object_path)); + } const full_out_path = try directory.join(arena, &[_][]const u8{base.options.emit.?.sub_path}); const full_out_path_z = try arena.dupeZ(u8, full_out_path); diff --git a/src/main.zig b/src/main.zig index ee36a25220..76e49cde2e 100644 --- a/src/main.zig +++ b/src/main.zig @@ -314,6 +314,8 @@ const usage_build_generic = \\ -fno-soname (Linux) Disable emitting a SONAME \\ -fLLD Force using LLD as the linker \\ -fno-LLD Prevent using LLD as the linker + \\ -fcompiler-rt Always including compiler-rt symbols in output + \\ -fno-compiler-rt Prevent including compiler-rt symbols in output \\ -rdynamic Add all symbols to the dynamic symbol table \\ -rpath [path] Add directory to the runtime library search path \\ -feach-lib-rpath Ensure adding rpath for each used dynamic library @@ -490,6 +492,7 @@ fn buildOutputType( var test_evented_io = false; var stack_size_override: ?u64 = null; var image_base_override: ?u64 = null; + var bundle_compiler_rt = false; var use_llvm: ?bool = null; var use_lld: ?bool = null; var use_clang: ?bool = null; @@ -794,6 +797,8 @@ fn buildOutputType( if (i + 1 >= args.len) fatal("expected parameter after {}", .{arg}); i += 1; override_lib_dir = args[i]; + } else if (mem.eql(u8, arg, "--bundle-compiler-rt")) { + bundle_compiler_rt = true; } else if (mem.eql(u8, arg, "-feach-lib-rpath")) { each_lib_rpath = true; } else if (mem.eql(u8, arg, "-fno-each-lib-rpath")) { @@ -1705,6 +1710,7 @@ fn buildOutputType( .link_emit_relocs = link_emit_relocs, .stack_size_override = stack_size_override, .image_base_override = image_base_override, + .bundle_compiler_rt = bundle_compiler_rt, .strip = strip, .single_threaded = single_threaded, .function_sections = function_sections, From ff9798eb265b02d572ecbced675efcd7c763aea9 Mon Sep 17 00:00:00 2001 From: Andrew Kelley Date: Mon, 30 Nov 2020 16:35:00 -0700 Subject: [PATCH 2/2] rework the bundle compiler-rt feature * it is now -fcompiler-rt and -fno-compiler-rt to override the (quite reasonable) default of bundling compiler-rt only for executables and dynamic libraries. - the build.zig API is still called bundle_compiler_rt however it is now an optional bool instead of a bool. leaving it as `null` means to use the compiler default. * renamed some internal identifiers to make the source more readable * additionally support -fcompiler-rt when doing build-obj for ELF files since that target already supports linking multiple objects into one. - includes an error message when attempting this for non-ELF. in the future this could additionally be supported with a more advanced implementation that does not rely on the linker. * properly populate the linker cache hash --- lib/std/build.zig | 11 ++++--- src/Compilation.zig | 74 +++++++++++++++++++++++---------------------- src/link.zig | 15 ++++++--- src/link/Elf.zig | 23 ++++++++++---- src/main.zig | 12 +++++--- 5 files changed, 79 insertions(+), 56 deletions(-) diff --git a/lib/std/build.zig b/lib/std/build.zig index 69af052e2a..c8439ca20a 100644 --- a/lib/std/build.zig +++ b/lib/std/build.zig @@ -1216,7 +1216,7 @@ pub const LibExeObjStep = struct { emit_bin: bool = true, emit_docs: bool = false, emit_h: bool = false, - bundle_compiler_rt: bool, + bundle_compiler_rt: ?bool = null, disable_stack_probing: bool, disable_sanitize_c: bool, rdynamic: bool, @@ -1395,7 +1395,6 @@ pub const LibExeObjStep = struct { .exec_cmd_args = null, .name_prefix = "", .filter = null, - .bundle_compiler_rt = false, .disable_stack_probing = false, .disable_sanitize_c = false, .rdynamic = false, @@ -2120,8 +2119,12 @@ pub const LibExeObjStep = struct { if (self.is_dynamic) { try zig_args.append("-dynamic"); } - if (self.bundle_compiler_rt) { - try zig_args.append("--bundle-compiler-rt"); + if (self.bundle_compiler_rt) |x| { + if (x) { + try zig_args.append("-fcompiler-rt"); + } else { + try zig_args.append("-fno-compiler-rt"); + } } if (self.disable_stack_probing) { try zig_args.append("-fno-stack-check"); diff --git a/src/Compilation.zig b/src/Compilation.zig index fe67cf31b7..b7660718de 100644 --- a/src/Compilation.zig +++ b/src/Compilation.zig @@ -167,9 +167,7 @@ const Job = union(enum) { libcxx: void, libcxxabi: void, libssp: void, - /// needed when producing a dynamic library or executable - libcompiler_rt: void, - /// needed when producing a static library with bundle-compiler-rt + compiler_rt_lib: void, compiler_rt_obj: void, /// needed when not linking libc and using LLVM for code generation because it generates /// calls to, for example, memcpy and memset. @@ -355,6 +353,7 @@ pub const InitOptions = struct { want_sanitize_c: ?bool = null, want_stack_check: ?bool = null, want_valgrind: ?bool = null, + want_compiler_rt: ?bool = null, use_llvm: ?bool = null, use_lld: ?bool = null, use_clang: ?bool = null, @@ -392,7 +391,6 @@ pub const InitOptions = struct { parent_compilation_link_libc: bool = false, stack_size_override: ?u64 = null, image_base_override: ?u64 = null, - bundle_compiler_rt: bool = false, self_exe_path: ?[]const u8 = null, version: ?std.builtin.Version = null, libc_installation: ?*const LibCInstallation = null, @@ -410,15 +408,14 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { .Obj, .Exe => false, .Lib => (options.link_mode orelse .Static) == .Dynamic, }; - const is_static_lib = switch (options.output_mode) { - .Obj, .Exe => false, - .Lib => (options.link_mode orelse .Static) == .Static, - }; const is_exe_or_dyn_lib = switch (options.output_mode) { .Obj => false, .Lib => is_dyn_lib, .Exe => true, }; + const needs_c_symbols = !options.is_compiler_rt_or_libc and + (is_exe_or_dyn_lib or (options.target.isWasm() and options.output_mode != .Obj)); + const comp: *Compilation = comp: { // For allocations that have the same lifetime as Compilation. This arena is used only during this // initialization and then is freed in deinit(). @@ -595,6 +592,8 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { break :b options.want_valgrind orelse (options.optimize_mode == .Debug); }; + const include_compiler_rt = options.want_compiler_rt orelse needs_c_symbols; + const single_threaded = options.single_threaded or target_util.isSingleThreaded(options.target); const llvm_cpu_features: ?[*:0]const u8 = if (build_options.have_llvm and use_llvm) blk: { @@ -831,7 +830,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { .z_defs = options.linker_z_defs, .stack_size_override = options.stack_size_override, .image_base_override = options.image_base_override, - .bundle_compiler_rt = options.bundle_compiler_rt, + .include_compiler_rt = include_compiler_rt, .linker_script = options.linker_script, .version_script = options.version_script, .gc_sections = options.linker_gc_sections, @@ -978,24 +977,31 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { try comp.work_queue.writeItem(.libcxxabi); } - const needs_libc = is_exe_or_dyn_lib or - (comp.getTarget().isWasm() and comp.bin_file.options.output_mode != .Obj); - const needs_compiler_rt = options.bundle_compiler_rt or needs_libc; - - if (needs_compiler_rt and build_options.is_stage1) { - if (is_static_lib) { - try comp.work_queue.writeItem(.{ .compiler_rt_obj = {} }); - } else { - try comp.work_queue.writeItem(.{ .libcompiler_rt = {} }); + // The `is_stage1` condition is here only because stage2 cannot yet build compiler-rt. + // Once it is capable this condition should be removed. + if (build_options.is_stage1) { + if (comp.bin_file.options.include_compiler_rt) { + if (is_exe_or_dyn_lib) { + try comp.work_queue.writeItem(.{ .compiler_rt_lib = {} }); + } else { + try comp.work_queue.writeItem(.{ .compiler_rt_obj = {} }); + if (comp.bin_file.options.object_format != .elf) { + // For ELF we can rely on using -r to link multiple objects together into one, + // but to truly support `build-obj -fcompiler-rt` will require virtually + // injecting `_ = @import("compiler_rt.zig")` into the root source file of + // the compilation. + fatal("Embedding compiler-rt into non-ELF objects is not yet implemented.", .{}); + } + } } - } - if (needs_libc and build_options.is_stage1) { - // MinGW provides no libssp, use our own implementation. - if (comp.getTarget().isMinGW()) { - try comp.work_queue.writeItem(.{ .libssp = {} }); - } - if (!comp.bin_file.options.link_libc) { - try comp.work_queue.writeItem(.{ .zig_libc = {} }); + if (needs_c_symbols) { + // MinGW provides no libssp, use our own implementation. + if (comp.getTarget().isMinGW()) { + try comp.work_queue.writeItem(.{ .libssp = {} }); + } + if (!comp.bin_file.options.link_libc) { + try comp.work_queue.writeItem(.{ .zig_libc = {} }); + } } } } @@ -1393,26 +1399,26 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor fatal("unable to build libcxxabi: {}", .{@errorName(err)}); }; }, - .libcompiler_rt => { - self.buildStaticLibFromZig("compiler_rt.zig", &self.compiler_rt_static_lib) catch |err| { + .compiler_rt_lib => { + self.buildOutputFromZig("compiler_rt.zig", .Lib, &self.compiler_rt_static_lib) catch |err| { // TODO Expose this as a normal compile error rather than crashing here. - fatal("unable to build compiler_rt: {}", .{@errorName(err)}); + fatal("unable to build compiler_rt: {s}", .{@errorName(err)}); }; }, .compiler_rt_obj => { self.buildOutputFromZig("compiler_rt.zig", .Obj, &self.compiler_rt_obj) catch |err| { // TODO Expose this as a normal compile error rather than crashing here. - fatal("unable to build compiler_rt: {}", .{@errorName(err)}); + fatal("unable to build compiler_rt: {s}", .{@errorName(err)}); }; }, .libssp => { - self.buildStaticLibFromZig("ssp.zig", &self.libssp_static_lib) catch |err| { + self.buildOutputFromZig("ssp.zig", .Lib, &self.libssp_static_lib) catch |err| { // TODO Expose this as a normal compile error rather than crashing here. fatal("unable to build libssp: {}", .{@errorName(err)}); }; }, .zig_libc => { - self.buildStaticLibFromZig("c.zig", &self.libc_static_lib) catch |err| { + self.buildOutputFromZig("c.zig", .Lib, &self.libc_static_lib) catch |err| { // TODO Expose this as a normal compile error rather than crashing here. fatal("unable to build zig's multitarget libc: {}", .{@errorName(err)}); }; @@ -2670,10 +2676,6 @@ fn buildOutputFromZig( }; } -fn buildStaticLibFromZig(comp: *Compilation, src_basename: []const u8, out: *?CRTFile) !void { - return buildOutputFromZig(comp, src_basename, .Lib, out); -} - fn updateStage1Module(comp: *Compilation, main_progress_node: *std.Progress.Node) !void { const tracy = trace(@src()); defer tracy.end(); diff --git a/src/link.zig b/src/link.zig index c24c003073..3df3727fc3 100644 --- a/src/link.zig +++ b/src/link.zig @@ -46,7 +46,7 @@ pub const Options = struct { entry_addr: ?u64 = null, stack_size_override: ?u64, image_base_override: ?u64, - bundle_compiler_rt: bool, + include_compiler_rt: bool, /// Set to `true` to omit debug info. strip: bool, /// If this is true then this link code is responsible for outputting an object @@ -474,6 +474,11 @@ pub const File = struct { break :blk full_obj_path; } else null; + const compiler_rt_path: ?[]const u8 = if (base.options.include_compiler_rt) + comp.compiler_rt_obj.?.full_object_path + else + null; + // This function follows the same pattern as link.Elf.linkWithLLD so if you want some // insight as to what's going on here you can read that function body which is more // well-commented. @@ -490,6 +495,7 @@ pub const File = struct { _ = try ch.addFile(entry.key.status.success.object_path, null); } try ch.addOptionalFile(module_obj_path); + try ch.addOptionalFile(compiler_rt_path); // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock. _ = try ch.hit(); @@ -519,8 +525,7 @@ pub const File = struct { var object_files = std.ArrayList([*:0]const u8).init(base.allocator); defer object_files.deinit(); - try object_files.ensureCapacity(base.options.objects.len + comp.c_object_table.items().len + - 1 + @boolToInt(base.options.bundle_compiler_rt)); + try object_files.ensureCapacity(base.options.objects.len + comp.c_object_table.items().len + 2); for (base.options.objects) |obj_path| { object_files.appendAssumeCapacity(try arena.dupeZ(u8, obj_path)); } @@ -530,8 +535,8 @@ pub const File = struct { if (module_obj_path) |p| { object_files.appendAssumeCapacity(try arena.dupeZ(u8, p)); } - if (base.options.bundle_compiler_rt) { - object_files.appendAssumeCapacity(try arena.dupeZ(u8, comp.compiler_rt_obj.?.full_object_path)); + if (compiler_rt_path) |p| { + object_files.appendAssumeCapacity(try arena.dupeZ(u8, p)); } const full_out_path = try directory.join(arena, &[_][]const u8{base.options.emit.?.sub_path}); diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 82c3df35ea..66542027e1 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -1260,6 +1260,13 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { const gc_sections = self.base.options.gc_sections orelse !is_obj; const stack_size = self.base.options.stack_size_override orelse 16777216; const allow_shlib_undefined = self.base.options.allow_shlib_undefined orelse !self.base.options.is_native_os; + const compiler_rt_path: ?[]const u8 = if (self.base.options.include_compiler_rt) blk: { + if (is_exe_or_dyn_lib) { + break :blk comp.compiler_rt_static_lib.?.full_object_path; + } else { + break :blk comp.compiler_rt_obj.?.full_object_path; + } + } else null; // Here we want to determine whether we can save time by not invoking LLD when the // output is unchanged. None of the linker options or the object files that are being @@ -1289,6 +1296,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { _ = try man.addFile(entry.key.status.success.object_path, null); } try man.addOptionalFile(module_obj_path); + try man.addOptionalFile(compiler_rt_path); + // We can skip hashing libc and libc++ components that we are in charge of building from Zig // installation sources because they are always a product of the compiler version + target information. man.hash.add(stack_size); @@ -1531,12 +1540,14 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { try argv.append(p); } - // compiler-rt and libc - if (is_exe_or_dyn_lib and !self.base.options.is_compiler_rt_or_libc) { - if (!self.base.options.link_libc) { - try argv.append(comp.libc_static_lib.?.full_object_path); - } - try argv.append(comp.compiler_rt_static_lib.?.full_object_path); + // libc + if (is_exe_or_dyn_lib and !self.base.options.is_compiler_rt_or_libc and !self.base.options.link_libc) { + try argv.append(comp.libc_static_lib.?.full_object_path); + } + + // compiler-rt + if (compiler_rt_path) |p| { + try argv.append(p); } // Shared libraries. diff --git a/src/main.zig b/src/main.zig index 76e49cde2e..5e406152d3 100644 --- a/src/main.zig +++ b/src/main.zig @@ -314,7 +314,7 @@ const usage_build_generic = \\ -fno-soname (Linux) Disable emitting a SONAME \\ -fLLD Force using LLD as the linker \\ -fno-LLD Prevent using LLD as the linker - \\ -fcompiler-rt Always including compiler-rt symbols in output + \\ -fcompiler-rt Always include compiler-rt symbols in output \\ -fno-compiler-rt Prevent including compiler-rt symbols in output \\ -rdynamic Add all symbols to the dynamic symbol table \\ -rpath [path] Add directory to the runtime library search path @@ -480,6 +480,7 @@ fn buildOutputType( var want_sanitize_c: ?bool = null; var want_stack_check: ?bool = null; var want_valgrind: ?bool = null; + var want_compiler_rt: ?bool = null; var rdynamic: bool = false; var linker_script: ?[]const u8 = null; var version_script: ?[]const u8 = null; @@ -492,7 +493,6 @@ fn buildOutputType( var test_evented_io = false; var stack_size_override: ?u64 = null; var image_base_override: ?u64 = null; - var bundle_compiler_rt = false; var use_llvm: ?bool = null; var use_lld: ?bool = null; var use_clang: ?bool = null; @@ -797,8 +797,10 @@ fn buildOutputType( if (i + 1 >= args.len) fatal("expected parameter after {}", .{arg}); i += 1; override_lib_dir = args[i]; - } else if (mem.eql(u8, arg, "--bundle-compiler-rt")) { - bundle_compiler_rt = true; + } else if (mem.eql(u8, arg, "-fcompiler-rt")) { + want_compiler_rt = true; + } else if (mem.eql(u8, arg, "-fno-compiler-rt")) { + want_compiler_rt = false; } else if (mem.eql(u8, arg, "-feach-lib-rpath")) { each_lib_rpath = true; } else if (mem.eql(u8, arg, "-fno-each-lib-rpath")) { @@ -1693,6 +1695,7 @@ fn buildOutputType( .want_sanitize_c = want_sanitize_c, .want_stack_check = want_stack_check, .want_valgrind = want_valgrind, + .want_compiler_rt = want_compiler_rt, .use_llvm = use_llvm, .use_lld = use_lld, .use_clang = use_clang, @@ -1710,7 +1713,6 @@ fn buildOutputType( .link_emit_relocs = link_emit_relocs, .stack_size_override = stack_size_override, .image_base_override = image_base_override, - .bundle_compiler_rt = bundle_compiler_rt, .strip = strip, .single_threaded = single_threaded, .function_sections = function_sections,