| author | |
| committer | |
| log | 791e38da8c416b62e4e30f4c9cb44fd6f26442a5 |
| tree | 97bc088985627d86d3315821fc47d7c7ff0e17e5 |
| parent | 1a61a9d4bf37183282de8a09431ed1baaf049999 |
Closes #7013
Closes #68175 files changed, 104 insertions(+), 33 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, |
| ... | @@ -1392,7 +1392,6 @@ pub const LibExeObjStep = struct { | ... | @@ -1392,7 +1392,6 @@ pub const LibExeObjStep = struct { |
| 1392 | .exec_cmd_args = null, | 1392 | .exec_cmd_args = null, |
| 1393 | .name_prefix = "", | 1393 | .name_prefix = "", |
| 1394 | .filter = null, | 1394 | .filter = null, |
| 1395 | .bundle_compiler_rt = false, | ||
| 1396 | .disable_stack_probing = false, | 1395 | .disable_stack_probing = false, |
| 1397 | .disable_sanitize_c = false, | 1396 | .disable_sanitize_c = false, |
| 1398 | .rdynamic = false, | 1397 | .rdynamic = false, |
| ... | @@ -2117,8 +2116,12 @@ pub const LibExeObjStep = struct { | ... | @@ -2117,8 +2116,12 @@ pub const LibExeObjStep = struct { |
| 2117 | if (self.is_dynamic) { | 2116 | if (self.is_dynamic) { |
| 2118 | try zig_args.append("-dynamic"); | 2117 | try zig_args.append("-dynamic"); |
| 2119 | } | 2118 | } |
| 2120 | if (self.bundle_compiler_rt) { | 2119 | if (self.bundle_compiler_rt) |x| { |
| 2121 | try zig_args.append("--bundle-compiler-rt"); | 2120 | if (x) { |
| 2121 | try zig_args.append("-fcompiler-rt"); | ||
| 2122 | } else { | ||
| 2123 | try zig_args.append("-fno-compiler-rt"); | ||
| 2124 | } | ||
| 2122 | } | 2125 | } |
| 2123 | if (self.disable_stack_probing) { | 2126 | if (self.disable_stack_probing) { |
| 2124 | try zig_args.append("-fno-stack-check"); | 2127 | 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, |
| ... | @@ -346,6 +349,7 @@ pub const InitOptions = struct { | ... | @@ -346,6 +349,7 @@ pub const InitOptions = struct { |
| 346 | want_sanitize_c: ?bool = null, | 349 | want_sanitize_c: ?bool = null, |
| 347 | want_stack_check: ?bool = null, | 350 | want_stack_check: ?bool = null, |
| 348 | want_valgrind: ?bool = null, | 351 | want_valgrind: ?bool = null, |
| 352 | want_compiler_rt: ?bool = null, | ||
| 349 | use_llvm: ?bool = null, | 353 | use_llvm: ?bool = null, |
| 350 | use_lld: ?bool = null, | 354 | use_lld: ?bool = null, |
| 351 | use_clang: ?bool = null, | 355 | use_clang: ?bool = null, |
| ... | @@ -405,6 +409,9 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { | ... | @@ -405,6 +409,9 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 405 | .Lib => is_dyn_lib, | 409 | .Lib => is_dyn_lib, |
| 406 | .Exe => true, | 410 | .Exe => true, |
| 407 | }; | 411 | }; |
| 412 | const needs_c_symbols = !options.is_compiler_rt_or_libc and | ||
| 413 | (is_exe_or_dyn_lib or (options.target.isWasm() and options.output_mode != .Obj)); | ||
| 414 | |||
| 408 | const comp: *Compilation = comp: { | 415 | const comp: *Compilation = comp: { |
| 409 | // For allocations that have the same lifetime as Compilation. This arena is used only during this | 416 | // For allocations that have the same lifetime as Compilation. This arena is used only during this |
| 410 | // initialization and then is freed in deinit(). | 417 | // initialization and then is freed in deinit(). |
| ... | @@ -568,6 +575,8 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { | ... | @@ -568,6 +575,8 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 568 | break :b options.want_valgrind orelse (options.optimize_mode == .Debug); | 575 | break :b options.want_valgrind orelse (options.optimize_mode == .Debug); |
| 569 | }; | 576 | }; |
| 570 | 577 | ||
| 578 | const include_compiler_rt = options.want_compiler_rt orelse needs_c_symbols; | ||
| 579 | |||
| 571 | const single_threaded = options.single_threaded or target_util.isSingleThreaded(options.target); | 580 | const single_threaded = options.single_threaded or target_util.isSingleThreaded(options.target); |
| 572 | 581 | ||
| 573 | const llvm_cpu_features: ?[*:0]const u8 = if (build_options.have_llvm and use_llvm) blk: { | 582 | const llvm_cpu_features: ?[*:0]const u8 = if (build_options.have_llvm and use_llvm) blk: { |
| ... | @@ -803,6 +812,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { | ... | @@ -803,6 +812,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 803 | .z_defs = options.linker_z_defs, | 812 | .z_defs = options.linker_z_defs, |
| 804 | .stack_size_override = options.stack_size_override, | 813 | .stack_size_override = options.stack_size_override, |
| 805 | .image_base_override = options.image_base_override, | 814 | .image_base_override = options.image_base_override, |
| 815 | .include_compiler_rt = include_compiler_rt, | ||
| 806 | .linker_script = options.linker_script, | 816 | .linker_script = options.linker_script, |
| 807 | .version_script = options.version_script, | 817 | .version_script = options.version_script, |
| 808 | .gc_sections = options.linker_gc_sections, | 818 | .gc_sections = options.linker_gc_sections, |
| ... | @@ -947,16 +957,31 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { | ... | @@ -947,16 +957,31 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 947 | try comp.work_queue.writeItem(.libcxxabi); | 957 | try comp.work_queue.writeItem(.libcxxabi); |
| 948 | } | 958 | } |
| 949 | 959 | ||
| 950 | const needs_compiler_rt_and_c = is_exe_or_dyn_lib or | 960 | // The `is_stage1` condition is here only because stage2 cannot yet build compiler-rt. |
| 951 | (comp.getTarget().isWasm() and comp.bin_file.options.output_mode != .Obj); | 961 | // Once it is capable this condition should be removed. |
| 952 | if (needs_compiler_rt_and_c and build_options.is_stage1) { | 962 | if (build_options.is_stage1) { |
| 953 | try comp.work_queue.writeItem(.{ .libcompiler_rt = {} }); | 963 | if (comp.bin_file.options.include_compiler_rt) { |
| 954 | // MinGW provides no libssp, use our own implementation. | 964 | if (is_exe_or_dyn_lib) { |
| 955 | if (comp.getTarget().isMinGW()) { | 965 | try comp.work_queue.writeItem(.{ .compiler_rt_lib = {} }); |
| 956 | try comp.work_queue.writeItem(.{ .libssp = {} }); | 966 | } else { |
| 967 | try comp.work_queue.writeItem(.{ .compiler_rt_obj = {} }); | ||
| 968 | if (comp.bin_file.options.object_format != .elf) { | ||
| 969 | // For ELF we can rely on using -r to link multiple objects together into one, | ||
| 970 | // but to truly support `build-obj -fcompiler-rt` will require virtually | ||
| 971 | // injecting `_ = @import("compiler_rt.zig")` into the root source file of | ||
| 972 | // the compilation. | ||
| 973 | fatal("Embedding compiler-rt into non-ELF objects is not yet implemented.", .{}); | ||
| 974 | } | ||
| 975 | } | ||
| 957 | } | 976 | } |
| 958 | if (!comp.bin_file.options.link_libc) { | 977 | if (needs_c_symbols) { |
| 959 | try comp.work_queue.writeItem(.{ .zig_libc = {} }); | 978 | // MinGW provides no libssp, use our own implementation. |
| 979 | if (comp.getTarget().isMinGW()) { | ||
| 980 | try comp.work_queue.writeItem(.{ .libssp = {} }); | ||
| 981 | } | ||
| 982 | if (!comp.bin_file.options.link_libc) { | ||
| 983 | try comp.work_queue.writeItem(.{ .zig_libc = {} }); | ||
| 984 | } | ||
| 960 | } | 985 | } |
| 961 | } | 986 | } |
| 962 | } | 987 | } |
| ... | @@ -1354,20 +1379,26 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor | ... | @@ -1354,20 +1379,26 @@ pub fn performAllTheWork(self: *Compilation) error{ TimerUnsupported, OutOfMemor |
| 1354 | fatal("unable to build libcxxabi: {}", .{@errorName(err)}); | 1379 | fatal("unable to build libcxxabi: {}", .{@errorName(err)}); |
| 1355 | }; | 1380 | }; |
| 1356 | }, | 1381 | }, |
| 1357 | .libcompiler_rt => { | 1382 | .compiler_rt_lib => { |
| 1358 | self.buildStaticLibFromZig("compiler_rt.zig", &self.compiler_rt_static_lib) catch |err| { | 1383 | self.buildOutputFromZig("compiler_rt.zig", .Lib, &self.compiler_rt_static_lib) catch |err| { |
| 1359 | // TODO Expose this as a normal compile error rather than crashing here. | 1384 | // TODO Expose this as a normal compile error rather than crashing here. |
| 1360 | fatal("unable to build compiler_rt: {}", .{@errorName(err)}); | 1385 | fatal("unable to build compiler_rt: {s}", .{@errorName(err)}); |
| 1386 | }; | ||
| 1387 | }, | ||
| 1388 | .compiler_rt_obj => { | ||
| 1389 | self.buildOutputFromZig("compiler_rt.zig", .Obj, &self.compiler_rt_obj) catch |err| { | ||
| 1390 | // TODO Expose this as a normal compile error rather than crashing here. | ||
| 1391 | fatal("unable to build compiler_rt: {s}", .{@errorName(err)}); | ||
| 1361 | }; | 1392 | }; |
| 1362 | }, | 1393 | }, |
| 1363 | .libssp => { | 1394 | .libssp => { |
| 1364 | self.buildStaticLibFromZig("ssp.zig", &self.libssp_static_lib) catch |err| { | 1395 | self.buildOutputFromZig("ssp.zig", .Lib, &self.libssp_static_lib) catch |err| { |
| 1365 | // TODO Expose this as a normal compile error rather than crashing here. | 1396 | // TODO Expose this as a normal compile error rather than crashing here. |
| 1366 | fatal("unable to build libssp: {}", .{@errorName(err)}); | 1397 | fatal("unable to build libssp: {}", .{@errorName(err)}); |
| 1367 | }; | 1398 | }; |
| 1368 | }, | 1399 | }, |
| 1369 | .zig_libc => { | 1400 | .zig_libc => { |
| 1370 | self.buildStaticLibFromZig("c.zig", &self.libc_static_lib) catch |err| { | 1401 | self.buildOutputFromZig("c.zig", .Lib, &self.libc_static_lib) catch |err| { |
| 1371 | // TODO Expose this as a normal compile error rather than crashing here. | 1402 | // TODO Expose this as a normal compile error rather than crashing here. |
| 1372 | fatal("unable to build zig's multitarget libc: {}", .{@errorName(err)}); | 1403 | fatal("unable to build zig's multitarget libc: {}", .{@errorName(err)}); |
| 1373 | }; | 1404 | }; |
| ... | @@ -2531,10 +2562,16 @@ pub fn updateSubCompilation(sub_compilation: *Compilation) !void { | ... | @@ -2531,10 +2562,16 @@ pub fn updateSubCompilation(sub_compilation: *Compilation) !void { |
| 2531 | } | 2562 | } |
| 2532 | } | 2563 | } |
| 2533 | 2564 | ||
| 2534 | fn buildStaticLibFromZig(comp: *Compilation, src_basename: []const u8, out: *?CRTFile) !void { | 2565 | fn buildOutputFromZig( |
| 2566 | comp: *Compilation, | ||
| 2567 | src_basename: []const u8, | ||
| 2568 | output_mode: std.builtin.OutputMode, | ||
| 2569 | out: *?CRTFile, | ||
| 2570 | ) !void { | ||
| 2535 | const tracy = trace(@src()); | 2571 | const tracy = trace(@src()); |
| 2536 | defer tracy.end(); | 2572 | defer tracy.end(); |
| 2537 | 2573 | ||
| 2574 | std.debug.assert(output_mode != .Exe); | ||
| 2538 | const special_sub = "std" ++ std.fs.path.sep_str ++ "special"; | 2575 | const special_sub = "std" ++ std.fs.path.sep_str ++ "special"; |
| 2539 | const special_path = try comp.zig_lib_directory.join(comp.gpa, &[_][]const u8{special_sub}); | 2576 | const special_path = try comp.zig_lib_directory.join(comp.gpa, &[_][]const u8{special_sub}); |
| 2540 | defer comp.gpa.free(special_path); | 2577 | defer comp.gpa.free(special_path); |
| ... | @@ -2551,11 +2588,11 @@ fn buildStaticLibFromZig(comp: *Compilation, src_basename: []const u8, out: *?CR | ... | @@ -2551,11 +2588,11 @@ fn buildStaticLibFromZig(comp: *Compilation, src_basename: []const u8, out: *?CR |
| 2551 | }; | 2588 | }; |
| 2552 | const root_name = mem.split(src_basename, ".").next().?; | 2589 | const root_name = mem.split(src_basename, ".").next().?; |
| 2553 | const target = comp.getTarget(); | 2590 | const target = comp.getTarget(); |
| 2554 | const output_mode: std.builtin.OutputMode = if (target.cpu.arch.isWasm()) .Obj else .Lib; | 2591 | const fixed_output_mode = if (target.cpu.arch.isWasm()) .Obj else output_mode; |
| 2555 | const bin_basename = try std.zig.binNameAlloc(comp.gpa, .{ | 2592 | const bin_basename = try std.zig.binNameAlloc(comp.gpa, .{ |
| 2556 | .root_name = root_name, | 2593 | .root_name = root_name, |
| 2557 | .target = target, | 2594 | .target = target, |
| 2558 | .output_mode = output_mode, | 2595 | .output_mode = fixed_output_mode, |
| 2559 | }); | 2596 | }); |
| 2560 | defer comp.gpa.free(bin_basename); | 2597 | defer comp.gpa.free(bin_basename); |
| 2561 | 2598 | ||
| ... | @@ -2578,7 +2615,7 @@ fn buildStaticLibFromZig(comp: *Compilation, src_basename: []const u8, out: *?CR | ... | @@ -2578,7 +2615,7 @@ fn buildStaticLibFromZig(comp: *Compilation, src_basename: []const u8, out: *?CR |
| 2578 | .target = target, | 2615 | .target = target, |
| 2579 | .root_name = root_name, | 2616 | .root_name = root_name, |
| 2580 | .root_pkg = &root_pkg, | 2617 | .root_pkg = &root_pkg, |
| 2581 | .output_mode = output_mode, | 2618 | .output_mode = fixed_output_mode, |
| 2582 | .rand = comp.rand, | 2619 | .rand = comp.rand, |
| 2583 | .libc_installation = comp.bin_file.options.libc_installation, | 2620 | .libc_installation = comp.bin_file.options.libc_installation, |
| 2584 | .emit_bin = emit_bin, | 2621 | .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 |
| ... | @@ -450,6 +451,11 @@ pub const File = struct { | ... | @@ -450,6 +451,11 @@ pub const File = struct { |
| 450 | break :blk full_obj_path; | 451 | break :blk full_obj_path; |
| 451 | } else null; | 452 | } else null; |
| 452 | 453 | ||
| 454 | const compiler_rt_path: ?[]const u8 = if (base.options.include_compiler_rt) | ||
| 455 | comp.compiler_rt_obj.?.full_object_path | ||
| 456 | else | ||
| 457 | null; | ||
| 458 | |||
| 453 | // This function follows the same pattern as link.Elf.linkWithLLD so if you want some | 459 | // This function follows the same pattern as link.Elf.linkWithLLD so if you want some |
| 454 | // insight as to what's going on here you can read that function body which is more | 460 | // insight as to what's going on here you can read that function body which is more |
| 455 | // well-commented. | 461 | // well-commented. |
| ... | @@ -466,6 +472,7 @@ pub const File = struct { | ... | @@ -466,6 +472,7 @@ pub const File = struct { |
| 466 | _ = try ch.addFile(entry.key.status.success.object_path, null); | 472 | _ = try ch.addFile(entry.key.status.success.object_path, null); |
| 467 | } | 473 | } |
| 468 | try ch.addOptionalFile(module_obj_path); | 474 | try ch.addOptionalFile(module_obj_path); |
| 475 | try ch.addOptionalFile(compiler_rt_path); | ||
| 469 | 476 | ||
| 470 | // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock. | 477 | // We don't actually care whether it's a cache hit or miss; we just need the digest and the lock. |
| 471 | _ = try ch.hit(); | 478 | _ = try ch.hit(); |
| ... | @@ -495,7 +502,7 @@ pub const File = struct { | ... | @@ -495,7 +502,7 @@ pub const File = struct { |
| 495 | var object_files = std.ArrayList([*:0]const u8).init(base.allocator); | 502 | var object_files = std.ArrayList([*:0]const u8).init(base.allocator); |
| 496 | defer object_files.deinit(); | 503 | defer object_files.deinit(); |
| 497 | 504 | ||
| 498 | try object_files.ensureCapacity(base.options.objects.len + comp.c_object_table.items().len + 1); | 505 | try object_files.ensureCapacity(base.options.objects.len + comp.c_object_table.items().len + 2); |
| 499 | for (base.options.objects) |obj_path| { | 506 | for (base.options.objects) |obj_path| { |
| 500 | object_files.appendAssumeCapacity(try arena.dupeZ(u8, obj_path)); | 507 | object_files.appendAssumeCapacity(try arena.dupeZ(u8, obj_path)); |
| 501 | } | 508 | } |
| ... | @@ -505,6 +512,9 @@ pub const File = struct { | ... | @@ -505,6 +512,9 @@ pub const File = struct { |
| 505 | if (module_obj_path) |p| { | 512 | if (module_obj_path) |p| { |
| 506 | object_files.appendAssumeCapacity(try arena.dupeZ(u8, p)); | 513 | object_files.appendAssumeCapacity(try arena.dupeZ(u8, p)); |
| 507 | } | 514 | } |
| 515 | if (compiler_rt_path) |p| { | ||
| 516 | object_files.appendAssumeCapacity(try arena.dupeZ(u8, p)); | ||
| 517 | } | ||
| 508 | 518 | ||
| 509 | const full_out_path = try directory.join(arena, &[_][]const u8{base.options.emit.?.sub_path}); | 519 | const full_out_path = try directory.join(arena, &[_][]const u8{base.options.emit.?.sub_path}); |
| 510 | const full_out_path_z = try arena.dupeZ(u8, full_out_path); | 520 | 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); |
| ... | @@ -1524,12 +1533,14 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { | ... | @@ -1524,12 +1533,14 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1524 | try argv.append(p); | 1533 | try argv.append(p); |
| 1525 | } | 1534 | } |
| 1526 | 1535 | ||
| 1527 | // compiler-rt and libc | 1536 | // libc |
| 1528 | if (is_exe_or_dyn_lib and !self.base.options.is_compiler_rt_or_libc) { | 1537 | if (is_exe_or_dyn_lib and !self.base.options.is_compiler_rt_or_libc and !self.base.options.link_libc) { |
| 1529 | if (!self.base.options.link_libc) { | 1538 | try argv.append(comp.libc_static_lib.?.full_object_path); |
| 1530 | try argv.append(comp.libc_static_lib.?.full_object_path); | 1539 | } |
| 1531 | } | 1540 | |
| 1532 | try argv.append(comp.compiler_rt_static_lib.?.full_object_path); | 1541 | // compiler-rt |
| 1542 | if (compiler_rt_path) |p| { | ||
| 1543 | try argv.append(p); | ||
| 1533 | } | 1544 | } |
| 1534 | 1545 | ||
| 1535 | // Shared libraries. | 1546 | // Shared libraries. |
src/main.zig+12-2| ... | @@ -304,8 +304,12 @@ const usage_build_generic = | ... | @@ -304,8 +304,12 @@ const usage_build_generic = |
| 304 | \\ --version-script [path] Provide a version .map file | 304 | \\ --version-script [path] Provide a version .map file |
| 305 | \\ --dynamic-linker [path] Set the dynamic interpreter path (usually ld.so) | 305 | \\ --dynamic-linker [path] Set the dynamic interpreter path (usually ld.so) |
| 306 | \\ --version [ver] Dynamic library semver | 306 | \\ --version [ver] Dynamic library semver |
| 307 | \\ -fsoname[=name] (linux) Override the default SONAME value | 307 | \\ -fsoname[=name] (Linux) Override the default SONAME value |
| 308 | \\ -fno-soname (linux) Disable emitting a SONAME | 308 | \\ -fno-soname (Linux) Disable emitting a SONAME |
| 309 | \\ -fLLD Force using LLD as the linker | ||
| 310 | \\ -fno-LLD Prevent using LLD as the linker | ||
| 311 | \\ -fcompiler-rt Always include compiler-rt symbols in output | ||
| 312 | \\ -fno-compiler-rt Prevent including compiler-rt symbols in output | ||
| 309 | \\ -rdynamic Add all symbols to the dynamic symbol table | 313 | \\ -rdynamic Add all symbols to the dynamic symbol table |
| 310 | \\ -rpath [path] Add directory to the runtime library search path | 314 | \\ -rpath [path] Add directory to the runtime library search path |
| 311 | \\ -feach-lib-rpath Ensure adding rpath for each used dynamic library | 315 | \\ -feach-lib-rpath Ensure adding rpath for each used dynamic library |
| ... | @@ -469,6 +473,7 @@ fn buildOutputType( | ... | @@ -469,6 +473,7 @@ fn buildOutputType( |
| 469 | var want_sanitize_c: ?bool = null; | 473 | var want_sanitize_c: ?bool = null; |
| 470 | var want_stack_check: ?bool = null; | 474 | var want_stack_check: ?bool = null; |
| 471 | var want_valgrind: ?bool = null; | 475 | var want_valgrind: ?bool = null; |
| 476 | var want_compiler_rt: ?bool = null; | ||
| 472 | var rdynamic: bool = false; | 477 | var rdynamic: bool = false; |
| 473 | var linker_script: ?[]const u8 = null; | 478 | var linker_script: ?[]const u8 = null; |
| 474 | var version_script: ?[]const u8 = null; | 479 | var version_script: ?[]const u8 = null; |
| ... | @@ -785,6 +790,10 @@ fn buildOutputType( | ... | @@ -785,6 +790,10 @@ fn buildOutputType( |
| 785 | if (i + 1 >= args.len) fatal("expected parameter after {}", .{arg}); | 790 | if (i + 1 >= args.len) fatal("expected parameter after {}", .{arg}); |
| 786 | i += 1; | 791 | i += 1; |
| 787 | override_lib_dir = args[i]; | 792 | override_lib_dir = args[i]; |
| 793 | } else if (mem.eql(u8, arg, "-fcompiler-rt")) { | ||
| 794 | want_compiler_rt = true; | ||
| 795 | } else if (mem.eql(u8, arg, "-fno-compiler-rt")) { | ||
| 796 | want_compiler_rt = false; | ||
| 788 | } else if (mem.eql(u8, arg, "-feach-lib-rpath")) { | 797 | } else if (mem.eql(u8, arg, "-feach-lib-rpath")) { |
| 789 | each_lib_rpath = true; | 798 | each_lib_rpath = true; |
| 790 | } else if (mem.eql(u8, arg, "-fno-each-lib-rpath")) { | 799 | } else if (mem.eql(u8, arg, "-fno-each-lib-rpath")) { |
| ... | @@ -1667,6 +1676,7 @@ fn buildOutputType( | ... | @@ -1667,6 +1676,7 @@ fn buildOutputType( |
| 1667 | .want_sanitize_c = want_sanitize_c, | 1676 | .want_sanitize_c = want_sanitize_c, |
| 1668 | .want_stack_check = want_stack_check, | 1677 | .want_stack_check = want_stack_check, |
| 1669 | .want_valgrind = want_valgrind, | 1678 | .want_valgrind = want_valgrind, |
| 1679 | .want_compiler_rt = want_compiler_rt, | ||
| 1670 | .use_llvm = use_llvm, | 1680 | .use_llvm = use_llvm, |
| 1671 | .use_lld = use_lld, | 1681 | .use_lld = use_lld, |
| 1672 | .use_clang = use_clang, | 1682 | .use_clang = use_clang, |