| author | |
| committer | |
| log | 0f2612037784570930dea433afef559ff6161b21 |
| tree | d60fbc768c7460ac6874ed937eac38f8fe345842 |
| parent | 44e480aa2cef24a0a9edbc5d24991f9432a255e3 |
- more support for linux, android, freebsd, netbsd, openbsd, dragonfly
- centralize musl utils; musl logic is no longer intertwined with csu
- fix musl compilation to build crti/crtn for full archs list
- fix openbsd to support `zig build-lib -dynamic`
- initial dragonfly linking success (with a warning)
ancillary:
- fix emutls (openbsd) tests to use `try`11 files changed, 288 insertions(+), 91 deletions(-)
lib/std/Thread.zig+3| ... | @@ -576,6 +576,9 @@ pub fn getCurrentThreadId() u64 { | ... | @@ -576,6 +576,9 @@ pub fn getCurrentThreadId() u64 { |
| 576 | assert(c.pthread_threadid_np(null, &thread_id) == 0); | 576 | assert(c.pthread_threadid_np(null, &thread_id) == 0); |
| 577 | return thread_id; | 577 | return thread_id; |
| 578 | }, | 578 | }, |
| 579 | .dragonfly => { | ||
| 580 | return @bitCast(u32, c.lwp_gettid()); | ||
| 581 | }, | ||
| 579 | .netbsd => { | 582 | .netbsd => { |
| 580 | return @bitCast(u32, c._lwp_self()); | 583 | return @bitCast(u32, c._lwp_self()); |
| 581 | }, | 584 | }, |
lib/std/c/dragonfly.zig+4| ... | @@ -18,6 +18,8 @@ pub extern "c" fn pipe2(fds: *[2]fd_t, flags: u32) c_int; | ... | @@ -18,6 +18,8 @@ pub extern "c" fn pipe2(fds: *[2]fd_t, flags: u32) c_int; |
| 18 | pub const dl_iterate_phdr_callback = fn (info: *dl_phdr_info, size: usize, data: ?*c_void) callconv(.C) c_int; | 18 | pub const dl_iterate_phdr_callback = fn (info: *dl_phdr_info, size: usize, data: ?*c_void) callconv(.C) c_int; |
| 19 | pub extern "c" fn dl_iterate_phdr(callback: dl_iterate_phdr_callback, data: ?*c_void) c_int; | 19 | pub extern "c" fn dl_iterate_phdr(callback: dl_iterate_phdr_callback, data: ?*c_void) c_int; |
| 20 | 20 | ||
| 21 | pub extern "c" fn lwp_gettid() c_int; | ||
| 22 | |||
| 21 | pub extern "c" fn posix_memalign(memptr: *?*c_void, alignment: usize, size: usize) c_int; | 23 | pub extern "c" fn posix_memalign(memptr: *?*c_void, alignment: usize, size: usize) c_int; |
| 22 | 24 | ||
| 23 | pub const pthread_mutex_t = extern struct { | 25 | pub const pthread_mutex_t = extern struct { |
| ... | @@ -31,3 +33,5 @@ pub const pthread_attr_t = extern struct { // copied from freebsd | ... | @@ -31,3 +33,5 @@ pub const pthread_attr_t = extern struct { // copied from freebsd |
| 31 | __size: [56]u8, | 33 | __size: [56]u8, |
| 32 | __align: c_long, | 34 | __align: c_long, |
| 33 | }; | 35 | }; |
| 36 | |||
| 37 | pub const sem_t = ?*opaque {}; |
lib/std/child_process.zig+14-2| ... | @@ -203,6 +203,10 @@ pub const ChildProcess = struct { | ... | @@ -203,6 +203,10 @@ pub const ChildProcess = struct { |
| 203 | // of space an ArrayList will allocate grows exponentially. | 203 | // of space an ArrayList will allocate grows exponentially. |
| 204 | const bump_amt = 512; | 204 | const bump_amt = 512; |
| 205 | 205 | ||
| 206 | // TODO https://github.com/ziglang/zig/issues/8724 | ||
| 207 | // parent process does not receive POLLHUP events | ||
| 208 | const dragonfly_workaround = builtin.os.tag == .dragonfly; | ||
| 209 | |||
| 206 | while (dead_fds < poll_fds.len) { | 210 | while (dead_fds < poll_fds.len) { |
| 207 | const events = try os.poll(&poll_fds, std.math.maxInt(i32)); | 211 | const events = try os.poll(&poll_fds, std.math.maxInt(i32)); |
| 208 | if (events == 0) continue; | 212 | if (events == 0) continue; |
| ... | @@ -215,7 +219,11 @@ pub const ChildProcess = struct { | ... | @@ -215,7 +219,11 @@ pub const ChildProcess = struct { |
| 215 | try stdout.ensureCapacity(new_capacity); | 219 | try stdout.ensureCapacity(new_capacity); |
| 216 | const buf = stdout.unusedCapacitySlice(); | 220 | const buf = stdout.unusedCapacitySlice(); |
| 217 | if (buf.len == 0) return error.StdoutStreamTooLong; | 221 | if (buf.len == 0) return error.StdoutStreamTooLong; |
| 218 | stdout.items.len += try os.read(poll_fds[0].fd, buf); | 222 | const nread = try os.read(poll_fds[0].fd, buf); |
| 223 | stdout.items.len += nread; | ||
| 224 | |||
| 225 | // insert POLLHUP event because dragonfly fails to do so | ||
| 226 | if (dragonfly_workaround and nread == 0) poll_fds[0].revents |= os.POLLHUP; | ||
| 219 | } | 227 | } |
| 220 | if (poll_fds[1].revents & os.POLLIN != 0) { | 228 | if (poll_fds[1].revents & os.POLLIN != 0) { |
| 221 | // stderr is ready. | 229 | // stderr is ready. |
| ... | @@ -223,7 +231,11 @@ pub const ChildProcess = struct { | ... | @@ -223,7 +231,11 @@ pub const ChildProcess = struct { |
| 223 | try stderr.ensureCapacity(new_capacity); | 231 | try stderr.ensureCapacity(new_capacity); |
| 224 | const buf = stderr.unusedCapacitySlice(); | 232 | const buf = stderr.unusedCapacitySlice(); |
| 225 | if (buf.len == 0) return error.StderrStreamTooLong; | 233 | if (buf.len == 0) return error.StderrStreamTooLong; |
| 226 | stderr.items.len += try os.read(poll_fds[1].fd, buf); | 234 | const nread = try os.read(poll_fds[1].fd, buf); |
| 235 | stderr.items.len += nread; | ||
| 236 | |||
| 237 | // insert POLLHUP event because dragonfly fails to do so | ||
| 238 | if (dragonfly_workaround and nread == 0) poll_fds[1].revents |= os.POLLHUP; | ||
| 227 | } | 239 | } |
| 228 | 240 | ||
| 229 | // Exclude the fds that signaled an error. | 241 | // Exclude the fds that signaled an error. |
lib/std/os/bits/dragonfly.zig+26| ... | @@ -767,3 +767,29 @@ pub const rlimit = extern struct { | ... | @@ -767,3 +767,29 @@ pub const rlimit = extern struct { |
| 767 | /// Hard limit | 767 | /// Hard limit |
| 768 | max: rlim_t, | 768 | max: rlim_t, |
| 769 | }; | 769 | }; |
| 770 | |||
| 771 | pub const SHUT_RD = 0; | ||
| 772 | pub const SHUT_WR = 1; | ||
| 773 | pub const SHUT_RDWR = 2; | ||
| 774 | |||
| 775 | pub const nfds_t = u32; | ||
| 776 | |||
| 777 | pub const pollfd = extern struct { | ||
| 778 | fd: fd_t, | ||
| 779 | events: i16, | ||
| 780 | revents: i16, | ||
| 781 | }; | ||
| 782 | |||
| 783 | /// Requestable events. | ||
| 784 | pub const POLLIN = 0x0001; | ||
| 785 | pub const POLLPRI = 0x0002; | ||
| 786 | pub const POLLOUT = 0x0004; | ||
| 787 | pub const POLLRDNORM = 0x0040; | ||
| 788 | pub const POLLWRNORM = POLLOUT; | ||
| 789 | pub const POLLRDBAND = 0x0080; | ||
| 790 | pub const POLLWRBAND = 0x0100; | ||
| 791 | |||
| 792 | /// These events are set if they occur regardless of whether they were requested. | ||
| 793 | pub const POLLERR = 0x0008; | ||
| 794 | pub const POLLHUP = 0x0010; | ||
| 795 | pub const POLLNVAL = 0x0020; |
lib/std/special/compiler_rt/emutls.zig+6-6| ... | @@ -376,7 +376,7 @@ test "__emutls_get_address with default_value" { | ... | @@ -376,7 +376,7 @@ test "__emutls_get_address with default_value" { |
| 376 | 376 | ||
| 377 | test "test default_value with differents sizes" { | 377 | test "test default_value with differents sizes" { |
| 378 | const testType = struct { | 378 | const testType = struct { |
| 379 | fn _testType(comptime T: type, value: T) void { | 379 | fn _testType(comptime T: type, value: T) !void { |
| 380 | var def: T = value; | 380 | var def: T = value; |
| 381 | var ctl = emutls_control.init(T, &def); | 381 | var ctl = emutls_control.init(T, &def); |
| 382 | var x = ctl.get_typed_pointer(T); | 382 | var x = ctl.get_typed_pointer(T); |
| ... | @@ -384,11 +384,11 @@ test "test default_value with differents sizes" { | ... | @@ -384,11 +384,11 @@ test "test default_value with differents sizes" { |
| 384 | } | 384 | } |
| 385 | }._testType; | 385 | }._testType; |
| 386 | 386 | ||
| 387 | testType(usize, 1234); | 387 | try testType(usize, 1234); |
| 388 | testType(u32, 1234); | 388 | try testType(u32, 1234); |
| 389 | testType(i16, -12); | 389 | try testType(i16, -12); |
| 390 | testType(f64, -12.0); | 390 | try testType(f64, -12.0); |
| 391 | testType( | 391 | try testType( |
| 392 | @TypeOf("012345678901234567890123456789"), | 392 | @TypeOf("012345678901234567890123456789"), |
| 393 | "012345678901234567890123456789", | 393 | "012345678901234567890123456789", |
| 394 | ); | 394 | ); |
src/Compilation.zig+2-2| ... | @@ -1407,7 +1407,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { | ... | @@ -1407,7 +1407,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 1407 | } | 1407 | } |
| 1408 | if (comp.wantBuildMuslFromSource()) { | 1408 | if (comp.wantBuildMuslFromSource()) { |
| 1409 | try comp.work_queue.ensureUnusedCapacity(6); | 1409 | try comp.work_queue.ensureUnusedCapacity(6); |
| 1410 | if (target_util.libc_needs_crti_crtn(comp.getTarget())) { | 1410 | if (musl.needsCrtiCrtn(comp.getTarget())) { |
| 1411 | comp.work_queue.writeAssumeCapacity(&[_]Job{ | 1411 | comp.work_queue.writeAssumeCapacity(&[_]Job{ |
| 1412 | .{ .musl_crt_file = .crti_o }, | 1412 | .{ .musl_crt_file = .crti_o }, |
| 1413 | .{ .musl_crt_file = .crtn_o }, | 1413 | .{ .musl_crt_file = .crtn_o }, |
| ... | @@ -3180,7 +3180,7 @@ fn detectLibCIncludeDirs( | ... | @@ -3180,7 +3180,7 @@ fn detectLibCIncludeDirs( |
| 3180 | const generic_name = target_util.libCGenericName(target); | 3180 | const generic_name = target_util.libCGenericName(target); |
| 3181 | // Some architectures are handled by the same set of headers. | 3181 | // Some architectures are handled by the same set of headers. |
| 3182 | const arch_name = if (target.abi.isMusl()) | 3182 | const arch_name = if (target.abi.isMusl()) |
| 3183 | target_util.archMuslName(target.cpu.arch) | 3183 | musl.archMuslName(target.cpu.arch) |
| 3184 | else if (target.cpu.arch.isThumb()) | 3184 | else if (target.cpu.arch.isThumb()) |
| 3185 | // ARM headers are valid for Thumb too. | 3185 | // ARM headers are valid for Thumb too. |
| 3186 | switch (target.cpu.arch) { | 3186 | switch (target.cpu.arch) { |
src/libc_installation.zig+3-3| ... | @@ -195,8 +195,8 @@ pub const LibCInstallation = struct { | ... | @@ -195,8 +195,8 @@ pub const LibCInstallation = struct { |
| 195 | errdefer batch.wait() catch {}; | 195 | errdefer batch.wait() catch {}; |
| 196 | batch.add(&async self.findNativeIncludeDirPosix(args)); | 196 | batch.add(&async self.findNativeIncludeDirPosix(args)); |
| 197 | switch (Target.current.os.tag) { | 197 | switch (Target.current.os.tag) { |
| 198 | .freebsd, .netbsd, .openbsd => self.crt_dir = try std.mem.dupeZ(args.allocator, u8, "/usr/lib"), | 198 | .freebsd, .netbsd, .openbsd, .dragonfly => self.crt_dir = try std.mem.dupeZ(args.allocator, u8, "/usr/lib"), |
| 199 | .linux, .dragonfly => batch.add(&async self.findNativeCrtDirPosix(args)), | 199 | .linux => batch.add(&async self.findNativeCrtDirPosix(args)), |
| 200 | .haiku => self.crt_dir = try std.mem.dupeZ(args.allocator, u8, "/system/develop/lib"), | 200 | .haiku => self.crt_dir = try std.mem.dupeZ(args.allocator, u8, "/system/develop/lib"), |
| 201 | else => {}, | 201 | else => {}, |
| 202 | } | 202 | } |
| ... | @@ -523,7 +523,7 @@ pub const CCPrintFileNameOptions = struct { | ... | @@ -523,7 +523,7 @@ pub const CCPrintFileNameOptions = struct { |
| 523 | }; | 523 | }; |
| 524 | 524 | ||
| 525 | /// caller owns returned memory | 525 | /// caller owns returned memory |
| 526 | fn ccPrintFileName(args: CCPrintFileNameOptions) ![:0]u8 { | 526 | pub fn ccPrintFileName(args: CCPrintFileNameOptions) ![:0]u8 { |
| 527 | const allocator = args.allocator; | 527 | const allocator = args.allocator; |
| 528 | 528 | ||
| 529 | const cc_exe = std.os.getenvZ("CC") orelse default_cc_exe; | 529 | const cc_exe = std.os.getenvZ("CC") orelse default_cc_exe; |
src/link/Elf.zig+188-45| ... | @@ -23,6 +23,7 @@ const File = link.File; | ... | @@ -23,6 +23,7 @@ const File = link.File; |
| 23 | const build_options = @import("build_options"); | 23 | const build_options = @import("build_options"); |
| 24 | const target_util = @import("../target.zig"); | 24 | const target_util = @import("../target.zig"); |
| 25 | const glibc = @import("../glibc.zig"); | 25 | const glibc = @import("../glibc.zig"); |
| 26 | const musl = @import("../musl.zig"); | ||
| 26 | const Cache = @import("../Cache.zig"); | 27 | const Cache = @import("../Cache.zig"); |
| 27 | const llvm_backend = @import("../codegen/llvm.zig"); | 28 | const llvm_backend = @import("../codegen/llvm.zig"); |
| 28 | 29 | ||
| ... | @@ -1278,7 +1279,6 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { | ... | @@ -1278,7 +1279,6 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1278 | const is_exe_or_dyn_lib = is_dyn_lib or self.base.options.output_mode == .Exe; | 1279 | const is_exe_or_dyn_lib = is_dyn_lib or self.base.options.output_mode == .Exe; |
| 1279 | const have_dynamic_linker = self.base.options.link_libc and | 1280 | const have_dynamic_linker = self.base.options.link_libc and |
| 1280 | self.base.options.link_mode == .Dynamic and is_exe_or_dyn_lib; | 1281 | self.base.options.link_mode == .Dynamic and is_exe_or_dyn_lib; |
| 1281 | const link_in_crt = self.base.options.link_libc and self.base.options.output_mode == .Exe; | ||
| 1282 | const target = self.base.options.target; | 1282 | const target = self.base.options.target; |
| 1283 | const gc_sections = self.base.options.gc_sections orelse !is_obj; | 1283 | const gc_sections = self.base.options.gc_sections orelse !is_obj; |
| 1284 | const stack_size = self.base.options.stack_size_override orelse 16777216; | 1284 | const stack_size = self.base.options.stack_size_override orelse 16777216; |
| ... | @@ -1499,40 +1499,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { | ... | @@ -1499,40 +1499,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1499 | try argv.append("-o"); | 1499 | try argv.append("-o"); |
| 1500 | try argv.append(full_out_path); | 1500 | try argv.append(full_out_path); |
| 1501 | 1501 | ||
| 1502 | if (link_in_crt) { | 1502 | // csu prelude |
| 1503 | const crt1o: []const u8 = o: { | 1503 | var csu = try CsuObjects.init(arena, self.base.options, comp); |
| 1504 | if (target.os.tag == .netbsd) { | 1504 | if (csu.crt0) |v| try argv.append(v); |
| 1505 | break :o "crt0.o"; | 1505 | if (csu.crti) |v| try argv.append(v); |
| 1506 | } else if (target.os.tag == .openbsd) { | 1506 | if (csu.crtbegin) |v| try argv.append(v); |
| 1507 | if (self.base.options.link_mode == .Static) { | ||
| 1508 | break :o "rcrt0.o"; | ||
| 1509 | } else { | ||
| 1510 | break :o "crt0.o"; | ||
| 1511 | } | ||
| 1512 | } else if (target.isAndroid()) { | ||
| 1513 | if (self.base.options.link_mode == .Dynamic) { | ||
| 1514 | break :o "crtbegin_dynamic.o"; | ||
| 1515 | } else { | ||
| 1516 | break :o "crtbegin_static.o"; | ||
| 1517 | } | ||
| 1518 | } else if (self.base.options.link_mode == .Static) { | ||
| 1519 | if (self.base.options.pie) { | ||
| 1520 | break :o "rcrt1.o"; | ||
| 1521 | } else { | ||
| 1522 | break :o "crt1.o"; | ||
| 1523 | } | ||
| 1524 | } else { | ||
| 1525 | break :o "Scrt1.o"; | ||
| 1526 | } | ||
| 1527 | }; | ||
| 1528 | try argv.append(try comp.get_libc_crt_file(arena, crt1o)); | ||
| 1529 | if (target_util.libc_needs_crti_crtn(target)) { | ||
| 1530 | try argv.append(try comp.get_libc_crt_file(arena, "crti.o")); | ||
| 1531 | } | ||
| 1532 | if (target.os.tag == .openbsd) { | ||
| 1533 | try argv.append(try comp.get_libc_crt_file(arena, "crtbegin.o")); | ||
| 1534 | } | ||
| 1535 | } | ||
| 1536 | 1507 | ||
| 1537 | // rpaths | 1508 | // rpaths |
| 1538 | var rpath_table = std.StringHashMap(void).init(self.base.allocator); | 1509 | var rpath_table = std.StringHashMap(void).init(self.base.allocator); |
| ... | @@ -1676,16 +1647,9 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { | ... | @@ -1676,16 +1647,9 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1676 | } | 1647 | } |
| 1677 | } | 1648 | } |
| 1678 | 1649 | ||
| 1679 | // crt end | 1650 | // crt postlude |
| 1680 | if (link_in_crt) { | 1651 | if (csu.crtend) |v| try argv.append(v); |
| 1681 | if (target.isAndroid()) { | 1652 | if (csu.crtn) |v| try argv.append(v); |
| 1682 | try argv.append(try comp.get_libc_crt_file(arena, "crtend_android.o")); | ||
| 1683 | } else if (target.os.tag == .openbsd) { | ||
| 1684 | try argv.append(try comp.get_libc_crt_file(arena, "crtend.o")); | ||
| 1685 | } else if (target_util.libc_needs_crti_crtn(target)) { | ||
| 1686 | try argv.append(try comp.get_libc_crt_file(arena, "crtn.o")); | ||
| 1687 | } | ||
| 1688 | } | ||
| 1689 | 1653 | ||
| 1690 | if (allow_shlib_undefined) { | 1654 | if (allow_shlib_undefined) { |
| 1691 | try argv.append("--allow-shlib-undefined"); | 1655 | try argv.append("--allow-shlib-undefined"); |
| ... | @@ -3237,3 +3201,182 @@ fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { | ... | @@ -3237,3 +3201,182 @@ fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { |
| 3237 | return std.math.add(@TypeOf(actual_size), actual_size, actual_size / ideal_factor) catch | 3201 | return std.math.add(@TypeOf(actual_size), actual_size, actual_size / ideal_factor) catch |
| 3238 | std.math.maxInt(@TypeOf(actual_size)); | 3202 | std.math.maxInt(@TypeOf(actual_size)); |
| 3239 | } | 3203 | } |
| 3204 | |||
| 3205 | // Provide a blueprint of csu (c-runtime startup) objects for supported | ||
| 3206 | // link modes. | ||
| 3207 | // | ||
| 3208 | // This is for cross-mode targets only. For host-mode targets the system | ||
| 3209 | // compiler can be probed to produce a robust blueprint. | ||
| 3210 | // | ||
| 3211 | // Targets requiring a libc for which zig does not bundle a libc are | ||
| 3212 | // host-mode targets. Unfortunately, host-mode probes are not yet | ||
| 3213 | // implemented. For now the data is hard-coded here. Such targets are | ||
| 3214 | // { freebsd, netbsd, openbsd, dragonfly }. | ||
| 3215 | const CsuObjects = struct { | ||
| 3216 | crt0: ?[]const u8 = null, | ||
| 3217 | crti: ?[]const u8 = null, | ||
| 3218 | crtbegin: ?[]const u8 = null, | ||
| 3219 | crtend: ?[]const u8 = null, | ||
| 3220 | crtn: ?[]const u8 = null, | ||
| 3221 | |||
| 3222 | fn init(arena: *mem.Allocator, link_options: link.Options, comp: *const Compilation) !CsuObjects { | ||
| 3223 | // crt objects are only required for libc. | ||
| 3224 | if (!link_options.link_libc) return CsuObjects{}; | ||
| 3225 | |||
| 3226 | var result: CsuObjects = .{}; | ||
| 3227 | |||
| 3228 | // TODO: https://github.com/ziglang/zig/issues/4629 | ||
| 3229 | // - use inline enum type | ||
| 3230 | // - reduce to enum-literals for values | ||
| 3231 | const Mode = enum { | ||
| 3232 | dynamic_lib, | ||
| 3233 | dynamic_exe, | ||
| 3234 | dynamic_pie, | ||
| 3235 | static_exe, | ||
| 3236 | static_pie, | ||
| 3237 | }; | ||
| 3238 | |||
| 3239 | // Flatten crt case types. | ||
| 3240 | const mode: Mode = switch (link_options.output_mode) { | ||
| 3241 | .Obj => return CsuObjects{}, | ||
| 3242 | .Lib => switch (link_options.link_mode) { | ||
| 3243 | .Dynamic => Mode.dynamic_lib, | ||
| 3244 | .Static => return CsuObjects{}, | ||
| 3245 | }, | ||
| 3246 | .Exe => switch (link_options.link_mode) { | ||
| 3247 | .Dynamic => if (link_options.pie) Mode.dynamic_pie else Mode.dynamic_exe, | ||
| 3248 | .Static => if (link_options.pie) Mode.static_pie else Mode.static_exe, | ||
| 3249 | }, | ||
| 3250 | }; | ||
| 3251 | |||
| 3252 | if (link_options.target.isAndroid()) { | ||
| 3253 | switch (mode) { | ||
| 3254 | // zig fmt: off | ||
| 3255 | .dynamic_lib => result.set( null, null, "crtbegin_so.o", "crtend_so.o", null ), | ||
| 3256 | .dynamic_exe, | ||
| 3257 | .dynamic_pie => result.set( null, null, "crtbegin_dynamic.o", "crtend_android.o", null ), | ||
| 3258 | .static_exe, | ||
| 3259 | .static_pie => result.set( null, null, "crtbegin_static.o", "crtend_android.o", null ), | ||
| 3260 | // zig fmt: on | ||
| 3261 | } | ||
| 3262 | } else { | ||
| 3263 | switch (link_options.target.os.tag) { | ||
| 3264 | .linux => { | ||
| 3265 | switch (mode) { | ||
| 3266 | // zig fmt: off | ||
| 3267 | .dynamic_lib => result.set( null, "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), | ||
| 3268 | .dynamic_exe => result.set( "crt1.o", "crti.o", "crtbegin.o", "crtend.o", "crtn.o" ), | ||
| 3269 | .dynamic_pie => result.set( "Scrt1.o", "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), | ||
| 3270 | .static_exe => result.set( "crt1.o", "crti.o", "crtbeginT.o", "crtend.o", "crtn.o" ), | ||
| 3271 | .static_pie => result.set( "rcrt1.o", "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), | ||
| 3272 | // zig fmt: on | ||
| 3273 | } | ||
| 3274 | if (link_options.libc_installation) |_| { | ||
| 3275 | // hosted-glibc provides crtbegin/end objects in platform/compiler-specific dirs | ||
| 3276 | // and they are not known at comptime. For now null-out crtbegin/end objects; | ||
| 3277 | // there is no feature loss, zig has never linked those objects in before. | ||
| 3278 | // TODO: probe for paths, ie. `cc -print-file-name` | ||
| 3279 | result.crtbegin = null; | ||
| 3280 | result.crtend = null; | ||
| 3281 | } else { | ||
| 3282 | // Bundled glibc only has Scrt1.o . | ||
| 3283 | if (result.crt0 != null and link_options.target.isGnuLibC()) result.crt0 = "Scrt1.o"; | ||
| 3284 | } | ||
| 3285 | }, | ||
| 3286 | .dragonfly => switch (mode) { | ||
| 3287 | // zig fmt: off | ||
| 3288 | .dynamic_lib => result.set( null, "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), | ||
| 3289 | .dynamic_exe => result.set( "crt1.o", "crti.o", "crtbegin.o", "crtend.o", "crtn.o" ), | ||
| 3290 | .dynamic_pie => result.set( "Scrt1.o", "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), | ||
| 3291 | .static_exe => result.set( "crt1.o", "crti.o", "crtbegin.o", "crtend.o", "crtn.o" ), | ||
| 3292 | .static_pie => result.set( "Scrt1.o", "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), | ||
| 3293 | // zig fmt: on | ||
| 3294 | }, | ||
| 3295 | .freebsd => switch (mode) { | ||
| 3296 | // zig fmt: off | ||
| 3297 | .dynamic_lib => result.set( null, "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), | ||
| 3298 | .dynamic_exe => result.set( "crt1.o", "crti.o", "crtbegin.o", "crtend.o", "crtn.o" ), | ||
| 3299 | .dynamic_pie => result.set( "Scrt1.o", "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), | ||
| 3300 | .static_exe => result.set( "crt1.o", "crti.o", "crtbeginT.o", "crtend.o", "crtn.o" ), | ||
| 3301 | .static_pie => result.set( "Scrt1.o", "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), | ||
| 3302 | // zig fmt: on | ||
| 3303 | }, | ||
| 3304 | .netbsd => switch (mode) { | ||
| 3305 | // zig fmt: off | ||
| 3306 | .dynamic_lib => result.set( null, "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), | ||
| 3307 | .dynamic_exe => result.set( "crt0.o", "crti.o", "crtbegin.o", "crtend.o", "crtn.o" ), | ||
| 3308 | .dynamic_pie => result.set( "crt0.o", "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), | ||
| 3309 | .static_exe => result.set( "crt0.o", "crti.o", "crtbeginT.o", "crtend.o", "crtn.o" ), | ||
| 3310 | .static_pie => result.set( "crt0.o", "crti.o", "crtbeginT.o", "crtendS.o", "crtn.o" ), | ||
| 3311 | // zig fmt: on | ||
| 3312 | }, | ||
| 3313 | .openbsd => switch(mode) { | ||
| 3314 | // zig fmt: off | ||
| 3315 | .dynamic_lib => result.set( null, null, "crtbeginS.o", "crtendS.o", null ), | ||
| 3316 | .dynamic_exe, | ||
| 3317 | .dynamic_pie => result.set( "crt0.o", null, "crtbegin.o", "crtend.o", null ), | ||
| 3318 | .static_exe, | ||
| 3319 | .static_pie => result.set( "rcrt0.o", null, "crtbegin.o", "crtend.o", null ), | ||
| 3320 | // zig fmt: on | ||
| 3321 | }, | ||
| 3322 | else => {}, | ||
| 3323 | } | ||
| 3324 | } | ||
| 3325 | |||
| 3326 | // Convert each object to a full pathname. | ||
| 3327 | if (link_options.libc_installation) |lci| { | ||
| 3328 | const crt_dir_path = lci.crt_dir orelse return error.LibCInstallationMissingCRTDir; | ||
| 3329 | switch (link_options.target.os.tag) { | ||
| 3330 | .dragonfly => { | ||
| 3331 | if (result.crt0) |*obj| obj.* = try fs.path.join(arena, &[_][]const u8{ crt_dir_path, obj.* }); | ||
| 3332 | if (result.crti) |*obj| obj.* = try fs.path.join(arena, &[_][]const u8{ crt_dir_path, obj.* }); | ||
| 3333 | if (result.crtn) |*obj| obj.* = try fs.path.join(arena, &[_][]const u8{ crt_dir_path, obj.* }); | ||
| 3334 | |||
| 3335 | var gccv: []const u8 = undefined; | ||
| 3336 | if (link_options.target.os.version_range.semver.isAtLeast(.{ .major = 5, .minor = 4 }) orelse true) { | ||
| 3337 | gccv = "gcc80"; | ||
| 3338 | } else { | ||
| 3339 | gccv = "gcc54"; | ||
| 3340 | } | ||
| 3341 | |||
| 3342 | if (result.crtbegin) |*obj| obj.* = try fs.path.join(arena, &[_][]const u8{ crt_dir_path, gccv, obj.* }); | ||
| 3343 | if (result.crtend) |*obj| obj.* = try fs.path.join(arena, &[_][]const u8{ crt_dir_path, gccv, obj.* }); | ||
| 3344 | }, | ||
| 3345 | else => { | ||
| 3346 | inline for (std.meta.fields(@TypeOf(result))) |f,i| { | ||
| 3347 | if (@field(result, f.name)) |*obj| { | ||
| 3348 | obj.* = try fs.path.join(arena, &[_][]const u8{ crt_dir_path, obj.* }); | ||
| 3349 | } | ||
| 3350 | } | ||
| 3351 | } | ||
| 3352 | } | ||
| 3353 | } else { | ||
| 3354 | inline for (std.meta.fields(@TypeOf(result))) |f,i| { | ||
| 3355 | if (@field(result, f.name)) |*obj| { | ||
| 3356 | if (comp.crt_files.get(obj.*)) |crtf| { | ||
| 3357 | obj.* = crtf.full_object_path; | ||
| 3358 | } else { | ||
| 3359 | @field(result, f.name) = null; | ||
| 3360 | } | ||
| 3361 | } | ||
| 3362 | } | ||
| 3363 | } | ||
| 3364 | |||
| 3365 | return result; | ||
| 3366 | } | ||
| 3367 | |||
| 3368 | fn set( | ||
| 3369 | self: *CsuObjects, | ||
| 3370 | crt0: ?[]const u8, | ||
| 3371 | crti: ?[]const u8, | ||
| 3372 | crtbegin: ?[]const u8, | ||
| 3373 | crtend: ?[]const u8, | ||
| 3374 | crtn: ?[]const u8, | ||
| 3375 | ) void { | ||
| 3376 | self.crt0 = crt0; | ||
| 3377 | self.crti = crti; | ||
| 3378 | self.crtbegin = crtbegin; | ||
| 3379 | self.crtend = crtend; | ||
| 3380 | self.crtn = crtn; | ||
| 3381 | } | ||
| 3382 | }; |
src/musl.zig+41-12| ... | @@ -30,7 +30,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { | ... | @@ -30,7 +30,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { |
| 30 | switch (crt_file) { | 30 | switch (crt_file) { |
| 31 | .crti_o => { | 31 | .crti_o => { |
| 32 | var args = std.ArrayList([]const u8).init(arena); | 32 | var args = std.ArrayList([]const u8).init(arena); |
| 33 | try add_cc_args(comp, arena, &args, false); | 33 | try addCcArgs(comp, arena, &args, false); |
| 34 | try args.appendSlice(&[_][]const u8{ | 34 | try args.appendSlice(&[_][]const u8{ |
| 35 | "-Qunused-arguments", | 35 | "-Qunused-arguments", |
| 36 | }); | 36 | }); |
| ... | @@ -43,7 +43,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { | ... | @@ -43,7 +43,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { |
| 43 | }, | 43 | }, |
| 44 | .crtn_o => { | 44 | .crtn_o => { |
| 45 | var args = std.ArrayList([]const u8).init(arena); | 45 | var args = std.ArrayList([]const u8).init(arena); |
| 46 | try add_cc_args(comp, arena, &args, false); | 46 | try addCcArgs(comp, arena, &args, false); |
| 47 | try args.appendSlice(&[_][]const u8{ | 47 | try args.appendSlice(&[_][]const u8{ |
| 48 | "-Qunused-arguments", | 48 | "-Qunused-arguments", |
| 49 | }); | 49 | }); |
| ... | @@ -56,7 +56,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { | ... | @@ -56,7 +56,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { |
| 56 | }, | 56 | }, |
| 57 | .crt1_o => { | 57 | .crt1_o => { |
| 58 | var args = std.ArrayList([]const u8).init(arena); | 58 | var args = std.ArrayList([]const u8).init(arena); |
| 59 | try add_cc_args(comp, arena, &args, false); | 59 | try addCcArgs(comp, arena, &args, false); |
| 60 | try args.appendSlice(&[_][]const u8{ | 60 | try args.appendSlice(&[_][]const u8{ |
| 61 | "-fno-stack-protector", | 61 | "-fno-stack-protector", |
| 62 | "-DCRT", | 62 | "-DCRT", |
| ... | @@ -72,7 +72,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { | ... | @@ -72,7 +72,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { |
| 72 | }, | 72 | }, |
| 73 | .rcrt1_o => { | 73 | .rcrt1_o => { |
| 74 | var args = std.ArrayList([]const u8).init(arena); | 74 | var args = std.ArrayList([]const u8).init(arena); |
| 75 | try add_cc_args(comp, arena, &args, false); | 75 | try addCcArgs(comp, arena, &args, false); |
| 76 | try args.appendSlice(&[_][]const u8{ | 76 | try args.appendSlice(&[_][]const u8{ |
| 77 | "-fPIC", | 77 | "-fPIC", |
| 78 | "-fno-stack-protector", | 78 | "-fno-stack-protector", |
| ... | @@ -89,7 +89,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { | ... | @@ -89,7 +89,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { |
| 89 | }, | 89 | }, |
| 90 | .scrt1_o => { | 90 | .scrt1_o => { |
| 91 | var args = std.ArrayList([]const u8).init(arena); | 91 | var args = std.ArrayList([]const u8).init(arena); |
| 92 | try add_cc_args(comp, arena, &args, false); | 92 | try addCcArgs(comp, arena, &args, false); |
| 93 | try args.appendSlice(&[_][]const u8{ | 93 | try args.appendSlice(&[_][]const u8{ |
| 94 | "-fPIC", | 94 | "-fPIC", |
| 95 | "-fno-stack-protector", | 95 | "-fno-stack-protector", |
| ... | @@ -108,7 +108,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { | ... | @@ -108,7 +108,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { |
| 108 | // When there is a src/<arch>/foo.* then it should substitute for src/foo.* | 108 | // When there is a src/<arch>/foo.* then it should substitute for src/foo.* |
| 109 | // Even a .s file can substitute for a .c file. | 109 | // Even a .s file can substitute for a .c file. |
| 110 | const target = comp.getTarget(); | 110 | const target = comp.getTarget(); |
| 111 | const arch_name = target_util.archMuslName(target.cpu.arch); | 111 | const arch_name = archMuslName(target.cpu.arch); |
| 112 | var source_table = std.StringArrayHashMap(Ext).init(comp.gpa); | 112 | var source_table = std.StringArrayHashMap(Ext).init(comp.gpa); |
| 113 | defer source_table.deinit(); | 113 | defer source_table.deinit(); |
| 114 | 114 | ||
| ... | @@ -147,7 +147,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { | ... | @@ -147,7 +147,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { |
| 147 | 147 | ||
| 148 | var is_arch_specific = false; | 148 | var is_arch_specific = false; |
| 149 | // Architecture-specific implementations are under a <arch>/ folder. | 149 | // Architecture-specific implementations are under a <arch>/ folder. |
| 150 | if (is_musl_arch_name(dirbasename)) { | 150 | if (isMuslArchName(dirbasename)) { |
| 151 | if (!mem.eql(u8, dirbasename, arch_name)) | 151 | if (!mem.eql(u8, dirbasename, arch_name)) |
| 152 | continue; // Not the architecture we're compiling for. | 152 | continue; // Not the architecture we're compiling for. |
| 153 | is_arch_specific = true; | 153 | is_arch_specific = true; |
| ... | @@ -177,7 +177,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { | ... | @@ -177,7 +177,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { |
| 177 | } | 177 | } |
| 178 | 178 | ||
| 179 | var args = std.ArrayList([]const u8).init(arena); | 179 | var args = std.ArrayList([]const u8).init(arena); |
| 180 | try add_cc_args(comp, arena, &args, ext == .o3); | 180 | try addCcArgs(comp, arena, &args, ext == .o3); |
| 181 | try args.appendSlice(&[_][]const u8{ | 181 | try args.appendSlice(&[_][]const u8{ |
| 182 | "-Qunused-arguments", | 182 | "-Qunused-arguments", |
| 183 | "-w", // disable all warnings | 183 | "-w", // disable all warnings |
| ... | @@ -248,7 +248,36 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { | ... | @@ -248,7 +248,36 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { |
| 248 | } | 248 | } |
| 249 | } | 249 | } |
| 250 | 250 | ||
| 251 | fn is_musl_arch_name(name: []const u8) bool { | 251 | pub fn archMuslName(arch: std.Target.Cpu.Arch) [:0]const u8 { |
| 252 | switch (arch) { | ||
| 253 | .aarch64, .aarch64_be => return "aarch64", | ||
| 254 | .arm, .armeb, .thumb, .thumbeb => return "arm", | ||
| 255 | .i386 => return "i386", | ||
| 256 | .mips, .mipsel => return "mips", | ||
| 257 | .mips64el, .mips64 => return "mips64", | ||
| 258 | .powerpc => return "powerpc", | ||
| 259 | .powerpc64, .powerpc64le => return "powerpc64", | ||
| 260 | .riscv64 => return "riscv64", | ||
| 261 | .s390x => return "s390x", | ||
| 262 | .wasm32, .wasm64 => return "wasm", | ||
| 263 | .x86_64 => return "x86_64", | ||
| 264 | else => unreachable, | ||
| 265 | } | ||
| 266 | } | ||
| 267 | |||
| 268 | // Return true if musl has arch-specific crti/crtn sources. | ||
| 269 | // See lib/libc/musl/crt/ARCH/crt?.s . | ||
| 270 | pub fn needsCrtiCrtn(target: std.Target) bool { | ||
| 271 | // zig fmt: off | ||
| 272 | return switch (target.cpu.arch) { | ||
| 273 | .riscv64, | ||
| 274 | .wasm32, .wasm64 => return false, | ||
| 275 | else => true, | ||
| 276 | }; | ||
| 277 | // zig fmt: on | ||
| 278 | } | ||
| 279 | |||
| 280 | fn isMuslArchName(name: []const u8) bool { | ||
| 252 | const musl_arch_names = [_][]const u8{ | 281 | const musl_arch_names = [_][]const u8{ |
| 253 | "aarch64", | 282 | "aarch64", |
| 254 | "arm", | 283 | "arm", |
| ... | @@ -314,14 +343,14 @@ fn addSrcFile(arena: *Allocator, source_table: *std.StringArrayHashMap(Ext), fil | ... | @@ -314,14 +343,14 @@ fn addSrcFile(arena: *Allocator, source_table: *std.StringArrayHashMap(Ext), fil |
| 314 | source_table.putAssumeCapacityNoClobber(key, ext); | 343 | source_table.putAssumeCapacityNoClobber(key, ext); |
| 315 | } | 344 | } |
| 316 | 345 | ||
| 317 | fn add_cc_args( | 346 | fn addCcArgs( |
| 318 | comp: *Compilation, | 347 | comp: *Compilation, |
| 319 | arena: *Allocator, | 348 | arena: *Allocator, |
| 320 | args: *std.ArrayList([]const u8), | 349 | args: *std.ArrayList([]const u8), |
| 321 | want_O3: bool, | 350 | want_O3: bool, |
| 322 | ) error{OutOfMemory}!void { | 351 | ) error{OutOfMemory}!void { |
| 323 | const target = comp.getTarget(); | 352 | const target = comp.getTarget(); |
| 324 | const arch_name = target_util.archMuslName(target.cpu.arch); | 353 | const arch_name = archMuslName(target.cpu.arch); |
| 325 | const os_name = @tagName(target.os.tag); | 354 | const os_name = @tagName(target.os.tag); |
| 326 | const triple = try std.fmt.allocPrint(arena, "{s}-{s}-musl", .{ arch_name, os_name }); | 355 | const triple = try std.fmt.allocPrint(arena, "{s}-{s}-musl", .{ arch_name, os_name }); |
| 327 | const o_arg = if (want_O3) "-O3" else "-Os"; | 356 | const o_arg = if (want_O3) "-O3" else "-Os"; |
| ... | @@ -369,7 +398,7 @@ fn add_cc_args( | ... | @@ -369,7 +398,7 @@ fn add_cc_args( |
| 369 | fn start_asm_path(comp: *Compilation, arena: *Allocator, basename: []const u8) ![]const u8 { | 398 | fn start_asm_path(comp: *Compilation, arena: *Allocator, basename: []const u8) ![]const u8 { |
| 370 | const target = comp.getTarget(); | 399 | const target = comp.getTarget(); |
| 371 | return comp.zig_lib_directory.join(arena, &[_][]const u8{ | 400 | return comp.zig_lib_directory.join(arena, &[_][]const u8{ |
| 372 | "libc", "musl", "crt", target_util.archMuslName(target.cpu.arch), basename, | 401 | "libc", "musl", "crt", archMuslName(target.cpu.arch), basename, |
| 373 | }); | 402 | }); |
| 374 | } | 403 | } |
| 375 | 404 |
src/target.zig-21| ... | @@ -99,23 +99,6 @@ pub fn libCGenericName(target: std.Target) [:0]const u8 { | ... | @@ -99,23 +99,6 @@ pub fn libCGenericName(target: std.Target) [:0]const u8 { |
| 99 | } | 99 | } |
| 100 | } | 100 | } |
| 101 | 101 | ||
| 102 | pub fn archMuslName(arch: std.Target.Cpu.Arch) [:0]const u8 { | ||
| 103 | switch (arch) { | ||
| 104 | .aarch64, .aarch64_be => return "aarch64", | ||
| 105 | .arm, .armeb, .thumb, .thumbeb => return "arm", | ||
| 106 | .mips, .mipsel => return "mips", | ||
| 107 | .mips64el, .mips64 => return "mips64", | ||
| 108 | .powerpc => return "powerpc", | ||
| 109 | .powerpc64, .powerpc64le => return "powerpc64", | ||
| 110 | .s390x => return "s390x", | ||
| 111 | .i386 => return "i386", | ||
| 112 | .x86_64 => return "x86_64", | ||
| 113 | .riscv64 => return "riscv64", | ||
| 114 | .wasm32, .wasm64 => return "wasm", | ||
| 115 | else => unreachable, | ||
| 116 | } | ||
| 117 | } | ||
| 118 | |||
| 119 | pub fn canBuildLibC(target: std.Target) bool { | 102 | pub fn canBuildLibC(target: std.Target) bool { |
| 120 | for (available_libcs) |libc| { | 103 | for (available_libcs) |libc| { |
| 121 | if (target.cpu.arch == libc.arch and target.os.tag == libc.os and target.abi == libc.abi) { | 104 | if (target.cpu.arch == libc.arch and target.os.tag == libc.os and target.abi == libc.abi) { |
| ... | @@ -172,10 +155,6 @@ pub fn supports_fpic(target: std.Target) bool { | ... | @@ -172,10 +155,6 @@ pub fn supports_fpic(target: std.Target) bool { |
| 172 | return target.os.tag != .windows; | 155 | return target.os.tag != .windows; |
| 173 | } | 156 | } |
| 174 | 157 | ||
| 175 | pub fn libc_needs_crti_crtn(target: std.Target) bool { | ||
| 176 | return !(target.cpu.arch.isRISCV() or target.isAndroid() or target.os.tag == .openbsd); | ||
| 177 | } | ||
| 178 | |||
| 179 | pub fn isSingleThreaded(target: std.Target) bool { | 158 | pub fn isSingleThreaded(target: std.Target) bool { |
| 180 | return target.isWasm(); | 159 | return target.isWasm(); |
| 181 | } | 160 | } |
test/stack_traces.zig+1| ... | @@ -171,6 +171,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { | ... | @@ -171,6 +171,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { |
| 171 | 171 | ||
| 172 | cases.addCase(.{ | 172 | cases.addCase(.{ |
| 173 | .exclude_os = .{ | 173 | .exclude_os = .{ |
| 174 | .openbsd, // integer overflow | ||
| 174 | .windows, | 175 | .windows, |
| 175 | }, | 176 | }, |
| 176 | .name = "dumpCurrentStackTrace", | 177 | .name = "dumpCurrentStackTrace", |