| author | |
| committer | |
| log | 205af5b14828d64c10f5c67e05cebf32b882c646 |
| tree | a76c48fca7b7458f41c4dca14f9ec9eb30325818 |
| parent | 51d7c14ce1bdadc4405474cfb3945581c198c741 |
| parent | ff9798eb265b02d572ecbced675efcd7c763aea9 |
Closes #7013
Closes #68175 files changed, 100 insertions(+), 31 deletions(-)
lib/std/build.zig+7-4| ... | @@ -1216,7 +1216,7 @@ pub const LibExeObjStep = struct { | ... | @@ -1216,7 +1216,7 @@ pub const LibExeObjStep = struct { |
| 1216 | emit_bin: bool = true, | 1216 | emit_bin: bool = true, |
| 1217 | emit_docs: bool = false, | 1217 | emit_docs: bool = false, |
| 1218 | emit_h: bool = false, | 1218 | emit_h: bool = false, |
| 1219 | bundle_compiler_rt: bool, | 1219 | bundle_compiler_rt: ?bool = null, |
| 1220 | disable_stack_probing: bool, | 1220 | disable_stack_probing: bool, |
| 1221 | disable_sanitize_c: bool, | 1221 | disable_sanitize_c: bool, |
| 1222 | rdynamic: bool, | 1222 | rdynamic: bool, |
| ... | @@ -1395,7 +1395,6 @@ pub const LibExeObjStep = struct { | ... | @@ -1395,7 +1395,6 @@ pub const LibExeObjStep = struct { |
| 1395 | .exec_cmd_args = null, | 1395 | .exec_cmd_args = null, |
| 1396 | .name_prefix = "", | 1396 | .name_prefix = "", |
| 1397 | .filter = null, | 1397 | .filter = null, |
| 1398 | .bundle_compiler_rt = false, | ||
| 1399 | .disable_stack_probing = false, | 1398 | .disable_stack_probing = false, |
| 1400 | .disable_sanitize_c = false, | 1399 | .disable_sanitize_c = false, |
| 1401 | .rdynamic = false, | 1400 | .rdynamic = false, |
| ... | @@ -2120,8 +2119,12 @@ pub const LibExeObjStep = struct { | ... | @@ -2120,8 +2119,12 @@ pub const LibExeObjStep = struct { |
| 2120 | if (self.is_dynamic) { | 2119 | if (self.is_dynamic) { |
| 2121 | try zig_args.append("-dynamic"); | 2120 | try zig_args.append("-dynamic"); |
| 2122 | } | 2121 | } |
| 2123 | if (self.bundle_compiler_rt) { | 2122 | if (self.bundle_compiler_rt) |x| { |
| 2124 | try zig_args.append("--bundle-compiler-rt"); | 2123 | if (x) { |
| 2124 | try zig_args.append("-fcompiler-rt"); | ||
| 2125 | } else { | ||
| 2126 | try zig_args.append("-fno-compiler-rt"); | ||
| 2127 | } | ||
| 2125 | } | 2128 | } |
| 2126 | if (self.disable_stack_probing) { | 2129 | if (self.disable_stack_probing) { |
| 2127 | try zig_args.append("-fno-stack-check"); | 2130 | try zig_args.append("-fno-stack-check"); |
src/Compilation.zig+57-20| ... | @@ -93,6 +93,9 @@ libc_static_lib: ?CRTFile = null, | ... | @@ -93,6 +93,9 @@ libc_static_lib: ?CRTFile = null, |
| 93 | /// Populated when we build the libcompiler_rt static library. A Job to build this is placed in the queue | 93 | /// Populated when we build the libcompiler_rt static library. A Job to build this is placed in the queue |
| 94 | /// and resolved before calling linker.flush(). | 94 | /// and resolved before calling linker.flush(). |
| 95 | compiler_rt_static_lib: ?CRTFile = null, | 95 | compiler_rt_static_lib: ?CRTFile = null, |
| 96 | /// Populated when we build the compiler_rt_obj object. A Job to build this is placed in the queue | ||
| 97 | /// and resolved before calling linker.flush(). | ||
| 98 | compiler_rt_obj: ?CRTFile = null, | ||
| 96 | 99 | ||
| 97 | glibc_so_files: ?glibc.BuiltSharedObjects = null, | 100 | glibc_so_files: ?glibc.BuiltSharedObjects = null, |
| 98 | 101 | ||
| ... | @@ -164,8 +167,8 @@ const Job = union(enum) { | ... | @@ -164,8 +167,8 @@ const Job = union(enum) { |
| 164 | libcxx: void, | 167 | libcxx: void, |
| 165 | libcxxabi: void, | 168 | libcxxabi: void, |
| 166 | libssp: void, | 169 | libssp: void, |
| 167 | /// needed when producing a dynamic library or executable | 170 | compiler_rt_lib: void, |
| 168 | libcompiler_rt: void, | 171 | compiler_rt_obj: void, |
| 169 | /// needed when not linking libc and using LLVM for code generation because it generates | 172 | /// needed when not linking libc and using LLVM for code generation because it generates |
| 170 | /// calls to, for example, memcpy and memset. | 173 | /// calls to, for example, memcpy and memset. |
| 171 | zig_libc: void, | 174 | zig_libc: void, |
| ... | @@ -350,6 +353,7 @@ pub const InitOptions = struct { | ... | @@ -350,6 +353,7 @@ pub const InitOptions = struct { |
| 350 | want_sanitize_c: ?bool = null, | 353 | want_sanitize_c: ?bool = null, |
| 351 | want_stack_check: ?bool = null, | 354 | want_stack_check: ?bool = null, |
| 352 | want_valgrind: ?bool = null, | 355 | want_valgrind: ?bool = null, |
| 356 | want_compiler_rt: ?bool = null, | ||
| 353 | use_llvm: ?bool = null, | 357 | use_llvm: ?bool = null, |
| 354 | use_lld: ?bool = null, | 358 | use_lld: ?bool = null, |
| 355 | use_clang: ?bool = null, | 359 | use_clang: ?bool = null, |
| ... | @@ -409,6 +413,9 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { | ... | @@ -409,6 +413,9 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 409 | .Lib => is_dyn_lib, | 413 | .Lib => is_dyn_lib, |
| 410 | .Exe => true, | 414 | .Exe => true, |
| 411 | }; | 415 | }; |
| 416 | const needs_c_symbols = !options.is_compiler_rt_or_libc and | ||
| 417 | (is_exe_or_dyn_lib or (options.target.isWasm() and options.output_mode != .Obj)); | ||
| 418 | |||
| 412 | const comp: *Compilation = comp: { | 419 | const comp: *Compilation = comp: { |
| 413 | // For allocations that have the same lifetime as Compilation. This arena is used only during this | 420 | // For allocations that have the same lifetime as Compilation. This arena is used only during this |
| 414 | // initialization and then is freed in deinit(). | 421 | // initialization and then is freed in deinit(). |
| ... | @@ -585,6 +592,8 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { | ... | @@ -585,6 +592,8 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 585 | break :b options.want_valgrind orelse (options.optimize_mode == .Debug); | 592 | break :b options.want_valgrind orelse (options.optimize_mode == .Debug); |
| 586 | }; | 593 | }; |
| 587 | 594 | ||
| 595 | const include_compiler_rt = options.want_compiler_rt orelse needs_c_symbols; | ||
| 596 | |||
| 588 | const single_threaded = options.single_threaded or target_util.isSingleThreaded(options.target); | 597 | const single_threaded = options.single_threaded or target_util.isSingleThreaded(options.target); |
| 589 | 598 | ||
| 590 | const llvm_cpu_features: ?[*:0]const u8 = if (build_options.have_llvm and use_llvm) blk: { | 599 | const llvm_cpu_features: ?[*:0]const u8 = if (build_options.have_llvm and use_llvm) blk: { |
| ... | @@ -821,6 +830,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { | ... | @@ -821,6 +830,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 821 | .z_defs = options.linker_z_defs, | 830 | .z_defs = options.linker_z_defs, |
| 822 | .stack_size_override = options.stack_size_override, | 831 | .stack_size_override = options.stack_size_override, |
| 823 | .image_base_override = options.image_base_override, | 832 | .image_base_override = options.image_base_override, |
| 833 | .include_compiler_rt = include_compiler_rt, | ||
| 824 | .linker_script = options.linker_script, | 834 | .linker_script = options.linker_script, |
| 825 | .version_script = options.version_script, | 835 | .version_script = options.version_script, |
| 826 | .gc_sections = options.linker_gc_sections, | 836 | .gc_sections = options.linker_gc_sections, |
| ... | @@ -967,16 +977,31 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { | ... | @@ -967,16 +977,31 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 967 | try comp.work_queue.writeItem(.libcxxabi); | 977 | try comp.work_queue.writeItem(.libcxxabi); |
| 968 | } | 978 | } |
| 969 | 979 | ||
| 970 | const needs_compiler_rt_and_c = is_exe_or_dyn_lib or | 980 | // The `is_stage1` condition is here only because stage2 cannot yet build compiler-rt. |
| 971 | (comp.getTarget().isWasm() and comp.bin_file.options.output_mode != .Obj); | 981 | // Once it is capable this condition should be removed. |
| 972 | if (needs_compiler_rt_and_c and build_options.is_stage1) { | 982 | if (build_options.is_stage1) { |
| 973 | try comp.work_queue.writeItem(.{ .libcompiler_rt = {} }); | 983 | if (comp.bin_file.options.include_compiler_rt) { |
| 974 | // MinGW provides no libssp, use our own implementation. | 984 | if (is_exe_or_dyn_lib) { |
| 975 | if (comp.getTarget().isMinGW()) { | 985 | try comp.work_queue.writeItem(.{ .compiler_rt_lib = {} }); |
| 976 | try comp.work_queue.writeItem(.{ .libssp = {} }); | 986 | } else { |
| 987 | try comp.work_queue.writeItem(.{ .compiler_rt_obj = {} }); | ||
| 988 | if (comp.bin_file.options.object_format != .elf) { | ||
| 989 | // For ELF we can rely on using -r to link multiple objects together into one, | ||
| 990 | // but to truly support `build-obj -fcompiler-rt` will require virtually | ||
| 991 | // injecting `_ = @import("compiler_rt.zig")` into the root source file of | ||
| 992 | // the compilation. | ||
| 993 | fatal("Embedding compiler-rt into non-ELF objects is not yet implemented.", .{}); | ||
| 994 | } | ||
| 995 | } | ||
| 977 | } | 996 | } |
| 978 | if (!comp.bin_file.options.link_libc) { | 997 | if (needs_c_symbols) { |
| 979 | try comp.work_queue.writeItem(.{ .zig_libc = {} }); | 998 | // MinGW provides no libssp, use our own implementation. |
| 999 | if (comp.getTarget().isMinGW()) { | ||
| 1000 | try comp.work_queue.writeItem(.{ .libssp = {} }); | ||
| 1001 | } | ||
| 1002 | if (!comp.bin_file.options.link_libc) { | ||
| 1003 | try comp.work_queue.writeItem(.{ .zig_libc = {} }); | ||
| 1004 | } | ||
| 980 | } | 1005 | } |
| 981 | } | 1006 | } |
| 982 | } | 1007 | } |
| ... | @@ -1374,20 +1399,26 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor | ... | @@ -1374,20 +1399,26 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor |
| 1374 | fatal("unable to build libcxxabi: {}", .{@errorName(err)}); | 1399 | fatal("unable to build libcxxabi: {}", .{@errorName(err)}); |
| 1375 | }; | 1400 | }; |
| 1376 | }, | 1401 | }, |
| 1377 | .libcompiler_rt => { | 1402 | .compiler_rt_lib => { |
| 1378 | self.buildStaticLibFromZig("compiler_rt.zig", &self.compiler_rt_static_lib) catch |err| { | 1403 | self.buildOutputFromZig("compiler_rt.zig", .Lib, &self.compiler_rt_static_lib) catch |err| { |
| 1379 | // TODO Expose this as a normal compile error rather than crashing here. | 1404 | // TODO Expose this as a normal compile error rather than crashing here. |
| 1380 | fatal("unable to build compiler_rt: {}", .{@errorName(err)}); | 1405 | fatal("unable to build compiler_rt: {s}", .{@errorName(err)}); |
| 1406 | }; | ||
| 1407 | }, | ||
| 1408 | .compiler_rt_obj => { | ||
| 1409 | self.buildOutputFromZig("compiler_rt.zig", .Obj, &self.compiler_rt_obj) catch |err| { | ||
| 1410 | // TODO Expose this as a normal compile error rather than crashing here. | ||
| 1411 | fatal("unable to build compiler_rt: {s}", .{@errorName(err)}); | ||
| 1381 | }; | 1412 | }; |
| 1382 | }, | 1413 | }, |
| 1383 | .libssp => { | 1414 | .libssp => { |
| 1384 | self.buildStaticLibFromZig("ssp.zig", &self.libssp_static_lib) catch |err| { | 1415 | self.buildOutputFromZig("ssp.zig", .Lib, &self.libssp_static_lib) catch |err| { |
| 1385 | // TODO Expose this as a normal compile error rather than crashing here. | 1416 | // TODO Expose this as a normal compile error rather than crashing here. |
| 1386 | fatal("unable to build libssp: {}", .{@errorName(err)}); | 1417 | fatal("unable to build libssp: {}", .{@errorName(err)}); |
| 1387 | }; | 1418 | }; |
| 1388 | }, | 1419 | }, |
| 1389 | .zig_libc => { | 1420 | .zig_libc => { |
| 1390 | self.buildStaticLibFromZig("c.zig", &self.libc_static_lib) catch |err| { | 1421 | self.buildOutputFromZig("c.zig", .Lib, &self.libc_static_lib) catch |err| { |
| 1391 | // TODO Expose this as a normal compile error rather than crashing here. | 1422 | // TODO Expose this as a normal compile error rather than crashing here. |
| 1392 | fatal("unable to build zig's multitarget libc: {}", .{@errorName(err)}); | 1423 | fatal("unable to build zig's multitarget libc: {}", .{@errorName(err)}); |
| 1393 | }; | 1424 | }; |
| ... | @@ -2551,10 +2582,16 @@ pub fn updateSubCompilation(sub_compilation: *Compilation) !void { | ... | @@ -2551,10 +2582,16 @@ pub fn updateSubCompilation(sub_compilation: *Compilation) !void { |
| 2551 | } | 2582 | } |
| 2552 | } | 2583 | } |
| 2553 | 2584 | ||
| 2554 | fn buildStaticLibFromZig(comp: *Compilation, src_basename: []const u8, out: *?CRTFile) !void { | 2585 | fn buildOutputFromZig( |
| 2586 | comp: *Compilation, | ||
| 2587 | src_basename: []const u8, | ||
| 2588 | output_mode: std.builtin.OutputMode, | ||
| 2589 | out: *?CRTFile, | ||
| 2590 | ) !void { | ||
| 2555 | const tracy = trace(@src()); | 2591 | const tracy = trace(@src()); |
| 2556 | defer tracy.end(); | 2592 | defer tracy.end(); |
| 2557 | 2593 | ||
| 2594 | std.debug.assert(output_mode != .Exe); | ||
| 2558 | const special_sub = "std" ++ std.fs.path.sep_str ++ "special"; | 2595 | const special_sub = "std" ++ std.fs.path.sep_str ++ "special"; |
| 2559 | const special_path = try comp.zig_lib_directory.join(comp.gpa, &[_][]const u8{special_sub}); | 2596 | const special_path = try comp.zig_lib_directory.join(comp.gpa, &[_][]const u8{special_sub}); |
| 2560 | defer comp.gpa.free(special_path); | 2597 | defer comp.gpa.free(special_path); |
| ... | @@ -2571,11 +2608,11 @@ fn buildStaticLibFromZig(comp: *Compilation, src_basename: []const u8, out: *?CR | ... | @@ -2571,11 +2608,11 @@ fn buildStaticLibFromZig(comp: *Compilation, src_basename: []const u8, out: *?CR |
| 2571 | }; | 2608 | }; |
| 2572 | const root_name = mem.split(src_basename, ".").next().?; | 2609 | const root_name = mem.split(src_basename, ".").next().?; |
| 2573 | const target = comp.getTarget(); | 2610 | const target = comp.getTarget(); |
| 2574 | const output_mode: std.builtin.OutputMode = if (target.cpu.arch.isWasm()) .Obj else .Lib; | 2611 | const fixed_output_mode = if (target.cpu.arch.isWasm()) .Obj else output_mode; |
| 2575 | const bin_basename = try std.zig.binNameAlloc(comp.gpa, .{ | 2612 | const bin_basename = try std.zig.binNameAlloc(comp.gpa, .{ |
| 2576 | .root_name = root_name, | 2613 | .root_name = root_name, |
| 2577 | .target = target, | 2614 | .target = target, |
| 2578 | .output_mode = output_mode, | 2615 | .output_mode = fixed_output_mode, |
| 2579 | }); | 2616 | }); |
| 2580 | defer comp.gpa.free(bin_basename); | 2617 | defer comp.gpa.free(bin_basename); |
| 2581 | 2618 | ||
| ... | @@ -2598,7 +2635,7 @@ fn buildStaticLibFromZig(comp: *Compilation, src_basename: []const u8, out: *?CR | ... | @@ -2598,7 +2635,7 @@ fn buildStaticLibFromZig(comp: *Compilation, src_basename: []const u8, out: *?CR |
| 2598 | .target = target, | 2635 | .target = target, |
| 2599 | .root_name = root_name, | 2636 | .root_name = root_name, |
| 2600 | .root_pkg = &root_pkg, | 2637 | .root_pkg = &root_pkg, |
| 2601 | .output_mode = output_mode, | 2638 | .output_mode = fixed_output_mode, |
| 2602 | .rand = comp.rand, | 2639 | .rand = comp.rand, |
| 2603 | .libc_installation = comp.bin_file.options.libc_installation, | 2640 | .libc_installation = comp.bin_file.options.libc_installation, |
| 2604 | .emit_bin = emit_bin, | 2641 | .emit_bin = emit_bin, |
src/link.zig+11-1| ... | @@ -46,6 +46,7 @@ pub const Options = struct { | ... | @@ -46,6 +46,7 @@ pub const Options = struct { |
| 46 | entry_addr: ?u64 = null, | 46 | entry_addr: ?u64 = null, |
| 47 | stack_size_override: ?u64, | 47 | stack_size_override: ?u64, |
| 48 | image_base_override: ?u64, | 48 | image_base_override: ?u64, |
| 49 | include_compiler_rt: bool, | ||
| 49 | /// Set to `true` to omit debug info. | 50 | /// Set to `true` to omit debug info. |
| 50 | strip: bool, | 51 | strip: bool, |
| 51 | /// If this is true then this link code is responsible for outputting an object | 52 | /// If this is true then this link code is responsible for outputting an object |
| ... | @@ -473,6 +474,11 @@ pub const File = struct { | ... | @@ -473,6 +474,11 @@ pub const File = struct { |
| 473 | break :blk full_obj_path; | 474 | break :blk full_obj_path; |
| 474 | } else null; | 475 | } else null; |
| 475 | 476 | ||
| 477 | const compiler_rt_path: ?[]const u8 = if (base.options.include_compiler_rt) | ||
| 478 | comp.compiler_rt_obj.?.full_object_path | ||
| 479 | else | ||
| 480 | null; | ||
| 481 | |||
| 476 | // This function follows the same pattern as link.Elf.linkWithLLD so if you want some | 482 | // This function follows the same pattern as link.Elf.linkWithLLD so if you want some |
| 477 | // insight as to what's going on here you can read that function body which is more | 483 | // insight as to what's going on here you can read that function body which is more |
| 478 | // well-commented. | 484 | // well-commented. |
| ... | @@ -489,6 +495,7 @@ pub const File = struct { | ... | @@ -489,6 +495,7 @@ pub const File = struct { |
| 489 | _ = try ch.addFile(entry.key.status.success.object_path, null); | 495 | _ = try ch.addFile(entry.key.status.success.object_path, null); |
| 490 | } | 496 | } |
| 491 | try ch.addOptionalFile(module_obj_path); | 497 | try ch.addOptionalFile(module_obj_path); |
| 498 | try ch.addOptionalFile(compiler_rt_path); | ||
| 492 | 499 | ||
| 493 | // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock. | 500 | // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock. |
| 494 | _ = try ch.hit(); | 501 | _ = try ch.hit(); |
| ... | @@ -518,7 +525,7 @@ pub const File = struct { | ... | @@ -518,7 +525,7 @@ pub const File = struct { |
| 518 | var object_files = std.ArrayList([*:0]const u8).init(base.allocator); | 525 | var object_files = std.ArrayList([*:0]const u8).init(base.allocator); |
| 519 | defer object_files.deinit(); | 526 | defer object_files.deinit(); |
| 520 | 527 | ||
| 521 | try object_files.ensureCapacity(base.options.objects.len + comp.c_object_table.items().len + 1); | 528 | try object_files.ensureCapacity(base.options.objects.len + comp.c_object_table.items().len + 2); |
| 522 | for (base.options.objects) |obj_path| { | 529 | for (base.options.objects) |obj_path| { |
| 523 | object_files.appendAssumeCapacity(try arena.dupeZ(u8, obj_path)); | 530 | object_files.appendAssumeCapacity(try arena.dupeZ(u8, obj_path)); |
| 524 | } | 531 | } |
| ... | @@ -528,6 +535,9 @@ pub const File = struct { | ... | @@ -528,6 +535,9 @@ pub const File = struct { |
| 528 | if (module_obj_path) |p| { | 535 | if (module_obj_path) |p| { |
| 529 | object_files.appendAssumeCapacity(try arena.dupeZ(u8, p)); | 536 | object_files.appendAssumeCapacity(try arena.dupeZ(u8, p)); |
| 530 | } | 537 | } |
| 538 | if (compiler_rt_path) |p| { | ||
| 539 | object_files.appendAssumeCapacity(try arena.dupeZ(u8, p)); | ||
| 540 | } | ||
| 531 | 541 | ||
| 532 | const full_out_path = try directory.join(arena, &[_][]const u8{base.options.emit.?.sub_path}); | 542 | const full_out_path = try directory.join(arena, &[_][]const u8{base.options.emit.?.sub_path}); |
| 533 | const full_out_path_z = try arena.dupeZ(u8, full_out_path); | 543 | const full_out_path_z = try arena.dupeZ(u8, full_out_path); |
src/link/Elf.zig+17-6| ... | @@ -1260,6 +1260,13 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { | ... | @@ -1260,6 +1260,13 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1260 | const gc_sections = self.base.options.gc_sections orelse !is_obj; | 1260 | const gc_sections = self.base.options.gc_sections orelse !is_obj; |
| 1261 | const stack_size = self.base.options.stack_size_override orelse 16777216; | 1261 | const stack_size = self.base.options.stack_size_override orelse 16777216; |
| 1262 | const allow_shlib_undefined = self.base.options.allow_shlib_undefined orelse !self.base.options.is_native_os; | 1262 | const allow_shlib_undefined = self.base.options.allow_shlib_undefined orelse !self.base.options.is_native_os; |
| 1263 | const compiler_rt_path: ?[]const u8 = if (self.base.options.include_compiler_rt) blk: { | ||
| 1264 | if (is_exe_or_dyn_lib) { | ||
| 1265 | break :blk comp.compiler_rt_static_lib.?.full_object_path; | ||
| 1266 | } else { | ||
| 1267 | break :blk comp.compiler_rt_obj.?.full_object_path; | ||
| 1268 | } | ||
| 1269 | } else null; | ||
| 1263 | 1270 | ||
| 1264 | // Here we want to determine whether we can save time by not invoking LLD when the | 1271 | // Here we want to determine whether we can save time by not invoking LLD when the |
| 1265 | // output is unchanged. None of the linker options or the object files that are being | 1272 | // 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 { | ... | @@ -1289,6 +1296,8 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1289 | _ = try man.addFile(entry.key.status.success.object_path, null); | 1296 | _ = try man.addFile(entry.key.status.success.object_path, null); |
| 1290 | } | 1297 | } |
| 1291 | try man.addOptionalFile(module_obj_path); | 1298 | try man.addOptionalFile(module_obj_path); |
| 1299 | try man.addOptionalFile(compiler_rt_path); | ||
| 1300 | |||
| 1292 | // We can skip hashing libc and libc++ components that we are in charge of building from Zig | 1301 | // We can skip hashing libc and libc++ components that we are in charge of building from Zig |
| 1293 | // installation sources because they are always a product of the compiler version + target information. | 1302 | // installation sources because they are always a product of the compiler version + target information. |
| 1294 | man.hash.add(stack_size); | 1303 | man.hash.add(stack_size); |
| ... | @@ -1531,12 +1540,14 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { | ... | @@ -1531,12 +1540,14 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1531 | try argv.append(p); | 1540 | try argv.append(p); |
| 1532 | } | 1541 | } |
| 1533 | 1542 | ||
| 1534 | // compiler-rt and libc | 1543 | // libc |
| 1535 | if (is_exe_or_dyn_lib and !self.base.options.is_compiler_rt_or_libc) { | 1544 | if (is_exe_or_dyn_lib and !self.base.options.is_compiler_rt_or_libc and !self.base.options.link_libc) { |
| 1536 | if (!self.base.options.link_libc) { | 1545 | try argv.append(comp.libc_static_lib.?.full_object_path); |
| 1537 | try argv.append(comp.libc_static_lib.?.full_object_path); | 1546 | } |
| 1538 | } | 1547 | |
| 1539 | try argv.append(comp.compiler_rt_static_lib.?.full_object_path); | 1548 | // compiler-rt |
| 1549 | if (compiler_rt_path) |p| { | ||
| 1550 | try argv.append(p); | ||
| 1540 | } | 1551 | } |
| 1541 | 1552 | ||
| 1542 | // Shared libraries. | 1553 | // Shared libraries. |
src/main.zig+8| ... | @@ -314,6 +314,8 @@ const usage_build_generic = | ... | @@ -314,6 +314,8 @@ const usage_build_generic = |
| 314 | \\ -fno-soname (Linux) Disable emitting a SONAME | 314 | \\ -fno-soname (Linux) Disable emitting a SONAME |
| 315 | \\ -fLLD Force using LLD as the linker | 315 | \\ -fLLD Force using LLD as the linker |
| 316 | \\ -fno-LLD Prevent using LLD as the linker | 316 | \\ -fno-LLD Prevent using LLD as the linker |
| 317 | \\ -fcompiler-rt Always include compiler-rt symbols in output | ||
| 318 | \\ -fno-compiler-rt Prevent including compiler-rt symbols in output | ||
| 317 | \\ -rdynamic Add all symbols to the dynamic symbol table | 319 | \\ -rdynamic Add all symbols to the dynamic symbol table |
| 318 | \\ -rpath [path] Add directory to the runtime library search path | 320 | \\ -rpath [path] Add directory to the runtime library search path |
| 319 | \\ -feach-lib-rpath Ensure adding rpath for each used dynamic library | 321 | \\ -feach-lib-rpath Ensure adding rpath for each used dynamic library |
| ... | @@ -478,6 +480,7 @@ fn buildOutputType( | ... | @@ -478,6 +480,7 @@ fn buildOutputType( |
| 478 | var want_sanitize_c: ?bool = null; | 480 | var want_sanitize_c: ?bool = null; |
| 479 | var want_stack_check: ?bool = null; | 481 | var want_stack_check: ?bool = null; |
| 480 | var want_valgrind: ?bool = null; | 482 | var want_valgrind: ?bool = null; |
| 483 | var want_compiler_rt: ?bool = null; | ||
| 481 | var rdynamic: bool = false; | 484 | var rdynamic: bool = false; |
| 482 | var linker_script: ?[]const u8 = null; | 485 | var linker_script: ?[]const u8 = null; |
| 483 | var version_script: ?[]const u8 = null; | 486 | var version_script: ?[]const u8 = null; |
| ... | @@ -794,6 +797,10 @@ fn buildOutputType( | ... | @@ -794,6 +797,10 @@ fn buildOutputType( |
| 794 | if (i + 1 >= args.len) fatal("expected parameter after {}", .{arg}); | 797 | if (i + 1 >= args.len) fatal("expected parameter after {}", .{arg}); |
| 795 | i += 1; | 798 | i += 1; |
| 796 | override_lib_dir = args[i]; | 799 | override_lib_dir = args[i]; |
| 800 | } else if (mem.eql(u8, arg, "-fcompiler-rt")) { | ||
| 801 | want_compiler_rt = true; | ||
| 802 | } else if (mem.eql(u8, arg, "-fno-compiler-rt")) { | ||
| 803 | want_compiler_rt = false; | ||
| 797 | } else if (mem.eql(u8, arg, "-feach-lib-rpath")) { | 804 | } else if (mem.eql(u8, arg, "-feach-lib-rpath")) { |
| 798 | each_lib_rpath = true; | 805 | each_lib_rpath = true; |
| 799 | } else if (mem.eql(u8, arg, "-fno-each-lib-rpath")) { | 806 | } else if (mem.eql(u8, arg, "-fno-each-lib-rpath")) { |
| ... | @@ -1688,6 +1695,7 @@ fn buildOutputType( | ... | @@ -1688,6 +1695,7 @@ fn buildOutputType( |
| 1688 | .want_sanitize_c = want_sanitize_c, | 1695 | .want_sanitize_c = want_sanitize_c, |
| 1689 | .want_stack_check = want_stack_check, | 1696 | .want_stack_check = want_stack_check, |
| 1690 | .want_valgrind = want_valgrind, | 1697 | .want_valgrind = want_valgrind, |
| 1698 | .want_compiler_rt = want_compiler_rt, | ||
| 1691 | .use_llvm = use_llvm, | 1699 | .use_llvm = use_llvm, |
| 1692 | .use_lld = use_lld, | 1700 | .use_lld = use_lld, |
| 1693 | .use_clang = use_clang, | 1701 | .use_clang = use_clang, |