| author | |
| committer | |
| log | b08fd0e8fca5ff9ac5531437f5749e74dc009a14 |
| tree | e2fcc2a3a28e1ce90631542745d779c92b9356c0 |
| parent | 64deb46859a11588fb97e8464ec9dae53124b96b |
6 files changed, 426 insertions(+), 76 deletions(-)
BRANCH_TODO+4-2| ... | ... | @@ -1,7 +1,6 @@ |
| 1 | * musl | |
| 1 | * repair @cImport | |
| 2 | 2 | * tests passing with -Dskip-non-native |
| 3 | 3 | * windows CUSTOMBUILD : error : unable to build compiler_rt: FileNotFound [D:\a\1\s\build\zig_install_lib_files.vcxproj] |
| 4 | * repair @cImport | |
| 5 | 4 | * make sure zig cc works |
| 6 | 5 | - using it as a preprocessor (-E) |
| 7 | 6 | - try building some software |
| ... | ... | @@ -20,6 +19,7 @@ |
| 20 | 19 | * WASM LLD linking |
| 21 | 20 | * skip LLD caching when bin directory is not in the cache (so we don't put `id.txt` into the cwd) |
| 22 | 21 | (maybe make it an explicit option and have main.zig disable it) |
| 22 | - make sure that `zig cc -o hello hello.c -target native-native-musl` and `zig build-exe hello.zig -lc -target native-native-musl` will share the same libc build. | |
| 23 | 23 | * audit the CLI options for stage2 |
| 24 | 24 | * audit the base cache hash |
| 25 | 25 | * On operating systems that support it, do an execve for `zig test` and `zig run` rather than child process. |
| ... | ... | @@ -58,3 +58,5 @@ |
| 58 | 58 | * rename std.builtin.Mode to std.builtin.OptimizeMode |
| 59 | 59 | * implement `zig run` and `zig test` when combined with `--watch` |
| 60 | 60 | * close the --pkg-begin --pkg-end Package directory handles |
| 61 | * make std.Progress support multithreaded | |
| 62 | * update musl.zig static data to use native path separator in static data rather than replacing '/' at runtime |
lib/std/zig/system.zig+6| ... | ... | @@ -393,6 +393,12 @@ pub const NativeTargetInfo = struct { |
| 393 | 393 | if (!native_target_has_ld or have_all_info or os_is_non_native) { |
| 394 | 394 | return defaultAbiAndDynamicLinker(cpu, os, cross_target); |
| 395 | 395 | } |
| 396 | if (cross_target.abi) |abi| { | |
| 397 | if (abi.isMusl()) { | |
| 398 | // musl implies static linking. | |
| 399 | return defaultAbiAndDynamicLinker(cpu, os, cross_target); | |
| 400 | } | |
| 401 | } | |
| 396 | 402 | // The current target's ABI cannot be relied on for this. For example, we may build the zig |
| 397 | 403 | // compiler for target riscv64-linux-musl and provide a tarball for users to download. |
| 398 | 404 | // A user could then run that zig compiler on riscv64-linux-gnu. This use case is well-defined |
src/Compilation.zig+106-4| ... | ... | @@ -15,6 +15,7 @@ const liveness = @import("liveness.zig"); |
| 15 | 15 | const build_options = @import("build_options"); |
| 16 | 16 | const LibCInstallation = @import("libc_installation.zig").LibCInstallation; |
| 17 | 17 | const glibc = @import("glibc.zig"); |
| 18 | const musl = @import("musl.zig"); | |
| 18 | 19 | const libunwind = @import("libunwind.zig"); |
| 19 | 20 | const libcxx = @import("libcxx.zig"); |
| 20 | 21 | const fatal = @import("main.zig").fatal; |
| ... | ... | @@ -140,6 +141,8 @@ const Job = union(enum) { |
| 140 | 141 | glibc_crt_file: glibc.CRTFile, |
| 141 | 142 | /// all of the glibc shared objects |
| 142 | 143 | glibc_shared_objects, |
| 144 | /// one of the glibc static objects | |
| 145 | musl_crt_file: musl.CRTFile, | |
| 143 | 146 | /// libunwind.a, usually needed when linking libc |
| 144 | 147 | libunwind: void, |
| 145 | 148 | libcxx: void, |
| ... | ... | @@ -778,6 +781,18 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 778 | 781 | if (comp.wantBuildGLibCFromSource()) { |
| 779 | 782 | try comp.addBuildingGLibCJobs(); |
| 780 | 783 | } |
| 784 | if (comp.wantBuildMuslFromSource()) { | |
| 785 | try comp.work_queue.write(&[_]Job{ | |
| 786 | .{ .musl_crt_file = .crti_o }, | |
| 787 | .{ .musl_crt_file = .crtn_o }, | |
| 788 | .{ .musl_crt_file = .crt1_o }, | |
| 789 | .{ .musl_crt_file = .scrt1_o }, | |
| 790 | .{ .musl_crt_file = .libc_a }, | |
| 791 | }); | |
| 792 | } | |
| 793 | if (comp.wantBuildMinGWW64FromSource()) { | |
| 794 | @panic("TODO"); | |
| 795 | } | |
| 781 | 796 | if (comp.wantBuildLibUnwindFromSource()) { |
| 782 | 797 | try comp.work_queue.writeItem(.{ .libunwind = {} }); |
| 783 | 798 | } |
| ... | ... | @@ -822,6 +837,7 @@ pub fn destroy(self: *Compilation) void { |
| 822 | 837 | { |
| 823 | 838 | var it = self.crt_files.iterator(); |
| 824 | 839 | while (it.next()) |entry| { |
| 840 | gpa.free(entry.key); | |
| 825 | 841 | entry.value.deinit(gpa); |
| 826 | 842 | } |
| 827 | 843 | self.crt_files.deinit(gpa); |
| ... | ... | @@ -1128,6 +1144,12 @@ pub fn performAllTheWork(self: *Compilation) error{OutOfMemory}!void { |
| 1128 | 1144 | fatal("unable to build glibc shared objects: {}", .{@errorName(err)}); |
| 1129 | 1145 | }; |
| 1130 | 1146 | }, |
| 1147 | .musl_crt_file => |crt_file| { | |
| 1148 | musl.buildCRTFile(self, crt_file) catch |err| { | |
| 1149 | // TODO Expose this as a normal compile error rather than crashing here. | |
| 1150 | fatal("unable to build musl CRT file: {}", .{@errorName(err)}); | |
| 1151 | }; | |
| 1152 | }, | |
| 1131 | 1153 | .libunwind => { |
| 1132 | 1154 | libunwind.buildStaticLib(self) catch |err| { |
| 1133 | 1155 | // TODO Expose this as a normal compile error rather than crashing here. |
| ... | ... | @@ -1846,7 +1868,10 @@ fn detectLibCFromLibCInstallation(arena: *Allocator, target: Target, lci: *const |
| 1846 | 1868 | } |
| 1847 | 1869 | |
| 1848 | 1870 | pub fn get_libc_crt_file(comp: *Compilation, arena: *Allocator, basename: []const u8) ![]const u8 { |
| 1849 | if (comp.wantBuildGLibCFromSource()) { | |
| 1871 | if (comp.wantBuildGLibCFromSource() or | |
| 1872 | comp.wantBuildMuslFromSource() or | |
| 1873 | comp.wantBuildMinGWW64FromSource()) | |
| 1874 | { | |
| 1850 | 1875 | return comp.crt_files.get(basename).?.full_object_path; |
| 1851 | 1876 | } |
| 1852 | 1877 | const lci = comp.bin_file.options.libc_installation orelse return error.LibCInstallationNotAvailable; |
| ... | ... | @@ -1865,15 +1890,26 @@ fn addBuildingGLibCJobs(comp: *Compilation) !void { |
| 1865 | 1890 | }); |
| 1866 | 1891 | } |
| 1867 | 1892 | |
| 1868 | fn wantBuildGLibCFromSource(comp: *Compilation) bool { | |
| 1893 | fn wantBuildLibCFromSource(comp: Compilation) bool { | |
| 1869 | 1894 | const is_exe_or_dyn_lib = switch (comp.bin_file.options.output_mode) { |
| 1870 | 1895 | .Obj => false, |
| 1871 | 1896 | .Lib => comp.bin_file.options.link_mode == .Dynamic, |
| 1872 | 1897 | .Exe => true, |
| 1873 | 1898 | }; |
| 1874 | 1899 | return comp.bin_file.options.link_libc and is_exe_or_dyn_lib and |
| 1875 | comp.bin_file.options.libc_installation == null and | |
| 1876 | comp.bin_file.options.target.isGnuLibC(); | |
| 1900 | comp.bin_file.options.libc_installation == null; | |
| 1901 | } | |
| 1902 | ||
| 1903 | fn wantBuildGLibCFromSource(comp: Compilation) bool { | |
| 1904 | return comp.wantBuildLibCFromSource() and comp.getTarget().isGnuLibC(); | |
| 1905 | } | |
| 1906 | ||
| 1907 | fn wantBuildMuslFromSource(comp: Compilation) bool { | |
| 1908 | return comp.wantBuildLibCFromSource() and comp.getTarget().isMusl(); | |
| 1909 | } | |
| 1910 | ||
| 1911 | fn wantBuildMinGWW64FromSource(comp: Compilation) bool { | |
| 1912 | return comp.wantBuildLibCFromSource() and comp.getTarget().isMinGW(); | |
| 1877 | 1913 | } |
| 1878 | 1914 | |
| 1879 | 1915 | fn wantBuildLibUnwindFromSource(comp: *Compilation) bool { |
| ... | ... | @@ -2362,3 +2398,69 @@ fn createStage1Pkg( |
| 2362 | 2398 | }; |
| 2363 | 2399 | return child_pkg; |
| 2364 | 2400 | } |
| 2401 | ||
| 2402 | pub fn build_crt_file( | |
| 2403 | comp: *Compilation, | |
| 2404 | root_name: []const u8, | |
| 2405 | output_mode: std.builtin.OutputMode, | |
| 2406 | c_source_files: []const Compilation.CSourceFile, | |
| 2407 | ) !void { | |
| 2408 | const tracy = trace(@src()); | |
| 2409 | defer tracy.end(); | |
| 2410 | ||
| 2411 | const target = comp.getTarget(); | |
| 2412 | const basename = try std.zig.binNameAlloc(comp.gpa, root_name, target, output_mode, null, null); | |
| 2413 | errdefer comp.gpa.free(basename); | |
| 2414 | ||
| 2415 | // TODO: This is extracted into a local variable to work around a stage1 miscompilation. | |
| 2416 | const emit_bin = Compilation.EmitLoc{ | |
| 2417 | .directory = null, // Put it in the cache directory. | |
| 2418 | .basename = basename, | |
| 2419 | }; | |
| 2420 | const sub_compilation = try Compilation.create(comp.gpa, .{ | |
| 2421 | .local_cache_directory = comp.global_cache_directory, | |
| 2422 | .global_cache_directory = comp.global_cache_directory, | |
| 2423 | .zig_lib_directory = comp.zig_lib_directory, | |
| 2424 | .target = target, | |
| 2425 | .root_name = root_name, | |
| 2426 | .root_pkg = null, | |
| 2427 | .output_mode = output_mode, | |
| 2428 | .rand = comp.rand, | |
| 2429 | .libc_installation = comp.bin_file.options.libc_installation, | |
| 2430 | .emit_bin = emit_bin, | |
| 2431 | .optimize_mode = comp.bin_file.options.optimize_mode, | |
| 2432 | .want_sanitize_c = false, | |
| 2433 | .want_stack_check = false, | |
| 2434 | .want_valgrind = false, | |
| 2435 | .want_pic = comp.bin_file.options.pic, | |
| 2436 | .emit_h = null, | |
| 2437 | .strip = comp.bin_file.options.strip, | |
| 2438 | .is_native_os = comp.bin_file.options.is_native_os, | |
| 2439 | .self_exe_path = comp.self_exe_path, | |
| 2440 | .c_source_files = c_source_files, | |
| 2441 | .verbose_cc = comp.verbose_cc, | |
| 2442 | .verbose_link = comp.bin_file.options.verbose_link, | |
| 2443 | .verbose_tokenize = comp.verbose_tokenize, | |
| 2444 | .verbose_ast = comp.verbose_ast, | |
| 2445 | .verbose_ir = comp.verbose_ir, | |
| 2446 | .verbose_llvm_ir = comp.verbose_llvm_ir, | |
| 2447 | .verbose_cimport = comp.verbose_cimport, | |
| 2448 | .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, | |
| 2449 | .clang_passthrough_mode = comp.clang_passthrough_mode, | |
| 2450 | .is_compiler_rt_or_libc = true, | |
| 2451 | }); | |
| 2452 | defer sub_compilation.destroy(); | |
| 2453 | ||
| 2454 | try sub_compilation.updateSubCompilation(); | |
| 2455 | ||
| 2456 | try comp.crt_files.ensureCapacity(comp.gpa, comp.crt_files.count() + 1); | |
| 2457 | const artifact_path = if (sub_compilation.bin_file.options.directory.path) |p| | |
| 2458 | try std.fs.path.join(comp.gpa, &[_][]const u8{ p, basename }) | |
| 2459 | else | |
| 2460 | try comp.gpa.dupe(u8, basename); | |
| 2461 | ||
| 2462 | comp.crt_files.putAssumeCapacityNoClobber(basename, .{ | |
| 2463 | .full_object_path = artifact_path, | |
| 2464 | .lock = sub_compilation.bin_file.toOwnedLock(), | |
| 2465 | }); | |
| 2466 | } |
src/glibc.zig+4-66| ... | ... | @@ -274,7 +274,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { |
| 274 | 274 | "-g", |
| 275 | 275 | "-Wa,--noexecstack", |
| 276 | 276 | }); |
| 277 | return build_crt_file(comp, "crti.o", .Obj, &[1]Compilation.CSourceFile{ | |
| 277 | return comp.build_crt_file("crti", .Obj, &[1]Compilation.CSourceFile{ | |
| 278 | 278 | .{ |
| 279 | 279 | .src_path = try start_asm_path(comp, arena, "crti.S"), |
| 280 | 280 | .extra_flags = args.items, |
| ... | ... | @@ -292,7 +292,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { |
| 292 | 292 | "-g", |
| 293 | 293 | "-Wa,--noexecstack", |
| 294 | 294 | }); |
| 295 | return build_crt_file(comp, "crtn.o", .Obj, &[1]Compilation.CSourceFile{ | |
| 295 | return comp.build_crt_file("crtn", .Obj, &[1]Compilation.CSourceFile{ | |
| 296 | 296 | .{ |
| 297 | 297 | .src_path = try start_asm_path(comp, arena, "crtn.S"), |
| 298 | 298 | .extra_flags = args.items, |
| ... | ... | @@ -343,7 +343,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { |
| 343 | 343 | .extra_flags = args.items, |
| 344 | 344 | }; |
| 345 | 345 | }; |
| 346 | return build_crt_file(comp, "Scrt1.o", .Obj, &[_]Compilation.CSourceFile{ start_os, abi_note_o }); | |
| 346 | return comp.build_crt_file("Scrt1", .Obj, &[_]Compilation.CSourceFile{ start_os, abi_note_o }); | |
| 347 | 347 | }, |
| 348 | 348 | .libc_nonshared_a => { |
| 349 | 349 | const deps = [_][]const u8{ |
| ... | ... | @@ -433,7 +433,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { |
| 433 | 433 | .extra_flags = args.items, |
| 434 | 434 | }; |
| 435 | 435 | } |
| 436 | return build_crt_file(comp, "libc_nonshared.a", .Lib, &c_source_files); | |
| 436 | return comp.build_crt_file("c_nonshared", .Lib, &c_source_files); | |
| 437 | 437 | }, |
| 438 | 438 | } |
| 439 | 439 | } |
| ... | ... | @@ -676,68 +676,6 @@ fn lib_path(comp: *Compilation, arena: *Allocator, sub_path: []const u8) ![]cons |
| 676 | 676 | return path.join(arena, &[_][]const u8{ comp.zig_lib_directory.path.?, sub_path }); |
| 677 | 677 | } |
| 678 | 678 | |
| 679 | fn build_crt_file( | |
| 680 | comp: *Compilation, | |
| 681 | basename: []const u8, | |
| 682 | output_mode: std.builtin.OutputMode, | |
| 683 | c_source_files: []const Compilation.CSourceFile, | |
| 684 | ) !void { | |
| 685 | const tracy = trace(@src()); | |
| 686 | defer tracy.end(); | |
| 687 | ||
| 688 | // TODO: This is extracted into a local variable to work around a stage1 miscompilation. | |
| 689 | const emit_bin = Compilation.EmitLoc{ | |
| 690 | .directory = null, // Put it in the cache directory. | |
| 691 | .basename = basename, | |
| 692 | }; | |
| 693 | const sub_compilation = try Compilation.create(comp.gpa, .{ | |
| 694 | .local_cache_directory = comp.global_cache_directory, | |
| 695 | .global_cache_directory = comp.global_cache_directory, | |
| 696 | .zig_lib_directory = comp.zig_lib_directory, | |
| 697 | .target = comp.getTarget(), | |
| 698 | .root_name = mem.split(basename, ".").next().?, | |
| 699 | .root_pkg = null, | |
| 700 | .output_mode = output_mode, | |
| 701 | .rand = comp.rand, | |
| 702 | .libc_installation = comp.bin_file.options.libc_installation, | |
| 703 | .emit_bin = emit_bin, | |
| 704 | .optimize_mode = comp.bin_file.options.optimize_mode, | |
| 705 | .want_sanitize_c = false, | |
| 706 | .want_stack_check = false, | |
| 707 | .want_valgrind = false, | |
| 708 | .want_pic = comp.bin_file.options.pic, | |
| 709 | .emit_h = null, | |
| 710 | .strip = comp.bin_file.options.strip, | |
| 711 | .is_native_os = comp.bin_file.options.is_native_os, | |
| 712 | .self_exe_path = comp.self_exe_path, | |
| 713 | .c_source_files = c_source_files, | |
| 714 | .verbose_cc = comp.verbose_cc, | |
| 715 | .verbose_link = comp.bin_file.options.verbose_link, | |
| 716 | .verbose_tokenize = comp.verbose_tokenize, | |
| 717 | .verbose_ast = comp.verbose_ast, | |
| 718 | .verbose_ir = comp.verbose_ir, | |
| 719 | .verbose_llvm_ir = comp.verbose_llvm_ir, | |
| 720 | .verbose_cimport = comp.verbose_cimport, | |
| 721 | .verbose_llvm_cpu_features = comp.verbose_llvm_cpu_features, | |
| 722 | .clang_passthrough_mode = comp.clang_passthrough_mode, | |
| 723 | .is_compiler_rt_or_libc = true, | |
| 724 | }); | |
| 725 | defer sub_compilation.destroy(); | |
| 726 | ||
| 727 | try sub_compilation.updateSubCompilation(); | |
| 728 | ||
| 729 | try comp.crt_files.ensureCapacity(comp.gpa, comp.crt_files.count() + 1); | |
| 730 | const artifact_path = if (sub_compilation.bin_file.options.directory.path) |p| | |
| 731 | try path.join(comp.gpa, &[_][]const u8{ p, basename }) | |
| 732 | else | |
| 733 | try comp.gpa.dupe(u8, basename); | |
| 734 | ||
| 735 | comp.crt_files.putAssumeCapacityNoClobber(basename, .{ | |
| 736 | .full_object_path = artifact_path, | |
| 737 | .lock = sub_compilation.bin_file.toOwnedLock(), | |
| 738 | }); | |
| 739 | } | |
| 740 | ||
| 741 | 679 | pub const BuiltSharedObjects = struct { |
| 742 | 680 | lock: Cache.Lock, |
| 743 | 681 | dir_path: []u8, |
src/link/Elf.zig+1-1| ... | ... | @@ -1548,7 +1548,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1548 | 1548 | try argv.append(try comp.get_libc_crt_file(arena, "libc_nonshared.a")); |
| 1549 | 1549 | } else if (target.isMusl()) { |
| 1550 | 1550 | try argv.append(comp.libunwind_static_lib.?.full_object_path); |
| 1551 | try argv.append(comp.libc_static_lib.?.full_object_path); | |
| 1551 | try argv.append(try comp.get_libc_crt_file(arena, "libc.a")); | |
| 1552 | 1552 | } else if (self.base.options.link_libcpp) { |
| 1553 | 1553 | try argv.append(comp.libunwind_static_lib.?.full_object_path); |
| 1554 | 1554 | } else { |
src/musl.zig+305-3| ... | ... | @@ -1,6 +1,308 @@ |
| 1 | //! TODO build musl libc from source | |
| 1 | const std = @import("std"); | |
| 2 | const Allocator = std.mem.Allocator; | |
| 3 | const mem = std.mem; | |
| 4 | const path = std.fs.path; | |
| 5 | const assert = std.debug.assert; | |
| 2 | 6 | |
| 3 | pub const src_files = [_][]const u8{ | |
| 7 | const target_util = @import("target.zig"); | |
| 8 | const Compilation = @import("Compilation.zig"); | |
| 9 | const build_options = @import("build_options"); | |
| 10 | const trace = @import("tracy.zig").trace; | |
| 11 | const Cache = @import("Cache.zig"); | |
| 12 | const Package = @import("Package.zig"); | |
| 13 | ||
| 14 | pub const CRTFile = enum { | |
| 15 | crti_o, | |
| 16 | crtn_o, | |
| 17 | crt1_o, | |
| 18 | scrt1_o, | |
| 19 | libc_a, | |
| 20 | }; | |
| 21 | ||
| 22 | pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { | |
| 23 | if (!build_options.have_llvm) { | |
| 24 | return error.ZigCompilerNotBuiltWithLLVMExtensions; | |
| 25 | } | |
| 26 | const gpa = comp.gpa; | |
| 27 | var arena_allocator = std.heap.ArenaAllocator.init(gpa); | |
| 28 | defer arena_allocator.deinit(); | |
| 29 | const arena = &arena_allocator.allocator; | |
| 30 | ||
| 31 | switch (crt_file) { | |
| 32 | .crti_o => { | |
| 33 | var args = std.ArrayList([]const u8).init(arena); | |
| 34 | try add_cc_args(comp, arena, &args, false); | |
| 35 | try args.appendSlice(&[_][]const u8{ | |
| 36 | "-Qunused-arguments", | |
| 37 | }); | |
| 38 | return comp.build_crt_file("crti", .Obj, &[1]Compilation.CSourceFile{ | |
| 39 | .{ | |
| 40 | .src_path = try start_asm_path(comp, arena, "crti.s"), | |
| 41 | .extra_flags = args.items, | |
| 42 | }, | |
| 43 | }); | |
| 44 | }, | |
| 45 | .crtn_o => { | |
| 46 | var args = std.ArrayList([]const u8).init(arena); | |
| 47 | try add_cc_args(comp, arena, &args, false); | |
| 48 | try args.appendSlice(&[_][]const u8{ | |
| 49 | "-Qunused-arguments", | |
| 50 | }); | |
| 51 | return comp.build_crt_file("crtn", .Obj, &[1]Compilation.CSourceFile{ | |
| 52 | .{ | |
| 53 | .src_path = try start_asm_path(comp, arena, "crtn.s"), | |
| 54 | .extra_flags = args.items, | |
| 55 | }, | |
| 56 | }); | |
| 57 | }, | |
| 58 | .crt1_o => { | |
| 59 | var args = std.ArrayList([]const u8).init(arena); | |
| 60 | try add_cc_args(comp, arena, &args, false); | |
| 61 | try args.appendSlice(&[_][]const u8{ | |
| 62 | "-fno-stack-protector", | |
| 63 | "-DCRT", | |
| 64 | }); | |
| 65 | return comp.build_crt_file("crt1", .Obj, &[1]Compilation.CSourceFile{ | |
| 66 | .{ | |
| 67 | .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ | |
| 68 | "libc", "musl", "crt", "crt1.c", | |
| 69 | }), | |
| 70 | .extra_flags = args.items, | |
| 71 | }, | |
| 72 | }); | |
| 73 | }, | |
| 74 | .scrt1_o => { | |
| 75 | var args = std.ArrayList([]const u8).init(arena); | |
| 76 | try add_cc_args(comp, arena, &args, false); | |
| 77 | try args.appendSlice(&[_][]const u8{ | |
| 78 | "-fPIC", | |
| 79 | "-fno-stack-protector", | |
| 80 | "-DCRT", | |
| 81 | }); | |
| 82 | return comp.build_crt_file("Scrt1", .Obj, &[1]Compilation.CSourceFile{ | |
| 83 | .{ | |
| 84 | .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ | |
| 85 | "libc", "musl", "crt", "Scrt1.c", | |
| 86 | }), | |
| 87 | .extra_flags = args.items, | |
| 88 | }, | |
| 89 | }); | |
| 90 | }, | |
| 91 | .libc_a => { | |
| 92 | // When there is a src/<arch>/foo.* then it should substitute for src/foo.* | |
| 93 | // Even a .s file can substitute for a .c file. | |
| 94 | const target = comp.getTarget(); | |
| 95 | const arch_name = target_util.archMuslName(target.cpu.arch); | |
| 96 | var source_table = std.StringArrayHashMap(Ext).init(comp.gpa); | |
| 97 | defer source_table.deinit(); | |
| 98 | ||
| 99 | try source_table.ensureCapacity(compat_time32_files.len + src_files.len); | |
| 100 | ||
| 101 | for (src_files) |src_file| { | |
| 102 | try addSrcFile(arena, &source_table, src_file); | |
| 103 | } | |
| 104 | ||
| 105 | const time32_compat_arch_list = [_][]const u8{ "arm", "i386", "mips", "powerpc" }; | |
| 106 | for (time32_compat_arch_list) |time32_compat_arch| { | |
| 107 | if (mem.eql(u8, arch_name, time32_compat_arch)) { | |
| 108 | for (compat_time32_files) |compat_time32_file| { | |
| 109 | try addSrcFile(arena, &source_table, compat_time32_file); | |
| 110 | } | |
| 111 | } | |
| 112 | } | |
| 113 | ||
| 114 | var c_source_files = std.ArrayList(Compilation.CSourceFile).init(comp.gpa); | |
| 115 | defer c_source_files.deinit(); | |
| 116 | ||
| 117 | var override_path = std.ArrayList(u8).init(comp.gpa); | |
| 118 | defer override_path.deinit(); | |
| 119 | ||
| 120 | const s = path.sep_str; | |
| 121 | ||
| 122 | for (source_table.items()) |entry| { | |
| 123 | const src_file = entry.key; | |
| 124 | const ext = entry.value; | |
| 125 | ||
| 126 | const dirname = path.dirname(src_file).?; | |
| 127 | const basename = path.basename(src_file); | |
| 128 | const noextbasename = mem.split(basename, ".").next().?; | |
| 129 | const before_arch_dir = path.dirname(dirname).?; | |
| 130 | const dirbasename = path.basename(dirname); | |
| 131 | ||
| 132 | var is_arch_specific = false; | |
| 133 | // Architecture-specific implementations are under a <arch>/ folder. | |
| 134 | if (is_musl_arch_name(dirbasename)) { | |
| 135 | if (!mem.eql(u8, dirbasename, arch_name)) | |
| 136 | continue; // Not the architecture we're compiling for. | |
| 137 | is_arch_specific = true; | |
| 138 | } | |
| 139 | if (!is_arch_specific) { | |
| 140 | // Look for an arch specific override. | |
| 141 | override_path.shrinkRetainingCapacity(0); | |
| 142 | try override_path.writer().print("{}" ++ s ++ "{}" ++ s ++ "{}.s", .{ | |
| 143 | dirname, arch_name, noextbasename, | |
| 144 | }); | |
| 145 | if (source_table.contains(override_path.items)) | |
| 146 | continue; | |
| 147 | ||
| 148 | override_path.shrinkRetainingCapacity(0); | |
| 149 | try override_path.writer().print("{}" ++ s ++ "{}" ++ s ++ "{}.S", .{ | |
| 150 | dirname, arch_name, noextbasename, | |
| 151 | }); | |
| 152 | if (source_table.contains(override_path.items)) | |
| 153 | continue; | |
| 154 | ||
| 155 | override_path.shrinkRetainingCapacity(0); | |
| 156 | try override_path.writer().print("{}" ++ s ++ "{}" ++ s ++ "{}.c", .{ | |
| 157 | dirname, arch_name, noextbasename, | |
| 158 | }); | |
| 159 | if (source_table.contains(override_path.items)) | |
| 160 | continue; | |
| 161 | } | |
| 162 | ||
| 163 | var args = std.ArrayList([]const u8).init(arena); | |
| 164 | try add_cc_args(comp, arena, &args, ext == .o3); | |
| 165 | try args.appendSlice(&[_][]const u8{ | |
| 166 | "-Qunused-arguments", | |
| 167 | "-w", // disable all warnings | |
| 168 | }); | |
| 169 | const c_source_file = try c_source_files.addOne(); | |
| 170 | c_source_file.* = .{ | |
| 171 | .src_path = try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", src_file }), | |
| 172 | .extra_flags = args.items, | |
| 173 | }; | |
| 174 | } | |
| 175 | return comp.build_crt_file("c", .Lib, c_source_files.items); | |
| 176 | }, | |
| 177 | } | |
| 178 | } | |
| 179 | ||
| 180 | fn is_musl_arch_name(name: []const u8) bool { | |
| 181 | const musl_arch_names = [_][]const u8{ | |
| 182 | "aarch64", | |
| 183 | "arm", | |
| 184 | "generic", | |
| 185 | "i386", | |
| 186 | "m68k", | |
| 187 | "microblaze", | |
| 188 | "mips", | |
| 189 | "mips64", | |
| 190 | "mipsn32", | |
| 191 | "or1k", | |
| 192 | "powerpc", | |
| 193 | "powerpc64", | |
| 194 | "riscv64", | |
| 195 | "s390x", | |
| 196 | "sh", | |
| 197 | "x32", | |
| 198 | "x86_64", | |
| 199 | }; | |
| 200 | for (musl_arch_names) |musl_arch_name| { | |
| 201 | if (mem.eql(u8, musl_arch_name, name)) { | |
| 202 | return true; | |
| 203 | } | |
| 204 | } | |
| 205 | return false; | |
| 206 | } | |
| 207 | ||
| 208 | const Ext = enum { | |
| 209 | assembly, | |
| 210 | normal, | |
| 211 | o3, | |
| 212 | }; | |
| 213 | ||
| 214 | fn addSrcFile(arena: *Allocator, source_table: *std.StringArrayHashMap(Ext), file_path: []const u8) !void { | |
| 215 | const ext: Ext = ext: { | |
| 216 | if (mem.endsWith(u8, file_path, ".c")) { | |
| 217 | if (mem.startsWith(u8, file_path, "musl/src/malloc/") or | |
| 218 | mem.startsWith(u8, file_path, "musl/src/string/") or | |
| 219 | mem.startsWith(u8, file_path, "musl/src/internal/")) | |
| 220 | { | |
| 221 | break :ext .o3; | |
| 222 | } else { | |
| 223 | break :ext .assembly; | |
| 224 | } | |
| 225 | } else if (mem.endsWith(u8, file_path, ".s") or mem.endsWith(u8, file_path, ".S")) { | |
| 226 | break :ext .assembly; | |
| 227 | } else { | |
| 228 | unreachable; | |
| 229 | } | |
| 230 | }; | |
| 231 | // TODO do this at comptime on the comptime data rather than at runtime | |
| 232 | // probably best to wait until self-hosted is done and our comptime execution | |
| 233 | // is faster and uses less memory. | |
| 234 | const key = if (path.sep != '/') blk: { | |
| 235 | const mutable_file_path = try arena.dupe(u8, file_path); | |
| 236 | for (mutable_file_path) |*c| { | |
| 237 | if (c.* == '/') { | |
| 238 | c.* == path.sep; | |
| 239 | } | |
| 240 | } | |
| 241 | break :blk mutable_file_path; | |
| 242 | } else file_path; | |
| 243 | source_table.putAssumeCapacityNoClobber(key, ext); | |
| 244 | } | |
| 245 | ||
| 246 | fn add_cc_args( | |
| 247 | comp: *Compilation, | |
| 248 | arena: *Allocator, | |
| 249 | args: *std.ArrayList([]const u8), | |
| 250 | want_O3: bool, | |
| 251 | ) error{OutOfMemory}!void { | |
| 252 | const target = comp.getTarget(); | |
| 253 | const arch_name = target_util.archMuslName(target.cpu.arch); | |
| 254 | const os_name = @tagName(target.os.tag); | |
| 255 | const triple = try std.fmt.allocPrint(arena, "{}-{}-musl", .{ arch_name, os_name }); | |
| 256 | const o_arg = if (want_O3) "-O3" else "-Os"; | |
| 257 | ||
| 258 | try args.appendSlice(&[_][]const u8{ | |
| 259 | "-std=c99", | |
| 260 | "-ffreestanding", | |
| 261 | // Musl adds these args to builds with gcc but clang does not support them. | |
| 262 | //"-fexcess-precision=standard", | |
| 263 | //"-frounding-math", | |
| 264 | "-Wa,--noexecstack", | |
| 265 | "-D_XOPEN_SOURCE=700", | |
| 266 | ||
| 267 | "-I", | |
| 268 | try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "musl", "arch", arch_name }), | |
| 269 | ||
| 270 | "-I", | |
| 271 | try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "musl", "arch", "generic" }), | |
| 272 | ||
| 273 | "-I", | |
| 274 | try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "musl", "src", "include" }), | |
| 275 | ||
| 276 | "-I", | |
| 277 | try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "musl", "src", "internal" }), | |
| 278 | ||
| 279 | "-I", | |
| 280 | try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "musl", "include" }), | |
| 281 | ||
| 282 | "-I", | |
| 283 | try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "include", triple }), | |
| 284 | ||
| 285 | "-I", | |
| 286 | try comp.zig_lib_directory.join(arena, &[_][]const u8{ "libc", "include", "generic-musl" }), | |
| 287 | ||
| 288 | o_arg, | |
| 289 | ||
| 290 | "-fomit-frame-pointer", | |
| 291 | "-fno-unwind-tables", | |
| 292 | "-fno-asynchronous-unwind-tables", | |
| 293 | "-ffunction-sections", | |
| 294 | "-fdata-sections", | |
| 295 | }); | |
| 296 | } | |
| 297 | ||
| 298 | fn start_asm_path(comp: *Compilation, arena: *Allocator, basename: []const u8) ![]const u8 { | |
| 299 | const target = comp.getTarget(); | |
| 300 | return comp.zig_lib_directory.join(arena, &[_][]const u8{ | |
| 301 | "libc", "musl", "crt", target_util.archMuslName(target.cpu.arch), basename, | |
| 302 | }); | |
| 303 | } | |
| 304 | ||
| 305 | const src_files = [_][]const u8{ | |
| 4 | 306 | "musl/src/aio/aio.c", |
| 5 | 307 | "musl/src/aio/aio_suspend.c", |
| 6 | 308 | "musl/src/aio/lio_listio.c", |
| ... | ... | @@ -1776,7 +2078,7 @@ pub const src_files = [_][]const u8{ |
| 1776 | 2078 | "musl/src/unistd/writev.c", |
| 1777 | 2079 | "musl/src/unistd/x32/lseek.c", |
| 1778 | 2080 | }; |
| 1779 | pub const compat_time32_files = [_][]const u8{ | |
| 2081 | const compat_time32_files = [_][]const u8{ | |
| 1780 | 2082 | "musl/compat/time32/__xstat.c", |
| 1781 | 2083 | "musl/compat/time32/adjtime32.c", |
| 1782 | 2084 | "musl/compat/time32/adjtimex_time32.c", |