diff --git a/lib/std/debug.zig b/lib/std/debug.zig index bfaf6f0df4..8da1dbe673 100644 --- a/lib/std/debug.zig +++ b/lib/std/debug.zig @@ -1686,7 +1686,7 @@ pub const ModuleDebugInfo = switch (native_os) { }; } }, - .linux, .netbsd, .freebsd, .dragonfly, .openbsd => struct { + .linux, .netbsd, .freebsd, .dragonfly, .openbsd, .haiku => struct { base_address: usize, dwarf: DW.DwarfInfo, mapped_memory: []const u8, diff --git a/lib/std/process.zig b/lib/std/process.zig index 8b49e84a8c..f026c640e0 100644 --- a/lib/std/process.zig +++ b/lib/std/process.zig @@ -800,7 +800,10 @@ pub fn getSelfExeSharedLibPaths(allocator: *Allocator) error{OutOfMemory}![][:0] } /// Tells whether calling the `execv` or `execve` functions will be a compile error. -pub const can_execv = std.builtin.os.tag != .windows; +pub const can_execv = switch (builtin.os.tag) { + .windows, .haiku => false, + else => true, +}; pub const ExecvError = std.os.ExecveError || error{OutOfMemory}; diff --git a/src/libc_installation.zig b/src/libc_installation.zig index 66ff8f77fd..b9f0f0ecc7 100644 --- a/src/libc_installation.zig +++ b/src/libc_installation.zig @@ -21,6 +21,7 @@ pub const LibCInstallation = struct { crt_dir: ?[]const u8 = null, msvc_lib_dir: ?[]const u8 = null, kernel32_lib_dir: ?[]const u8 = null, + gcc_dir: ?[]const u8 = null, pub const FindError = error{ OutOfMemory, @@ -113,6 +114,10 @@ pub const LibCInstallation = struct { }); return error.ParseError; } + if (self.gcc_dir == null and is_haiku) { + log.err("gcc_dir may not be empty for {s}\n", .{@tagName(Target.current.os.tag)}); + return error.ParseError; + } return self; } @@ -124,6 +129,7 @@ pub const LibCInstallation = struct { const crt_dir = self.crt_dir orelse ""; const msvc_lib_dir = self.msvc_lib_dir orelse ""; const kernel32_lib_dir = self.kernel32_lib_dir orelse ""; + const gcc_dir = self.gcc_dir orelse ""; try out.print( \\# The directory that contains `stdlib.h`. @@ -148,12 +154,17 @@ pub const LibCInstallation = struct { \\# Only needed when targeting MSVC on Windows. \\kernel32_lib_dir={s} \\ + \\# The directory that contains `crtbeginS.o` and `crtendS.o` + \\# Only needed when targeting Haiku. + \\gcc_dir={s} + \\ , .{ include_dir, sys_include_dir, crt_dir, msvc_lib_dir, kernel32_lib_dir, + gcc_dir, }); } @@ -188,6 +199,15 @@ pub const LibCInstallation = struct { .NotFound => return error.WindowsSdkNotFound, .PathTooLong => return error.WindowsSdkNotFound, } + } else if (is_haiku) { + try blk: { + var batch = Batch(FindError!void, 2, .auto_async).init(); + errdefer batch.wait() catch {}; + batch.add(&async self.findNativeIncludeDirPosix(args)); + batch.add(&async self.findNativeCrtBeginDirHaiku(args)); + self.crt_dir = try std.mem.dupeZ(args.allocator, u8, "/system/develop/lib"); + break :blk batch.wait(); + }; } else { try blk: { var batch = Batch(FindError!void, 2, .auto_async).init(); @@ -196,7 +216,6 @@ pub const LibCInstallation = struct { switch (Target.current.os.tag) { .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 => {}, } break :blk batch.wait(); @@ -422,6 +441,15 @@ pub const LibCInstallation = struct { }); } + fn findNativeCrtBeginDirHaiku(self: *LibCInstallation, args: FindNativeOptions) FindError!void { + self.gcc_dir = try ccPrintFileName(.{ + .allocator = args.allocator, + .search_basename = "crtbeginS.o", + .want_dirname = .only_dir, + .verbose = args.verbose, + }); + } + fn findNativeKernel32LibDir( self: *LibCInstallation, args: FindNativeOptions, diff --git a/src/link/Elf.zig b/src/link/Elf.zig index 693ae3f83c..599d6fa2bf 100644 --- a/src/link/Elf.zig +++ b/src/link/Elf.zig @@ -3310,7 +3310,7 @@ const CsuObjects = struct { .static_pie => result.set( "crt0.o", "crti.o", "crtbeginT.o", "crtendS.o", "crtn.o" ), // zig fmt: on }, - .openbsd => switch(mode) { + .openbsd => switch (mode) { // zig fmt: off .dynamic_lib => result.set( null, null, "crtbeginS.o", "crtendS.o", null ), .dynamic_exe, @@ -3319,6 +3319,15 @@ const CsuObjects = struct { .static_pie => result.set( "rcrt0.o", null, "crtbegin.o", "crtend.o", null ), // zig fmt: on }, + .haiku => switch (mode) { + // zig fmt: off + .dynamic_lib => result.set( null, "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), + .dynamic_exe => result.set( "start_dyn.o", "crti.o", "crtbegin.o", "crtend.o", "crtn.o" ), + .dynamic_pie => result.set( "start_dyn.o", "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), + .static_exe => result.set( "start_dyn.o", "crti.o", "crtbegin.o", "crtend.o", "crtn.o" ), + .static_pie => result.set( "start_dyn.o", "crti.o", "crtbeginS.o", "crtendS.o", "crtn.o" ), + // zig fmt: on + }, else => {}, } } @@ -3342,16 +3351,25 @@ const CsuObjects = struct { 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.* }); }, + .haiku => { + const gcc_dir_path = lci.gcc_dir orelse return error.LibCInstallationMissingCRTDir; + 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.* }); + + if (result.crtbegin) |*obj| obj.* = try fs.path.join(arena, &[_][]const u8{ gcc_dir_path, obj.* }); + if (result.crtend) |*obj| obj.* = try fs.path.join(arena, &[_][]const u8{ gcc_dir_path, obj.* }); + }, else => { - inline for (std.meta.fields(@TypeOf(result))) |f,i| { + 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| { + 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; diff --git a/src/target.zig b/src/target.zig index b4e6123819..59be06f296 100644 --- a/src/target.zig +++ b/src/target.zig @@ -366,6 +366,12 @@ pub fn libcFullLinkFlags(target: std.Target) []const []const u8 { "-lc", "-lutil", }, + .haiku => &[_][]const u8{ + "-lm", + "-lroot", + "-lpthread", + "-lc", + }, else => switch (target.abi) { .android => &[_][]const u8{ "-lm",