| author | |
| committer | |
| log | b08fd0e8fca5ff9ac5531437f5749e74dc009a14 |
| tree | e2fcc2a3a28e1ce90631542745d779c92b9356c0 |
| parent | 64deb46859a11588fb97e8464ec9dae53124b96b |
6 files changed, 426 insertions(+), 76 deletions(-)
BRANCH_TODO+4-2| ... | @@ -1,7 +1,6 @@ | ... | @@ -1,7 +1,6 @@ |
| 1 | * musl | 1 | * repair @cImport |
| 2 | * tests passing with -Dskip-non-native | 2 | * tests passing with -Dskip-non-native |
| 3 | * windows CUSTOMBUILD : error : unable to build compiler_rt: FileNotFound [D:\a\1\s\build\zig_install_lib_files.vcxproj] | 3 | * windows CUSTOMBUILD : error : unable to build compiler_rt: FileNotFound [D:\a\1\s\build\zig_install_lib_files.vcxproj] |
| 4 | * repair @cImport | ||
| 5 | * make sure zig cc works | 4 | * make sure zig cc works |
| 6 | - using it as a preprocessor (-E) | 5 | - using it as a preprocessor (-E) |
| 7 | - try building some software | 6 | - try building some software |
| ... | @@ -20,6 +19,7 @@ | ... | @@ -20,6 +19,7 @@ |
| 20 | * WASM LLD linking | 19 | * WASM LLD linking |
| 21 | * skip LLD caching when bin directory is not in the cache (so we don't put `id.txt` into the cwd) | 20 | * skip LLD caching when bin directory is not in the cache (so we don't put `id.txt` into the cwd) |
| 22 | (maybe make it an explicit option and have main.zig disable it) | 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 | * audit the CLI options for stage2 | 23 | * audit the CLI options for stage2 |
| 24 | * audit the base cache hash | 24 | * audit the base cache hash |
| 25 | * On operating systems that support it, do an execve for `zig test` and `zig run` rather than child process. | 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,3 +58,5 @@ |
| 58 | * rename std.builtin.Mode to std.builtin.OptimizeMode | 58 | * rename std.builtin.Mode to std.builtin.OptimizeMode |
| 59 | * implement `zig run` and `zig test` when combined with `--watch` | 59 | * implement `zig run` and `zig test` when combined with `--watch` |
| 60 | * close the --pkg-begin --pkg-end Package directory handles | 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,6 +393,12 @@ pub const NativeTargetInfo = struct { |
| 393 | if (!native_target_has_ld or have_all_info or os_is_non_native) { | 393 | if (!native_target_has_ld or have_all_info or os_is_non_native) { |
| 394 | return defaultAbiAndDynamicLinker(cpu, os, cross_target); | 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 | // The current target's ABI cannot be relied on for this. For example, we may build the zig | 402 | // The current target's ABI cannot be relied on for this. For example, we may build the zig |
| 397 | // compiler for target riscv64-linux-musl and provide a tarball for users to download. | 403 | // compiler for target riscv64-linux-musl and provide a tarball for users to download. |
| 398 | // A user could then run that zig compiler on riscv64-linux-gnu. This use case is well-defined | 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,6 +15,7 @@ const liveness = @import("liveness.zig"); |
| 15 | const build_options = @import("build_options"); | 15 | const build_options = @import("build_options"); |
| 16 | const LibCInstallation = @import("libc_installation.zig").LibCInstallation; | 16 | const LibCInstallation = @import("libc_installation.zig").LibCInstallation; |
| 17 | const glibc = @import("glibc.zig"); | 17 | const glibc = @import("glibc.zig"); |
| 18 | const musl = @import("musl.zig"); | ||
| 18 | const libunwind = @import("libunwind.zig"); | 19 | const libunwind = @import("libunwind.zig"); |
| 19 | const libcxx = @import("libcxx.zig"); | 20 | const libcxx = @import("libcxx.zig"); |
| 20 | const fatal = @import("main.zig").fatal; | 21 | const fatal = @import("main.zig").fatal; |
| ... | @@ -140,6 +141,8 @@ const Job = union(enum) { | ... | @@ -140,6 +141,8 @@ const Job = union(enum) { |
| 140 | glibc_crt_file: glibc.CRTFile, | 141 | glibc_crt_file: glibc.CRTFile, |
| 141 | /// all of the glibc shared objects | 142 | /// all of the glibc shared objects |
| 142 | glibc_shared_objects, | 143 | glibc_shared_objects, |
| 144 | /// one of the glibc static objects | ||
| 145 | musl_crt_file: musl.CRTFile, | ||
| 143 | /// libunwind.a, usually needed when linking libc | 146 | /// libunwind.a, usually needed when linking libc |
| 144 | libunwind: void, | 147 | libunwind: void, |
| 145 | libcxx: void, | 148 | libcxx: void, |
| ... | @@ -778,6 +781,18 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { | ... | @@ -778,6 +781,18 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 778 | if (comp.wantBuildGLibCFromSource()) { | 781 | if (comp.wantBuildGLibCFromSource()) { |
| 779 | try comp.addBuildingGLibCJobs(); | 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 | if (comp.wantBuildLibUnwindFromSource()) { | 796 | if (comp.wantBuildLibUnwindFromSource()) { |
| 782 | try comp.work_queue.writeItem(.{ .libunwind = {} }); | 797 | try comp.work_queue.writeItem(.{ .libunwind = {} }); |
| 783 | } | 798 | } |
| ... | @@ -822,6 +837,7 @@ pub fn destroy(self: *Compilation) void { | ... | @@ -822,6 +837,7 @@ pub fn destroy(self: *Compilation) void { |
| 822 | { | 837 | { |
| 823 | var it = self.crt_files.iterator(); | 838 | var it = self.crt_files.iterator(); |
| 824 | while (it.next()) |entry| { | 839 | while (it.next()) |entry| { |
| 840 | gpa.free(entry.key); | ||
| 825 | entry.value.deinit(gpa); | 841 | entry.value.deinit(gpa); |
| 826 | } | 842 | } |
| 827 | self.crt_files.deinit(gpa); | 843 | self.crt_files.deinit(gpa); |
| ... | @@ -1128,6 +1144,12 @@ pub fn performAllTheWork(self: *Compilation) error{OutOfMemory}!void { | ... | @@ -1128,6 +1144,12 @@ pub fn performAllTheWork(self: *Compilation) error{OutOfMemory}!void { |
| 1128 | fatal("unable to build glibc shared objects: {}", .{@errorName(err)}); | 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 | .libunwind => { | 1153 | .libunwind => { |
| 1132 | libunwind.buildStaticLib(self) catch |err| { | 1154 | libunwind.buildStaticLib(self) catch |err| { |
| 1133 | // TODO Expose this as a normal compile error rather than crashing here. | 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,7 +1868,10 @@ fn detectLibCFromLibCInstallation(arena: *Allocator, target: Target, lci: *const |
| 1846 | } | 1868 | } |
| 1847 | 1869 | ||
| 1848 | pub fn get_libc_crt_file(comp: *Compilation, arena: *Allocator, basename: []const u8) ![]const u8 { | 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 | return comp.crt_files.get(basename).?.full_object_path; | 1875 | return comp.crt_files.get(basename).?.full_object_path; |
| 1851 | } | 1876 | } |
| 1852 | const lci = comp.bin_file.options.libc_installation orelse return error.LibCInstallationNotAvailable; | 1877 | const lci = comp.bin_file.options.libc_installation orelse return error.LibCInstallationNotAvailable; |
| ... | @@ -1865,15 +1890,26 @@ fn addBuildingGLibCJobs(comp: *Compilation) !void { | ... | @@ -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 | const is_exe_or_dyn_lib = switch (comp.bin_file.options.output_mode) { | 1894 | const is_exe_or_dyn_lib = switch (comp.bin_file.options.output_mode) { |
| 1870 | .Obj => false, | 1895 | .Obj => false, |
| 1871 | .Lib => comp.bin_file.options.link_mode == .Dynamic, | 1896 | .Lib => comp.bin_file.options.link_mode == .Dynamic, |
| 1872 | .Exe => true, | 1897 | .Exe => true, |
| 1873 | }; | 1898 | }; |
| 1874 | return comp.bin_file.options.link_libc and is_exe_or_dyn_lib and | 1899 | return comp.bin_file.options.link_libc and is_exe_or_dyn_lib and |
| 1875 | comp.bin_file.options.libc_installation == null and | 1900 | comp.bin_file.options.libc_installation == null; |
| 1876 | comp.bin_file.options.target.isGnuLibC(); | 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 | fn wantBuildLibUnwindFromSource(comp: *Compilation) bool { | 1915 | fn wantBuildLibUnwindFromSource(comp: *Compilation) bool { |
| ... | @@ -2362,3 +2398,69 @@ fn createStage1Pkg( | ... | @@ -2362,3 +2398,69 @@ fn createStage1Pkg( |
| 2362 | }; | 2398 | }; |
| 2363 | return child_pkg; | 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,7 +274,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { |
| 274 | "-g", | 274 | "-g", |
| 275 | "-Wa,--noexecstack", | 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 | .src_path = try start_asm_path(comp, arena, "crti.S"), | 279 | .src_path = try start_asm_path(comp, arena, "crti.S"), |
| 280 | .extra_flags = args.items, | 280 | .extra_flags = args.items, |
| ... | @@ -292,7 +292,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { | ... | @@ -292,7 +292,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { |
| 292 | "-g", | 292 | "-g", |
| 293 | "-Wa,--noexecstack", | 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 | .src_path = try start_asm_path(comp, arena, "crtn.S"), | 297 | .src_path = try start_asm_path(comp, arena, "crtn.S"), |
| 298 | .extra_flags = args.items, | 298 | .extra_flags = args.items, |
| ... | @@ -343,7 +343,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { | ... | @@ -343,7 +343,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { |
| 343 | .extra_flags = args.items, | 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 | .libc_nonshared_a => { | 348 | .libc_nonshared_a => { |
| 349 | const deps = [_][]const u8{ | 349 | const deps = [_][]const u8{ |
| ... | @@ -433,7 +433,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { | ... | @@ -433,7 +433,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { |
| 433 | .extra_flags = args.items, | 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,68 +676,6 @@ fn lib_path(comp: *Compilation, arena: *Allocator, sub_path: []const u8) ![]cons |
| 676 | return path.join(arena, &[_][]const u8{ comp.zig_lib_directory.path.?, sub_path }); | 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 | pub const BuiltSharedObjects = struct { | 679 | pub const BuiltSharedObjects = struct { |
| 742 | lock: Cache.Lock, | 680 | lock: Cache.Lock, |
| 743 | dir_path: []u8, | 681 | dir_path: []u8, |
src/link/Elf.zig+1-1| ... | @@ -1548,7 +1548,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { | ... | @@ -1548,7 +1548,7 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1548 | try argv.append(try comp.get_libc_crt_file(arena, "libc_nonshared.a")); | 1548 | try argv.append(try comp.get_libc_crt_file(arena, "libc_nonshared.a")); |
| 1549 | } else if (target.isMusl()) { | 1549 | } else if (target.isMusl()) { |
| 1550 | try argv.append(comp.libunwind_static_lib.?.full_object_path); | 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 | } else if (self.base.options.link_libcpp) { | 1552 | } else if (self.base.options.link_libcpp) { |
| 1553 | try argv.append(comp.libunwind_static_lib.?.full_object_path); | 1553 | try argv.append(comp.libunwind_static_lib.?.full_object_path); |
| 1554 | } else { | 1554 | } else { |
src/musl.zig+305-3| ... | @@ -1,6 +1,308 @@ | ... | @@ -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 | "musl/src/aio/aio.c", | 306 | "musl/src/aio/aio.c", |
| 5 | "musl/src/aio/aio_suspend.c", | 307 | "musl/src/aio/aio_suspend.c", |
| 6 | "musl/src/aio/lio_listio.c", | 308 | "musl/src/aio/lio_listio.c", |
| ... | @@ -1776,7 +2078,7 @@ pub const src_files = [_][]const u8{ | ... | @@ -1776,7 +2078,7 @@ pub const src_files = [_][]const u8{ |
| 1776 | "musl/src/unistd/writev.c", | 2078 | "musl/src/unistd/writev.c", |
| 1777 | "musl/src/unistd/x32/lseek.c", | 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 | "musl/compat/time32/__xstat.c", | 2082 | "musl/compat/time32/__xstat.c", |
| 1781 | "musl/compat/time32/adjtime32.c", | 2083 | "musl/compat/time32/adjtime32.c", |
| 1782 | "musl/compat/time32/adjtimex_time32.c", | 2084 | "musl/compat/time32/adjtimex_time32.c", |