From 89b0c634c129aa048b7677c555ea1302a5d15d46 Mon Sep 17 00:00:00 2001 From: Linus Groh Date: Sat, 2 May 2026 01:03:56 +0100 Subject: [PATCH 1/2] compiler: Enable PIE by default for serenity See: - https://github.com/SerenityOS/serenity/blob/727c4a3d1a6748221b383207dac354e564b6150d/Meta/CMake/serenity_compile_options.cmake#L15 - https://github.com/llvm/llvm-project/blob/62418bee5b9679c5b3bd536fb1101913b1c4e4d5/clang/lib/Driver/ToolChains/Serenity.h#L65 --- src/target.zig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/target.zig b/src/target.zig index 871a598239..71ac7a8ca3 100644 --- a/src/target.zig +++ b/src/target.zig @@ -85,7 +85,7 @@ pub fn supports_fpic(target: *const std.Target) bool { pub fn defaultPie(target: *const std.Target) bool { return switch (target.os.tag) { - .openbsd => true, + .openbsd, .serenity => true, else => target.os.tag.isDarwin(), }; } From 0f5de17d6dcf58c22d4070e45758e995bb9f1633 Mon Sep 17 00:00:00 2001 From: Linus Groh Date: Sat, 2 May 2026 01:04:58 +0100 Subject: [PATCH 2/2] std.zig.LibCInstallation: Add support for serenity Largely mirrors Haiku, Serenity provides crt0 and GCC the rest (though only crtbegin/crtend are used as per serenity's toolchain patches[1]): ``` $ find Build/aarch64/Root -iname 'crt*.o' Build/aarch64/Root/usr/local/lib/gcc/aarch64-serenity/15.2.0/crtbeginS.o Build/aarch64/Root/usr/local/lib/gcc/aarch64-serenity/15.2.0/crtend.o Build/aarch64/Root/usr/local/lib/gcc/aarch64-serenity/15.2.0/crtbegin.o Build/aarch64/Root/usr/local/lib/gcc/aarch64-serenity/15.2.0/crtfastmath.o Build/aarch64/Root/usr/local/lib/gcc/aarch64-serenity/15.2.0/crti.o Build/aarch64/Root/usr/local/lib/gcc/aarch64-serenity/15.2.0/crtn.o Build/aarch64/Root/usr/local/lib/gcc/aarch64-serenity/15.2.0/crtendS.o Build/aarch64/Root/usr/lib/crt0.o ``` Serenity has a GCC and LLVM toolchain that work equally well, support for the latter may be added in the future. [1]: https://github.com/SerenityOS/serenity/blob/727c4a3d1a6748221b383207dac354e564b6150d/Toolchain/Patches/gcc/0001-Add-a-gcc-driver-for-SerenityOS.patch#L120-L127 --- lib/std/zig/LibCInstallation.zig | 31 ++++++++++++++++++++++++++----- 1 file changed, 26 insertions(+), 5 deletions(-) diff --git a/lib/std/zig/LibCInstallation.zig b/lib/std/zig/LibCInstallation.zig index 09aaf0dea2..96265165bd 100644 --- a/lib/std/zig/LibCInstallation.zig +++ b/lib/std/zig/LibCInstallation.zig @@ -5,6 +5,7 @@ const builtin = @import("builtin"); const is_darwin = builtin.target.os.tag.isDarwin(); const is_windows = builtin.target.os.tag == .windows; const is_haiku = builtin.target.os.tag == .haiku; +const is_serenity = builtin.target.os.tag == .serenity; const std = @import("std"); const Io = std.Io; @@ -112,7 +113,7 @@ pub fn parse(allocator: Allocator, io: Io, libc_file: []const u8, target: *const return error.ParseError; } - if (self.gcc_dir == null and os_tag == .haiku) { + if (self.gcc_dir == null and (os_tag == .haiku or os_tag == .serenity)) { log.err("gcc_dir may not be empty for {s}", .{@tagName(os_tag)}); return error.ParseError; } @@ -207,8 +208,12 @@ pub fn findNative(gpa: Allocator, io: Io, args: FindNativeOptions) FindError!Lib try self.findNativeCrtDirWindows(gpa, io, args.target, sdk); } else if (is_haiku) { try self.findNativeIncludeDirPosix(gpa, io, args); - try self.findNativeGccDirHaiku(gpa, io, args); + try self.findNativeGccDirPosix(gpa, io, args); self.crt_dir = try gpa.dupe(u8, "/system/develop/lib"); + } else if (is_serenity) { + try self.findNativeIncludeDirPosix(gpa, io, args); + try self.findNativeGccDirPosix(gpa, io, args); + self.crt_dir = try gpa.dupe(u8, "/usr/lib"); } else if (builtin.target.os.tag == .illumos) { // There is only one libc, and its headers/libraries are always in the same spot. self.include_dir = try gpa.dupe(u8, "/usr/include"); @@ -314,7 +319,7 @@ fn findNativeIncludeDirPosix(self: *LibCInstallation, gpa: Allocator, io: Io, ar const include_dir_example_file = if (is_haiku) "posix/stdlib.h" else "stdlib.h"; const sys_include_dir_example_file = if (is_windows) "sys\\types.h" - else if (is_haiku) + else if (is_haiku or is_serenity) "errno.h" else "sys/errno.h"; @@ -457,7 +462,7 @@ fn findNativeCrtDirPosix(self: *LibCInstallation, gpa: Allocator, io: Io, args: }); } -fn findNativeGccDirHaiku(self: *LibCInstallation, gpa: Allocator, io: Io, args: FindNativeOptions) FindError!void { +fn findNativeGccDirPosix(self: *LibCInstallation, gpa: Allocator, io: Io, args: FindNativeOptions) FindError!void { self.gcc_dir = try ccPrintFileName(gpa, io, .{ .environ_map = args.environ_map, .search_basename = "crtbeginS.o", @@ -949,6 +954,22 @@ pub const CrtBasenames = struct { }, .static_exe, .static_pie => .{}, }, + .serenity => switch (mode) { + .dynamic_lib => .{ + .crtbegin = "crtbeginS.o", + .crtend = "crtendS.o", + }, + .dynamic_exe, .static_exe => .{ + .crt0 = "crt0.o", + .crtbegin = "crtbegin.o", + .crtend = "crtend.o", + }, + .dynamic_pie, .static_pie => .{ + .crt0 = "crt0.o", + .crtbegin = "crtbeginS.o", + .crtend = "crtendS.o", + }, + }, else => .{}, }; } @@ -993,7 +1014,7 @@ pub fn resolveCrtPaths( .crtn = if (crt_basenames.crtn) |basename| try crt_dir_path.join(arena, basename) else null, }; }, - .haiku => { + .haiku, .serenity => { const gcc_dir_path: Path = .{ .root_dir = std.Build.Cache.Directory.cwd(), .sub_path = lci.gcc_dir orelse return error.LibCInstallationMissingCrtDir,