| 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 | 576 | assert(c.pthread_threadid_np(null, &thread_id) == 0); |
| 577 | 577 | return thread_id; |
| 578 | 578 | }, |
| 579 | .dragonfly => { | |
| 580 | return @bitCast(u32, c.lwp_gettid()); | |
| 581 | }, | |
| 579 | 582 | .netbsd => { |
| 580 | 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 | 18 | pub const dl_iterate_phdr_callback = fn (info: *dl_phdr_info, size: usize, data: ?*c_void) callconv(.C) c_int; |
| 19 | 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 | 23 | pub extern "c" fn posix_memalign(memptr: *?*c_void, alignment: usize, size: usize) c_int; |
| 22 | 24 | |
| 23 | 25 | pub const pthread_mutex_t = extern struct { |
| ... | ... | @@ -31,3 +33,5 @@ pub const pthread_attr_t = extern struct { // copied from freebsd |
| 31 | 33 | __size: [56]u8, |
| 32 | 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 | 203 | // of space an ArrayList will allocate grows exponentially. |
| 204 | 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 | 210 | while (dead_fds < poll_fds.len) { |
| 207 | 211 | const events = try os.poll(&poll_fds, std.math.maxInt(i32)); |
| 208 | 212 | if (events == 0) continue; |
| ... | ... | @@ -215,7 +219,11 @@ pub const ChildProcess = struct { |
| 215 | 219 | try stdout.ensureCapacity(new_capacity); |
| 216 | 220 | const buf = stdout.unusedCapacitySlice(); |
| 217 | 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 | 228 | if (poll_fds[1].revents & os.POLLIN != 0) { |
| 221 | 229 | // stderr is ready. |
| ... | ... | @@ -223,7 +231,11 @@ pub const ChildProcess = struct { |
| 223 | 231 | try stderr.ensureCapacity(new_capacity); |
| 224 | 232 | const buf = stderr.unusedCapacitySlice(); |
| 225 | 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 | 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 | 767 | /// Hard limit |
| 768 | 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 | 376 | |
| 377 | 377 | test "test default_value with differents sizes" { |
| 378 | 378 | const testType = struct { |
| 379 | fn _testType(comptime T: type, value: T) void { | |
| 379 | fn _testType(comptime T: type, value: T) !void { | |
| 380 | 380 | var def: T = value; |
| 381 | 381 | var ctl = emutls_control.init(T, &def); |
| 382 | 382 | var x = ctl.get_typed_pointer(T); |
| ... | ... | @@ -384,11 +384,11 @@ test "test default_value with differents sizes" { |
| 384 | 384 | } |
| 385 | 385 | }._testType; |
| 386 | 386 | |
| 387 | testType(usize, 1234); | |
| 388 | testType(u32, 1234); | |
| 389 | testType(i16, -12); | |
| 390 | testType(f64, -12.0); | |
| 391 | testType( | |
| 387 | try testType(usize, 1234); | |
| 388 | try testType(u32, 1234); | |
| 389 | try testType(i16, -12); | |
| 390 | try testType(f64, -12.0); | |
| 391 | try testType( | |
| 392 | 392 | @TypeOf("012345678901234567890123456789"), |
| 393 | 393 | "012345678901234567890123456789", |
| 394 | 394 | ); |
src/Compilation.zig+2-2| ... | ... | @@ -1407,7 +1407,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation { |
| 1407 | 1407 | } |
| 1408 | 1408 | if (comp.wantBuildMuslFromSource()) { |
| 1409 | 1409 | try comp.work_queue.ensureUnusedCapacity(6); |
| 1410 | if (target_util.libc_needs_crti_crtn(comp.getTarget())) { | |
| 1410 | if (musl.needsCrtiCrtn(comp.getTarget())) { | |
| 1411 | 1411 | comp.work_queue.writeAssumeCapacity(&[_]Job{ |
| 1412 | 1412 | .{ .musl_crt_file = .crti_o }, |
| 1413 | 1413 | .{ .musl_crt_file = .crtn_o }, |
| ... | ... | @@ -3180,7 +3180,7 @@ fn detectLibCIncludeDirs( |
| 3180 | 3180 | const generic_name = target_util.libCGenericName(target); |
| 3181 | 3181 | // Some architectures are handled by the same set of headers. |
| 3182 | 3182 | const arch_name = if (target.abi.isMusl()) |
| 3183 | target_util.archMuslName(target.cpu.arch) | |
| 3183 | musl.archMuslName(target.cpu.arch) | |
| 3184 | 3184 | else if (target.cpu.arch.isThumb()) |
| 3185 | 3185 | // ARM headers are valid for Thumb too. |
| 3186 | 3186 | switch (target.cpu.arch) { |
src/libc_installation.zig+3-3| ... | ... | @@ -195,8 +195,8 @@ pub const LibCInstallation = struct { |
| 195 | 195 | errdefer batch.wait() catch {}; |
| 196 | 196 | batch.add(&async self.findNativeIncludeDirPosix(args)); |
| 197 | 197 | switch (Target.current.os.tag) { |
| 198 | .freebsd, .netbsd, .openbsd => self.crt_dir = try std.mem.dupeZ(args.allocator, u8, "/usr/lib"), | |
| 199 | .linux, .dragonfly => batch.add(&async self.findNativeCrtDirPosix(args)), | |
| 198 | .freebsd, .netbsd, .openbsd, .dragonfly => self.crt_dir = try std.mem.dupeZ(args.allocator, u8, "/usr/lib"), | |
| 199 | .linux => batch.add(&async self.findNativeCrtDirPosix(args)), | |
| 200 | 200 | .haiku => self.crt_dir = try std.mem.dupeZ(args.allocator, u8, "/system/develop/lib"), |
| 201 | 201 | else => {}, |
| 202 | 202 | } |
| ... | ... | @@ -523,7 +523,7 @@ pub const CCPrintFileNameOptions = struct { |
| 523 | 523 | }; |
| 524 | 524 | |
| 525 | 525 | /// caller owns returned memory |
| 526 | fn ccPrintFileName(args: CCPrintFileNameOptions) ![:0]u8 { | |
| 526 | pub fn ccPrintFileName(args: CCPrintFileNameOptions) ![:0]u8 { | |
| 527 | 527 | const allocator = args.allocator; |
| 528 | 528 | |
| 529 | 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 | 23 | const build_options = @import("build_options"); |
| 24 | 24 | const target_util = @import("../target.zig"); |
| 25 | 25 | const glibc = @import("../glibc.zig"); |
| 26 | const musl = @import("../musl.zig"); | |
| 26 | 27 | const Cache = @import("../Cache.zig"); |
| 27 | 28 | const llvm_backend = @import("../codegen/llvm.zig"); |
| 28 | 29 | |
| ... | ... | @@ -1278,7 +1279,6 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1278 | 1279 | const is_exe_or_dyn_lib = is_dyn_lib or self.base.options.output_mode == .Exe; |
| 1279 | 1280 | const have_dynamic_linker = self.base.options.link_libc and |
| 1280 | 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 | 1282 | const target = self.base.options.target; |
| 1283 | 1283 | const gc_sections = self.base.options.gc_sections orelse !is_obj; |
| 1284 | 1284 | const stack_size = self.base.options.stack_size_override orelse 16777216; |
| ... | ... | @@ -1499,40 +1499,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1499 | 1499 | try argv.append("-o"); |
| 1500 | 1500 | try argv.append(full_out_path); |
| 1501 | 1501 | |
| 1502 | if (link_in_crt) { | |
| 1503 | const crt1o: []const u8 = o: { | |
| 1504 | if (target.os.tag == .netbsd) { | |
| 1505 | break :o "crt0.o"; | |
| 1506 | } else if (target.os.tag == .openbsd) { | |
| 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 | } | |
| 1502 | // csu prelude | |
| 1503 | var csu = try CsuObjects.init(arena, self.base.options, comp); | |
| 1504 | if (csu.crt0) |v| try argv.append(v); | |
| 1505 | if (csu.crti) |v| try argv.append(v); | |
| 1506 | if (csu.crtbegin) |v| try argv.append(v); | |
| 1536 | 1507 | |
| 1537 | 1508 | // rpaths |
| 1538 | 1509 | var rpath_table = std.StringHashMap(void).init(self.base.allocator); |
| ... | ... | @@ -1676,16 +1647,9 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void { |
| 1676 | 1647 | } |
| 1677 | 1648 | } |
| 1678 | 1649 | |
| 1679 | // crt end | |
| 1680 | if (link_in_crt) { | |
| 1681 | if (target.isAndroid()) { | |
| 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 | } | |
| 1650 | // crt postlude | |
| 1651 | if (csu.crtend) |v| try argv.append(v); | |
| 1652 | if (csu.crtn) |v| try argv.append(v); | |
| 1689 | 1653 | |
| 1690 | 1654 | if (allow_shlib_undefined) { |
| 1691 | 1655 | try argv.append("--allow-shlib-undefined"); |
| ... | ... | @@ -3237,3 +3201,182 @@ fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) { |
| 3237 | 3201 | return std.math.add(@TypeOf(actual_size), actual_size, actual_size / ideal_factor) catch |
| 3238 | 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 | 30 | switch (crt_file) { |
| 31 | 31 | .crti_o => { |
| 32 | 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 | 34 | try args.appendSlice(&[_][]const u8{ |
| 35 | 35 | "-Qunused-arguments", |
| 36 | 36 | }); |
| ... | ... | @@ -43,7 +43,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { |
| 43 | 43 | }, |
| 44 | 44 | .crtn_o => { |
| 45 | 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 | 47 | try args.appendSlice(&[_][]const u8{ |
| 48 | 48 | "-Qunused-arguments", |
| 49 | 49 | }); |
| ... | ... | @@ -56,7 +56,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { |
| 56 | 56 | }, |
| 57 | 57 | .crt1_o => { |
| 58 | 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 | 60 | try args.appendSlice(&[_][]const u8{ |
| 61 | 61 | "-fno-stack-protector", |
| 62 | 62 | "-DCRT", |
| ... | ... | @@ -72,7 +72,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { |
| 72 | 72 | }, |
| 73 | 73 | .rcrt1_o => { |
| 74 | 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 | 76 | try args.appendSlice(&[_][]const u8{ |
| 77 | 77 | "-fPIC", |
| 78 | 78 | "-fno-stack-protector", |
| ... | ... | @@ -89,7 +89,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { |
| 89 | 89 | }, |
| 90 | 90 | .scrt1_o => { |
| 91 | 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 | 93 | try args.appendSlice(&[_][]const u8{ |
| 94 | 94 | "-fPIC", |
| 95 | 95 | "-fno-stack-protector", |
| ... | ... | @@ -108,7 +108,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { |
| 108 | 108 | // When there is a src/<arch>/foo.* then it should substitute for src/foo.* |
| 109 | 109 | // Even a .s file can substitute for a .c file. |
| 110 | 110 | const target = comp.getTarget(); |
| 111 | const arch_name = target_util.archMuslName(target.cpu.arch); | |
| 111 | const arch_name = archMuslName(target.cpu.arch); | |
| 112 | 112 | var source_table = std.StringArrayHashMap(Ext).init(comp.gpa); |
| 113 | 113 | defer source_table.deinit(); |
| 114 | 114 | |
| ... | ... | @@ -147,7 +147,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { |
| 147 | 147 | |
| 148 | 148 | var is_arch_specific = false; |
| 149 | 149 | // Architecture-specific implementations are under a <arch>/ folder. |
| 150 | if (is_musl_arch_name(dirbasename)) { | |
| 150 | if (isMuslArchName(dirbasename)) { | |
| 151 | 151 | if (!mem.eql(u8, dirbasename, arch_name)) |
| 152 | 152 | continue; // Not the architecture we're compiling for. |
| 153 | 153 | is_arch_specific = true; |
| ... | ... | @@ -177,7 +177,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void { |
| 177 | 177 | } |
| 178 | 178 | |
| 179 | 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 | 181 | try args.appendSlice(&[_][]const u8{ |
| 182 | 182 | "-Qunused-arguments", |
| 183 | 183 | "-w", // disable all warnings |
| ... | ... | @@ -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 | 281 | const musl_arch_names = [_][]const u8{ |
| 253 | 282 | "aarch64", |
| 254 | 283 | "arm", |
| ... | ... | @@ -314,14 +343,14 @@ fn addSrcFile(arena: *Allocator, source_table: *std.StringArrayHashMap(Ext), fil |
| 314 | 343 | source_table.putAssumeCapacityNoClobber(key, ext); |
| 315 | 344 | } |
| 316 | 345 | |
| 317 | fn add_cc_args( | |
| 346 | fn addCcArgs( | |
| 318 | 347 | comp: *Compilation, |
| 319 | 348 | arena: *Allocator, |
| 320 | 349 | args: *std.ArrayList([]const u8), |
| 321 | 350 | want_O3: bool, |
| 322 | 351 | ) error{OutOfMemory}!void { |
| 323 | 352 | const target = comp.getTarget(); |
| 324 | const arch_name = target_util.archMuslName(target.cpu.arch); | |
| 353 | const arch_name = archMuslName(target.cpu.arch); | |
| 325 | 354 | const os_name = @tagName(target.os.tag); |
| 326 | 355 | const triple = try std.fmt.allocPrint(arena, "{s}-{s}-musl", .{ arch_name, os_name }); |
| 327 | 356 | const o_arg = if (want_O3) "-O3" else "-Os"; |
| ... | ... | @@ -369,7 +398,7 @@ fn add_cc_args( |
| 369 | 398 | fn start_asm_path(comp: *Compilation, arena: *Allocator, basename: []const u8) ![]const u8 { |
| 370 | 399 | const target = comp.getTarget(); |
| 371 | 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 | 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 | 102 | pub fn canBuildLibC(target: std.Target) bool { |
| 120 | 103 | for (available_libcs) |libc| { |
| 121 | 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 | 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 | 158 | pub fn isSingleThreaded(target: std.Target) bool { |
| 180 | 159 | return target.isWasm(); |
| 181 | 160 | } |
test/stack_traces.zig+1| ... | ... | @@ -171,6 +171,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void { |
| 171 | 171 | |
| 172 | 172 | cases.addCase(.{ |
| 173 | 173 | .exclude_os = .{ |
| 174 | .openbsd, // integer overflow | |
| 174 | 175 | .windows, |
| 175 | 176 | }, |
| 176 | 177 | .name = "dumpCurrentStackTrace", |