| ... | ... | @@ -93,6 +93,9 @@ libc_static_lib: ?CRTFile = null, |
| 93 | 93 | /// Populated when we build the libcompiler_rt static library. A Job to build this is placed in the queue |
| 94 | 94 | /// and resolved before calling linker.flush(). |
| 95 | 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 | 100 | glibc_so_files: ?glibc.BuiltSharedObjects = null, |
| 98 | 101 | |
| ... | ... | @@ -164,8 +167,8 @@ const Job = union(enum) { |
| 164 | 167 | libcxx: void, |
| 165 | 168 | libcxxabi: void, |
| 166 | 169 | libssp: void, |
| 167 | | /// needed when producing a dynamic library or executable |
| 168 | | libcompiler_rt: void, |
| 170 | compiler_rt_lib: void, |
| 171 | compiler_rt_obj: void, |
| 169 | 172 | /// needed when not linking libc and using LLVM for code generation because it generates |
| 170 | 173 | /// calls to, for example, memcpy and memset. |
| 171 | 174 | zig_libc: void, |
| ... | ... | @@ -350,6 +353,7 @@ pub const InitOptions = struct { |
| 350 | 353 | want_sanitize_c: ?bool = null, |
| 351 | 354 | want_stack_check: ?bool = null, |
| 352 | 355 | want_valgrind: ?bool = null, |
| 356 | want_compiler_rt: ?bool = null, |
| 353 | 357 | use_llvm: ?bool = null, |
| 354 | 358 | use_lld: ?bool = null, |
| 355 | 359 | use_clang: ?bool = null, |
| ... | ... | @@ -409,6 +413,9 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 409 | 413 | .Lib => is_dyn_lib, |
| 410 | 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 | 419 | const comp: *Compilation = comp: { |
| 413 | 420 | // For allocations that have the same lifetime as Compilation. This arena is used only during this |
| 414 | 421 | // initialization and then is freed in deinit(). |
| ... | ... | @@ -585,6 +592,8 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 585 | 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 | 597 | const single_threaded = options.single_threaded or target_util.isSingleThreaded(options.target); |
| 589 | 598 | |
| 590 | 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 | 830 | .z_defs = options.linker_z_defs, |
| 822 | 831 | .stack_size_override = options.stack_size_override, |
| 823 | 832 | .image_base_override = options.image_base_override, |
| 833 | .include_compiler_rt = include_compiler_rt, |
| 824 | 834 | .linker_script = options.linker_script, |
| 825 | 835 | .version_script = options.version_script, |
| 826 | 836 | .gc_sections = options.linker_gc_sections, |
| ... | ... | @@ -967,16 +977,31 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 967 | 977 | try comp.work_queue.writeItem(.libcxxabi); |
| 968 | 978 | } |
| 969 | 979 | |
| 970 | | const needs_compiler_rt_and_c = is_exe_or_dyn_lib or |
| 971 | | (comp.getTarget().isWasm() and comp.bin_file.options.output_mode != .Obj); |
| 972 | | if (needs_compiler_rt_and_c and build_options.is_stage1) { |
| 973 | | try comp.work_queue.writeItem(.{ .libcompiler_rt = {} }); |
| 974 | | // MinGW provides no libssp, use our own implementation. |
| 975 | | if (comp.getTarget().isMinGW()) { |
| 976 | | try comp.work_queue.writeItem(.{ .libssp = {} }); |
| 980 | // The `is_stage1` condition is here only because stage2 cannot yet build compiler-rt. |
| 981 | // Once it is capable this condition should be removed. |
| 982 | if (build_options.is_stage1) { |
| 983 | if (comp.bin_file.options.include_compiler_rt) { |
| 984 | if (is_exe_or_dyn_lib) { |
| 985 | try comp.work_queue.writeItem(.{ .compiler_rt_lib = {} }); |
| 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) { |
| 979 | | try comp.work_queue.writeItem(.{ .zig_libc = {} }); |
| 997 | if (needs_c_symbols) { |
| 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 | 1399 | fatal("unable to build libcxxabi: {}", .{@errorName(err)}); |
| 1375 | 1400 | }; |
| 1376 | 1401 | }, |
| 1377 | | .libcompiler_rt => { |
| 1378 | | self.buildStaticLibFromZig("compiler_rt.zig", &self.compiler_rt_static_lib) catch |err| { |
| 1402 | .compiler_rt_lib => { |
| 1403 | self.buildOutputFromZig("compiler_rt.zig", .Lib, &self.compiler_rt_static_lib) catch |err| { |
| 1379 | 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 | 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 | 1416 | // TODO Expose this as a normal compile error rather than crashing here. |
| 1386 | 1417 | fatal("unable to build libssp: {}", .{@errorName(err)}); |
| 1387 | 1418 | }; |
| 1388 | 1419 | }, |
| 1389 | 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 | 1422 | // TODO Expose this as a normal compile error rather than crashing here. |
| 1392 | 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 | 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 | 2591 | const tracy = trace(@src()); |
| 2556 | 2592 | defer tracy.end(); |
| 2557 | 2593 | |
| 2594 | std.debug.assert(output_mode != .Exe); |
| 2558 | 2595 | const special_sub = "std" ++ std.fs.path.sep_str ++ "special"; |
| 2559 | 2596 | const special_path = try comp.zig_lib_directory.join(comp.gpa, &[_][]const u8{special_sub}); |
| 2560 | 2597 | defer comp.gpa.free(special_path); |
| ... | ... | @@ -2571,11 +2608,11 @@ fn buildStaticLibFromZig(comp: *Compilation, src_basename: []const u8, out: *?CR |
| 2571 | 2608 | }; |
| 2572 | 2609 | const root_name = mem.split(src_basename, ".").next().?; |
| 2573 | 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 | 2612 | const bin_basename = try std.zig.binNameAlloc(comp.gpa, .{ |
| 2576 | 2613 | .root_name = root_name, |
| 2577 | 2614 | .target = target, |
| 2578 | | .output_mode = output_mode, |
| 2615 | .output_mode = fixed_output_mode, |
| 2579 | 2616 | }); |
| 2580 | 2617 | defer comp.gpa.free(bin_basename); |
| 2581 | 2618 | |
| ... | ... | @@ -2598,7 +2635,7 @@ fn buildStaticLibFromZig(comp: *Compilation, src_basename: []const u8, out: *?CR |
| 2598 | 2635 | .target = target, |
| 2599 | 2636 | .root_name = root_name, |
| 2600 | 2637 | .root_pkg = &root_pkg, |
| 2601 | | .output_mode = output_mode, |
| 2638 | .output_mode = fixed_output_mode, |
| 2602 | 2639 | .rand = comp.rand, |
| 2603 | 2640 | .libc_installation = comp.bin_file.options.libc_installation, |
| 2604 | 2641 | .emit_bin = emit_bin, |