mirror of
https://github.com/ziglang/zig.git
synced 2025-01-22 01:46:29 +00:00
overhaul elf csu (c-runtime startup) logic
- 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`
This commit is contained in:
parent
44e480aa2c
commit
0f26120377
@ -576,6 +576,9 @@ pub fn getCurrentThreadId() u64 {
|
||||
assert(c.pthread_threadid_np(null, &thread_id) == 0);
|
||||
return thread_id;
|
||||
},
|
||||
.dragonfly => {
|
||||
return @bitCast(u32, c.lwp_gettid());
|
||||
},
|
||||
.netbsd => {
|
||||
return @bitCast(u32, c._lwp_self());
|
||||
},
|
||||
|
@ -18,6 +18,8 @@ pub extern "c" fn pipe2(fds: *[2]fd_t, flags: u32) c_int;
|
||||
pub const dl_iterate_phdr_callback = fn (info: *dl_phdr_info, size: usize, data: ?*c_void) callconv(.C) c_int;
|
||||
pub extern "c" fn dl_iterate_phdr(callback: dl_iterate_phdr_callback, data: ?*c_void) c_int;
|
||||
|
||||
pub extern "c" fn lwp_gettid() c_int;
|
||||
|
||||
pub extern "c" fn posix_memalign(memptr: *?*c_void, alignment: usize, size: usize) c_int;
|
||||
|
||||
pub const pthread_mutex_t = extern struct {
|
||||
@ -31,3 +33,5 @@ pub const pthread_attr_t = extern struct { // copied from freebsd
|
||||
__size: [56]u8,
|
||||
__align: c_long,
|
||||
};
|
||||
|
||||
pub const sem_t = ?*opaque {};
|
||||
|
@ -203,6 +203,10 @@ pub const ChildProcess = struct {
|
||||
// of space an ArrayList will allocate grows exponentially.
|
||||
const bump_amt = 512;
|
||||
|
||||
// TODO https://github.com/ziglang/zig/issues/8724
|
||||
// parent process does not receive POLLHUP events
|
||||
const dragonfly_workaround = builtin.os.tag == .dragonfly;
|
||||
|
||||
while (dead_fds < poll_fds.len) {
|
||||
const events = try os.poll(&poll_fds, std.math.maxInt(i32));
|
||||
if (events == 0) continue;
|
||||
@ -215,7 +219,11 @@ pub const ChildProcess = struct {
|
||||
try stdout.ensureCapacity(new_capacity);
|
||||
const buf = stdout.unusedCapacitySlice();
|
||||
if (buf.len == 0) return error.StdoutStreamTooLong;
|
||||
stdout.items.len += try os.read(poll_fds[0].fd, buf);
|
||||
const nread = try os.read(poll_fds[0].fd, buf);
|
||||
stdout.items.len += nread;
|
||||
|
||||
// insert POLLHUP event because dragonfly fails to do so
|
||||
if (dragonfly_workaround and nread == 0) poll_fds[0].revents |= os.POLLHUP;
|
||||
}
|
||||
if (poll_fds[1].revents & os.POLLIN != 0) {
|
||||
// stderr is ready.
|
||||
@ -223,7 +231,11 @@ pub const ChildProcess = struct {
|
||||
try stderr.ensureCapacity(new_capacity);
|
||||
const buf = stderr.unusedCapacitySlice();
|
||||
if (buf.len == 0) return error.StderrStreamTooLong;
|
||||
stderr.items.len += try os.read(poll_fds[1].fd, buf);
|
||||
const nread = try os.read(poll_fds[1].fd, buf);
|
||||
stderr.items.len += nread;
|
||||
|
||||
// insert POLLHUP event because dragonfly fails to do so
|
||||
if (dragonfly_workaround and nread == 0) poll_fds[1].revents |= os.POLLHUP;
|
||||
}
|
||||
|
||||
// Exclude the fds that signaled an error.
|
||||
|
@ -767,3 +767,29 @@ pub const rlimit = extern struct {
|
||||
/// Hard limit
|
||||
max: rlim_t,
|
||||
};
|
||||
|
||||
pub const SHUT_RD = 0;
|
||||
pub const SHUT_WR = 1;
|
||||
pub const SHUT_RDWR = 2;
|
||||
|
||||
pub const nfds_t = u32;
|
||||
|
||||
pub const pollfd = extern struct {
|
||||
fd: fd_t,
|
||||
events: i16,
|
||||
revents: i16,
|
||||
};
|
||||
|
||||
/// Requestable events.
|
||||
pub const POLLIN = 0x0001;
|
||||
pub const POLLPRI = 0x0002;
|
||||
pub const POLLOUT = 0x0004;
|
||||
pub const POLLRDNORM = 0x0040;
|
||||
pub const POLLWRNORM = POLLOUT;
|
||||
pub const POLLRDBAND = 0x0080;
|
||||
pub const POLLWRBAND = 0x0100;
|
||||
|
||||
/// These events are set if they occur regardless of whether they were requested.
|
||||
pub const POLLERR = 0x0008;
|
||||
pub const POLLHUP = 0x0010;
|
||||
pub const POLLNVAL = 0x0020;
|
||||
|
@ -376,7 +376,7 @@ test "__emutls_get_address with default_value" {
|
||||
|
||||
test "test default_value with differents sizes" {
|
||||
const testType = struct {
|
||||
fn _testType(comptime T: type, value: T) void {
|
||||
fn _testType(comptime T: type, value: T) !void {
|
||||
var def: T = value;
|
||||
var ctl = emutls_control.init(T, &def);
|
||||
var x = ctl.get_typed_pointer(T);
|
||||
@ -384,11 +384,11 @@ test "test default_value with differents sizes" {
|
||||
}
|
||||
}._testType;
|
||||
|
||||
testType(usize, 1234);
|
||||
testType(u32, 1234);
|
||||
testType(i16, -12);
|
||||
testType(f64, -12.0);
|
||||
testType(
|
||||
try testType(usize, 1234);
|
||||
try testType(u32, 1234);
|
||||
try testType(i16, -12);
|
||||
try testType(f64, -12.0);
|
||||
try testType(
|
||||
@TypeOf("012345678901234567890123456789"),
|
||||
"012345678901234567890123456789",
|
||||
);
|
||||
|
@ -1407,7 +1407,7 @@ pub fn create(gpa: *Allocator, options: InitOptions) !*Compilation {
|
||||
}
|
||||
if (comp.wantBuildMuslFromSource()) {
|
||||
try comp.work_queue.ensureUnusedCapacity(6);
|
||||
if (target_util.libc_needs_crti_crtn(comp.getTarget())) {
|
||||
if (musl.needsCrtiCrtn(comp.getTarget())) {
|
||||
comp.work_queue.writeAssumeCapacity(&[_]Job{
|
||||
.{ .musl_crt_file = .crti_o },
|
||||
.{ .musl_crt_file = .crtn_o },
|
||||
@ -3180,7 +3180,7 @@ fn detectLibCIncludeDirs(
|
||||
const generic_name = target_util.libCGenericName(target);
|
||||
// Some architectures are handled by the same set of headers.
|
||||
const arch_name = if (target.abi.isMusl())
|
||||
target_util.archMuslName(target.cpu.arch)
|
||||
musl.archMuslName(target.cpu.arch)
|
||||
else if (target.cpu.arch.isThumb())
|
||||
// ARM headers are valid for Thumb too.
|
||||
switch (target.cpu.arch) {
|
||||
|
@ -195,8 +195,8 @@ pub const LibCInstallation = struct {
|
||||
errdefer batch.wait() catch {};
|
||||
batch.add(&async self.findNativeIncludeDirPosix(args));
|
||||
switch (Target.current.os.tag) {
|
||||
.freebsd, .netbsd, .openbsd => self.crt_dir = try std.mem.dupeZ(args.allocator, u8, "/usr/lib"),
|
||||
.linux, .dragonfly => batch.add(&async self.findNativeCrtDirPosix(args)),
|
||||
.freebsd, .netbsd, .openbsd, .dragonfly => self.crt_dir = try std.mem.dupeZ(args.allocator, u8, "/usr/lib"),
|
||||
.linux => batch.add(&async self.findNativeCrtDirPosix(args)),
|
||||
.haiku => self.crt_dir = try std.mem.dupeZ(args.allocator, u8, "/system/develop/lib"),
|
||||
else => {},
|
||||
}
|
||||
@ -523,7 +523,7 @@ pub const CCPrintFileNameOptions = struct {
|
||||
};
|
||||
|
||||
/// caller owns returned memory
|
||||
fn ccPrintFileName(args: CCPrintFileNameOptions) ![:0]u8 {
|
||||
pub fn ccPrintFileName(args: CCPrintFileNameOptions) ![:0]u8 {
|
||||
const allocator = args.allocator;
|
||||
|
||||
const cc_exe = std.os.getenvZ("CC") orelse default_cc_exe;
|
||||
|
233
src/link/Elf.zig
233
src/link/Elf.zig
@ -23,6 +23,7 @@ const File = link.File;
|
||||
const build_options = @import("build_options");
|
||||
const target_util = @import("../target.zig");
|
||||
const glibc = @import("../glibc.zig");
|
||||
const musl = @import("../musl.zig");
|
||||
const Cache = @import("../Cache.zig");
|
||||
const llvm_backend = @import("../codegen/llvm.zig");
|
||||
|
||||
@ -1278,7 +1279,6 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
|
||||
const is_exe_or_dyn_lib = is_dyn_lib or self.base.options.output_mode == .Exe;
|
||||
const have_dynamic_linker = self.base.options.link_libc and
|
||||
self.base.options.link_mode == .Dynamic and is_exe_or_dyn_lib;
|
||||
const link_in_crt = self.base.options.link_libc and self.base.options.output_mode == .Exe;
|
||||
const target = self.base.options.target;
|
||||
const gc_sections = self.base.options.gc_sections orelse !is_obj;
|
||||
const stack_size = self.base.options.stack_size_override orelse 16777216;
|
||||
@ -1499,40 +1499,11 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
|
||||
try argv.append("-o");
|
||||
try argv.append(full_out_path);
|
||||
|
||||
if (link_in_crt) {
|
||||
const crt1o: []const u8 = o: {
|
||||
if (target.os.tag == .netbsd) {
|
||||
break :o "crt0.o";
|
||||
} else if (target.os.tag == .openbsd) {
|
||||
if (self.base.options.link_mode == .Static) {
|
||||
break :o "rcrt0.o";
|
||||
} else {
|
||||
break :o "crt0.o";
|
||||
}
|
||||
} else if (target.isAndroid()) {
|
||||
if (self.base.options.link_mode == .Dynamic) {
|
||||
break :o "crtbegin_dynamic.o";
|
||||
} else {
|
||||
break :o "crtbegin_static.o";
|
||||
}
|
||||
} else if (self.base.options.link_mode == .Static) {
|
||||
if (self.base.options.pie) {
|
||||
break :o "rcrt1.o";
|
||||
} else {
|
||||
break :o "crt1.o";
|
||||
}
|
||||
} else {
|
||||
break :o "Scrt1.o";
|
||||
}
|
||||
};
|
||||
try argv.append(try comp.get_libc_crt_file(arena, crt1o));
|
||||
if (target_util.libc_needs_crti_crtn(target)) {
|
||||
try argv.append(try comp.get_libc_crt_file(arena, "crti.o"));
|
||||
}
|
||||
if (target.os.tag == .openbsd) {
|
||||
try argv.append(try comp.get_libc_crt_file(arena, "crtbegin.o"));
|
||||
}
|
||||
}
|
||||
// csu prelude
|
||||
var csu = try CsuObjects.init(arena, self.base.options, comp);
|
||||
if (csu.crt0) |v| try argv.append(v);
|
||||
if (csu.crti) |v| try argv.append(v);
|
||||
if (csu.crtbegin) |v| try argv.append(v);
|
||||
|
||||
// rpaths
|
||||
var rpath_table = std.StringHashMap(void).init(self.base.allocator);
|
||||
@ -1676,16 +1647,9 @@ fn linkWithLLD(self: *Elf, comp: *Compilation) !void {
|
||||
}
|
||||
}
|
||||
|
||||
// crt end
|
||||
if (link_in_crt) {
|
||||
if (target.isAndroid()) {
|
||||
try argv.append(try comp.get_libc_crt_file(arena, "crtend_android.o"));
|
||||
} else if (target.os.tag == .openbsd) {
|
||||
try argv.append(try comp.get_libc_crt_file(arena, "crtend.o"));
|
||||
} else if (target_util.libc_needs_crti_crtn(target)) {
|
||||
try argv.append(try comp.get_libc_crt_file(arena, "crtn.o"));
|
||||
}
|
||||
}
|
||||
// crt postlude
|
||||
if (csu.crtend) |v| try argv.append(v);
|
||||
if (csu.crtn) |v| try argv.append(v);
|
||||
|
||||
if (allow_shlib_undefined) {
|
||||
try argv.append("--allow-shlib-undefined");
|
||||
@ -3237,3 +3201,182 @@ fn padToIdeal(actual_size: anytype) @TypeOf(actual_size) {
|
||||
return std.math.add(@TypeOf(actual_size), actual_size, actual_size / ideal_factor) catch
|
||||
std.math.maxInt(@TypeOf(actual_size));
|
||||
}
|
||||
|
||||
// Provide a blueprint of csu (c-runtime startup) objects for supported
|
||||
// link modes.
|
||||
//
|
||||
// This is for cross-mode targets only. For host-mode targets the system
|
||||
// compiler can be probed to produce a robust blueprint.
|
||||
//
|
||||
// Targets requiring a libc for which zig does not bundle a libc are
|
||||
// host-mode targets. Unfortunately, host-mode probes are not yet
|
||||
// implemented. For now the data is hard-coded here. Such targets are
|
||||
// { freebsd, netbsd, openbsd, dragonfly }.
|
||||
const CsuObjects = struct {
|
||||
crt0: ?[]const u8 = null,
|
||||
crti: ?[]const u8 = null,
|
||||
crtbegin: ?[]const u8 = null,
|
||||
crtend: ?[]const u8 = null,
|
||||
crtn: ?[]const u8 = null,
|
||||
|
||||
fn init(arena: *mem.Allocator, link_options: link.Options, comp: *const Compilation) !CsuObjects {
|
||||
// crt objects are only required for libc.
|
||||
if (!link_options.link_libc) return CsuObjects{};
|
||||
|
||||
var result: CsuObjects = .{};
|
||||
|
||||
// TODO: https://github.com/ziglang/zig/issues/4629
|
||||
// - use inline enum type
|
||||
// - reduce to enum-literals for values
|
||||
const Mode = enum {
|
||||
dynamic_lib,
|
||||
dynamic_exe,
|
||||
dynamic_pie,
|
||||
static_exe,
|
||||
static_pie,
|
||||
};
|
||||
|
||||
// Flatten crt case types.
|
||||
const mode: Mode = switch (link_options.output_mode) {
|
||||
.Obj => return CsuObjects{},
|
||||
.Lib => switch (link_options.link_mode) {
|
||||
.Dynamic => Mode.dynamic_lib,
|
||||
.Static => return CsuObjects{},
|
||||
},
|
||||
.Exe => switch (link_options.link_mode) {
|
||||
.Dynamic => if (link_options.pie) Mode.dynamic_pie else Mode.dynamic_exe,
|
||||
.Static => if (link_options.pie) Mode.static_pie else Mode.static_exe,
|
||||
},
|
||||
};
|
||||
|
||||
if (link_options.target.isAndroid()) {
|
||||
switch (mode) {
|
||||
// zig fmt: off
|
||||
.dynamic_lib => result.set( null, null, "crtbegin_so.o", "crtend_so.o", null ),
|
||||
.dynamic_exe,
|
||||
.dynamic_pie => result.set( null, null, "crtbegin_dynamic.o", "crtend_android.o", null ),
|
||||
.static_exe,
|
||||
.static_pie => result.set( null, null, "crtbegin_static.o", "crtend_android.o", null ),
|
||||
// zig fmt: on
|
||||
}
|
||||
} else {
|
||||
switch (link_options.target.os.tag) {
|
||||
.linux => {
|
||||
switch (mode) {
|
||||
// zig fmt: off
|
||||
.dynamic_lib => result.set( null, "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ),
|
||||
.dynamic_exe => result.set( "crt1.o", "crti.o", "crtbegin.o", "crtend.o", "crtn.o" ),
|
||||
.dynamic_pie => result.set( "Scrt1.o", "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ),
|
||||
.static_exe => result.set( "crt1.o", "crti.o", "crtbeginT.o", "crtend.o", "crtn.o" ),
|
||||
.static_pie => result.set( "rcrt1.o", "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ),
|
||||
// zig fmt: on
|
||||
}
|
||||
if (link_options.libc_installation) |_| {
|
||||
// hosted-glibc provides crtbegin/end objects in platform/compiler-specific dirs
|
||||
// and they are not known at comptime. For now null-out crtbegin/end objects;
|
||||
// there is no feature loss, zig has never linked those objects in before.
|
||||
// TODO: probe for paths, ie. `cc -print-file-name`
|
||||
result.crtbegin = null;
|
||||
result.crtend = null;
|
||||
} else {
|
||||
// Bundled glibc only has Scrt1.o .
|
||||
if (result.crt0 != null and link_options.target.isGnuLibC()) result.crt0 = "Scrt1.o";
|
||||
}
|
||||
},
|
||||
.dragonfly => switch (mode) {
|
||||
// zig fmt: off
|
||||
.dynamic_lib => result.set( null, "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ),
|
||||
.dynamic_exe => result.set( "crt1.o", "crti.o", "crtbegin.o", "crtend.o", "crtn.o" ),
|
||||
.dynamic_pie => result.set( "Scrt1.o", "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ),
|
||||
.static_exe => result.set( "crt1.o", "crti.o", "crtbegin.o", "crtend.o", "crtn.o" ),
|
||||
.static_pie => result.set( "Scrt1.o", "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ),
|
||||
// zig fmt: on
|
||||
},
|
||||
.freebsd => switch (mode) {
|
||||
// zig fmt: off
|
||||
.dynamic_lib => result.set( null, "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ),
|
||||
.dynamic_exe => result.set( "crt1.o", "crti.o", "crtbegin.o", "crtend.o", "crtn.o" ),
|
||||
.dynamic_pie => result.set( "Scrt1.o", "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ),
|
||||
.static_exe => result.set( "crt1.o", "crti.o", "crtbeginT.o", "crtend.o", "crtn.o" ),
|
||||
.static_pie => result.set( "Scrt1.o", "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ),
|
||||
// zig fmt: on
|
||||
},
|
||||
.netbsd => switch (mode) {
|
||||
// zig fmt: off
|
||||
.dynamic_lib => result.set( null, "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ),
|
||||
.dynamic_exe => result.set( "crt0.o", "crti.o", "crtbegin.o", "crtend.o", "crtn.o" ),
|
||||
.dynamic_pie => result.set( "crt0.o", "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ),
|
||||
.static_exe => result.set( "crt0.o", "crti.o", "crtbeginT.o", "crtend.o", "crtn.o" ),
|
||||
.static_pie => result.set( "crt0.o", "crti.o", "crtbeginT.o", "crtendS.o", "crtn.o" ),
|
||||
// zig fmt: on
|
||||
},
|
||||
.openbsd => switch(mode) {
|
||||
// zig fmt: off
|
||||
.dynamic_lib => result.set( null, null, "crtbeginS.o", "crtendS.o", null ),
|
||||
.dynamic_exe,
|
||||
.dynamic_pie => result.set( "crt0.o", null, "crtbegin.o", "crtend.o", null ),
|
||||
.static_exe,
|
||||
.static_pie => result.set( "rcrt0.o", null, "crtbegin.o", "crtend.o", null ),
|
||||
// zig fmt: on
|
||||
},
|
||||
else => {},
|
||||
}
|
||||
}
|
||||
|
||||
// Convert each object to a full pathname.
|
||||
if (link_options.libc_installation) |lci| {
|
||||
const crt_dir_path = lci.crt_dir orelse return error.LibCInstallationMissingCRTDir;
|
||||
switch (link_options.target.os.tag) {
|
||||
.dragonfly => {
|
||||
if (result.crt0) |*obj| obj.* = try fs.path.join(arena, &[_][]const u8{ crt_dir_path, obj.* });
|
||||
if (result.crti) |*obj| obj.* = try fs.path.join(arena, &[_][]const u8{ crt_dir_path, obj.* });
|
||||
if (result.crtn) |*obj| obj.* = try fs.path.join(arena, &[_][]const u8{ crt_dir_path, obj.* });
|
||||
|
||||
var gccv: []const u8 = undefined;
|
||||
if (link_options.target.os.version_range.semver.isAtLeast(.{ .major = 5, .minor = 4 }) orelse true) {
|
||||
gccv = "gcc80";
|
||||
} else {
|
||||
gccv = "gcc54";
|
||||
}
|
||||
|
||||
if (result.crtbegin) |*obj| obj.* = try fs.path.join(arena, &[_][]const u8{ crt_dir_path, gccv, obj.* });
|
||||
if (result.crtend) |*obj| obj.* = try fs.path.join(arena, &[_][]const u8{ crt_dir_path, gccv, obj.* });
|
||||
},
|
||||
else => {
|
||||
inline for (std.meta.fields(@TypeOf(result))) |f,i| {
|
||||
if (@field(result, f.name)) |*obj| {
|
||||
obj.* = try fs.path.join(arena, &[_][]const u8{ crt_dir_path, obj.* });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
inline for (std.meta.fields(@TypeOf(result))) |f,i| {
|
||||
if (@field(result, f.name)) |*obj| {
|
||||
if (comp.crt_files.get(obj.*)) |crtf| {
|
||||
obj.* = crtf.full_object_path;
|
||||
} else {
|
||||
@field(result, f.name) = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
fn set(
|
||||
self: *CsuObjects,
|
||||
crt0: ?[]const u8,
|
||||
crti: ?[]const u8,
|
||||
crtbegin: ?[]const u8,
|
||||
crtend: ?[]const u8,
|
||||
crtn: ?[]const u8,
|
||||
) void {
|
||||
self.crt0 = crt0;
|
||||
self.crti = crti;
|
||||
self.crtbegin = crtbegin;
|
||||
self.crtend = crtend;
|
||||
self.crtn = crtn;
|
||||
}
|
||||
};
|
||||
|
53
src/musl.zig
53
src/musl.zig
@ -30,7 +30,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void {
|
||||
switch (crt_file) {
|
||||
.crti_o => {
|
||||
var args = std.ArrayList([]const u8).init(arena);
|
||||
try add_cc_args(comp, arena, &args, false);
|
||||
try addCcArgs(comp, arena, &args, false);
|
||||
try args.appendSlice(&[_][]const u8{
|
||||
"-Qunused-arguments",
|
||||
});
|
||||
@ -43,7 +43,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void {
|
||||
},
|
||||
.crtn_o => {
|
||||
var args = std.ArrayList([]const u8).init(arena);
|
||||
try add_cc_args(comp, arena, &args, false);
|
||||
try addCcArgs(comp, arena, &args, false);
|
||||
try args.appendSlice(&[_][]const u8{
|
||||
"-Qunused-arguments",
|
||||
});
|
||||
@ -56,7 +56,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void {
|
||||
},
|
||||
.crt1_o => {
|
||||
var args = std.ArrayList([]const u8).init(arena);
|
||||
try add_cc_args(comp, arena, &args, false);
|
||||
try addCcArgs(comp, arena, &args, false);
|
||||
try args.appendSlice(&[_][]const u8{
|
||||
"-fno-stack-protector",
|
||||
"-DCRT",
|
||||
@ -72,7 +72,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void {
|
||||
},
|
||||
.rcrt1_o => {
|
||||
var args = std.ArrayList([]const u8).init(arena);
|
||||
try add_cc_args(comp, arena, &args, false);
|
||||
try addCcArgs(comp, arena, &args, false);
|
||||
try args.appendSlice(&[_][]const u8{
|
||||
"-fPIC",
|
||||
"-fno-stack-protector",
|
||||
@ -89,7 +89,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void {
|
||||
},
|
||||
.scrt1_o => {
|
||||
var args = std.ArrayList([]const u8).init(arena);
|
||||
try add_cc_args(comp, arena, &args, false);
|
||||
try addCcArgs(comp, arena, &args, false);
|
||||
try args.appendSlice(&[_][]const u8{
|
||||
"-fPIC",
|
||||
"-fno-stack-protector",
|
||||
@ -108,7 +108,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void {
|
||||
// When there is a src/<arch>/foo.* then it should substitute for src/foo.*
|
||||
// Even a .s file can substitute for a .c file.
|
||||
const target = comp.getTarget();
|
||||
const arch_name = target_util.archMuslName(target.cpu.arch);
|
||||
const arch_name = archMuslName(target.cpu.arch);
|
||||
var source_table = std.StringArrayHashMap(Ext).init(comp.gpa);
|
||||
defer source_table.deinit();
|
||||
|
||||
@ -147,7 +147,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void {
|
||||
|
||||
var is_arch_specific = false;
|
||||
// Architecture-specific implementations are under a <arch>/ folder.
|
||||
if (is_musl_arch_name(dirbasename)) {
|
||||
if (isMuslArchName(dirbasename)) {
|
||||
if (!mem.eql(u8, dirbasename, arch_name))
|
||||
continue; // Not the architecture we're compiling for.
|
||||
is_arch_specific = true;
|
||||
@ -177,7 +177,7 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void {
|
||||
}
|
||||
|
||||
var args = std.ArrayList([]const u8).init(arena);
|
||||
try add_cc_args(comp, arena, &args, ext == .o3);
|
||||
try addCcArgs(comp, arena, &args, ext == .o3);
|
||||
try args.appendSlice(&[_][]const u8{
|
||||
"-Qunused-arguments",
|
||||
"-w", // disable all warnings
|
||||
@ -248,7 +248,36 @@ pub fn buildCRTFile(comp: *Compilation, crt_file: CRTFile) !void {
|
||||
}
|
||||
}
|
||||
|
||||
fn is_musl_arch_name(name: []const u8) bool {
|
||||
pub fn archMuslName(arch: std.Target.Cpu.Arch) [:0]const u8 {
|
||||
switch (arch) {
|
||||
.aarch64, .aarch64_be => return "aarch64",
|
||||
.arm, .armeb, .thumb, .thumbeb => return "arm",
|
||||
.i386 => return "i386",
|
||||
.mips, .mipsel => return "mips",
|
||||
.mips64el, .mips64 => return "mips64",
|
||||
.powerpc => return "powerpc",
|
||||
.powerpc64, .powerpc64le => return "powerpc64",
|
||||
.riscv64 => return "riscv64",
|
||||
.s390x => return "s390x",
|
||||
.wasm32, .wasm64 => return "wasm",
|
||||
.x86_64 => return "x86_64",
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
// Return true if musl has arch-specific crti/crtn sources.
|
||||
// See lib/libc/musl/crt/ARCH/crt?.s .
|
||||
pub fn needsCrtiCrtn(target: std.Target) bool {
|
||||
// zig fmt: off
|
||||
return switch (target.cpu.arch) {
|
||||
.riscv64,
|
||||
.wasm32, .wasm64 => return false,
|
||||
else => true,
|
||||
};
|
||||
// zig fmt: on
|
||||
}
|
||||
|
||||
fn isMuslArchName(name: []const u8) bool {
|
||||
const musl_arch_names = [_][]const u8{
|
||||
"aarch64",
|
||||
"arm",
|
||||
@ -314,14 +343,14 @@ fn addSrcFile(arena: *Allocator, source_table: *std.StringArrayHashMap(Ext), fil
|
||||
source_table.putAssumeCapacityNoClobber(key, ext);
|
||||
}
|
||||
|
||||
fn add_cc_args(
|
||||
fn addCcArgs(
|
||||
comp: *Compilation,
|
||||
arena: *Allocator,
|
||||
args: *std.ArrayList([]const u8),
|
||||
want_O3: bool,
|
||||
) error{OutOfMemory}!void {
|
||||
const target = comp.getTarget();
|
||||
const arch_name = target_util.archMuslName(target.cpu.arch);
|
||||
const arch_name = archMuslName(target.cpu.arch);
|
||||
const os_name = @tagName(target.os.tag);
|
||||
const triple = try std.fmt.allocPrint(arena, "{s}-{s}-musl", .{ arch_name, os_name });
|
||||
const o_arg = if (want_O3) "-O3" else "-Os";
|
||||
@ -369,7 +398,7 @@ fn add_cc_args(
|
||||
fn start_asm_path(comp: *Compilation, arena: *Allocator, basename: []const u8) ![]const u8 {
|
||||
const target = comp.getTarget();
|
||||
return comp.zig_lib_directory.join(arena, &[_][]const u8{
|
||||
"libc", "musl", "crt", target_util.archMuslName(target.cpu.arch), basename,
|
||||
"libc", "musl", "crt", archMuslName(target.cpu.arch), basename,
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -99,23 +99,6 @@ pub fn libCGenericName(target: std.Target) [:0]const u8 {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn archMuslName(arch: std.Target.Cpu.Arch) [:0]const u8 {
|
||||
switch (arch) {
|
||||
.aarch64, .aarch64_be => return "aarch64",
|
||||
.arm, .armeb, .thumb, .thumbeb => return "arm",
|
||||
.mips, .mipsel => return "mips",
|
||||
.mips64el, .mips64 => return "mips64",
|
||||
.powerpc => return "powerpc",
|
||||
.powerpc64, .powerpc64le => return "powerpc64",
|
||||
.s390x => return "s390x",
|
||||
.i386 => return "i386",
|
||||
.x86_64 => return "x86_64",
|
||||
.riscv64 => return "riscv64",
|
||||
.wasm32, .wasm64 => return "wasm",
|
||||
else => unreachable,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn canBuildLibC(target: std.Target) bool {
|
||||
for (available_libcs) |libc| {
|
||||
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 {
|
||||
return target.os.tag != .windows;
|
||||
}
|
||||
|
||||
pub fn libc_needs_crti_crtn(target: std.Target) bool {
|
||||
return !(target.cpu.arch.isRISCV() or target.isAndroid() or target.os.tag == .openbsd);
|
||||
}
|
||||
|
||||
pub fn isSingleThreaded(target: std.Target) bool {
|
||||
return target.isWasm();
|
||||
}
|
||||
|
@ -171,6 +171,7 @@ pub fn addCases(cases: *tests.StackTracesContext) void {
|
||||
|
||||
cases.addCase(.{
|
||||
.exclude_os = .{
|
||||
.openbsd, // integer overflow
|
||||
.windows,
|
||||
},
|
||||
.name = "dumpCurrentStackTrace",
|
||||
|
Loading…
Reference in New Issue
Block a user