compiler: Support building FreeBSD crt1.o/Scrt1.o and stub shared libraries.

Only works for FreeBSD 14+. Note that we still default to targeting FreeBSD 13.

Contributes to #2876.
This commit is contained in:
Alex Rønne Petersen 2025-05-05 07:23:28 +02:00
parent 0e3609b8e0
commit d3a6236eef
No known key found for this signature in database
4 changed files with 1172 additions and 2 deletions

View File

@ -586,6 +586,7 @@ set(ZIG_STAGE2_SOURCES
src/codegen/spirv/spec.zig
src/crash_report.zig
src/dev.zig
src/libs/freebsd.zig
src/libs/glibc.zig
src/introspect.zig
src/libs/libcxx.zig

View File

@ -23,6 +23,7 @@ const build_options = @import("build_options");
const LibCInstallation = std.zig.LibCInstallation;
const glibc = @import("libs/glibc.zig");
const musl = @import("libs/musl.zig");
const freebsd = @import("libs/freebsd.zig");
const mingw = @import("libs/mingw.zig");
const libunwind = @import("libs/libunwind.zig");
const libcxx = @import("libs/libcxx.zig");
@ -248,6 +249,7 @@ compiler_rt_obj: ?CrtFile = null,
fuzzer_lib: ?CrtFile = null,
glibc_so_files: ?glibc.BuiltSharedObjects = null,
freebsd_so_files: ?freebsd.BuiltSharedObjects = null,
wasi_emulated_libs: []const wasi_libc.CrtFile,
/// For example `Scrt1.o` and `libc_nonshared.a`. These are populated after building libc from source,
@ -294,12 +296,14 @@ const QueuedJobs = struct {
update_builtin_zig: bool,
musl_crt_file: [@typeInfo(musl.CrtFile).@"enum".fields.len]bool = @splat(false),
glibc_crt_file: [@typeInfo(glibc.CrtFile).@"enum".fields.len]bool = @splat(false),
freebsd_crt_file: [@typeInfo(freebsd.CrtFile).@"enum".fields.len]bool = @splat(false),
/// one of WASI libc static objects
wasi_libc_crt_file: [@typeInfo(wasi_libc.CrtFile).@"enum".fields.len]bool = @splat(false),
/// one of the mingw-w64 static objects
mingw_crt_file: [@typeInfo(mingw.CrtFile).@"enum".fields.len]bool = @splat(false),
/// all of the glibc shared objects
glibc_shared_objects: bool = false,
freebsd_shared_objects: bool = false,
/// libunwind.a, usually needed when linking libc
libunwind: bool = false,
libcxx: bool = false,
@ -789,6 +793,8 @@ pub const MiscTask = enum {
glibc_crt_file,
glibc_shared_objects,
musl_crt_file,
freebsd_crt_file,
freebsd_shared_objects,
mingw_crt_file,
windows_import_lib,
libunwind,
@ -823,6 +829,9 @@ pub const MiscTask = enum {
@"glibc libc_nonshared.a",
@"glibc shared object",
@"freebsd libc Scrt1.o",
@"freebsd libc shared object",
@"mingw-w64 crt2.o",
@"mingw-w64 dllcrt2.o",
@"mingw-w64 libmingw32.lib",
@ -1874,6 +1883,16 @@ pub fn create(gpa: Allocator, arena: Allocator, options: CreateOptions) !*Compil
comp.queued_jobs.glibc_crt_file[@intFromEnum(glibc.CrtFile.libc_nonshared_a)] = true;
comp.remaining_prelink_tasks += 1;
} else if (target.isFreeBSDLibC()) {
if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;
if (freebsd.needsCrt0(comp.config.output_mode)) |f| {
comp.queued_jobs.freebsd_crt_file[@intFromEnum(f)] = true;
comp.remaining_prelink_tasks += 1;
}
comp.queued_jobs.freebsd_shared_objects = true;
comp.remaining_prelink_tasks += freebsd.sharedObjectsCount();
} else if (target.isWasiLibC()) {
if (!std.zig.target.canBuildLibC(target)) return error.LibCUnavailable;
@ -2028,6 +2047,10 @@ pub fn destroy(comp: *Compilation) void {
glibc_file.deinit(gpa);
}
if (comp.freebsd_so_files) |*freebsd_file| {
freebsd_file.deinit(gpa);
}
for (comp.c_object_table.keys()) |key| {
key.destroy(gpa);
}
@ -3839,6 +3862,10 @@ fn performAllTheWorkInner(
comp.link_task_wait_group.spawnManager(buildGlibcSharedObjects, .{ comp, main_progress_node });
}
if (comp.queued_jobs.freebsd_shared_objects) {
comp.link_task_wait_group.spawnManager(buildFreeBSDSharedObjects, .{ comp, main_progress_node });
}
if (comp.queued_jobs.libunwind) {
comp.link_task_wait_group.spawnManager(buildLibUnwind, .{ comp, main_progress_node });
}
@ -3873,6 +3900,13 @@ fn performAllTheWorkInner(
}
}
for (0..@typeInfo(freebsd.CrtFile).@"enum".fields.len) |i| {
if (comp.queued_jobs.freebsd_crt_file[i]) {
const tag: freebsd.CrtFile = @enumFromInt(i);
comp.link_task_wait_group.spawnManager(buildFreeBSDCrtFile, .{ comp, tag, main_progress_node });
}
}
for (0..@typeInfo(wasi_libc.CrtFile).@"enum".fields.len) |i| {
if (comp.queued_jobs.wasi_libc_crt_file[i]) {
const tag: wasi_libc.CrtFile = @enumFromInt(i);
@ -4876,6 +4910,29 @@ fn buildGlibcSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) voi
}
}
fn buildFreeBSDCrtFile(comp: *Compilation, crt_file: freebsd.CrtFile, prog_node: std.Progress.Node) void {
if (freebsd.buildCrtFile(comp, crt_file, prog_node)) |_| {
comp.queued_jobs.freebsd_crt_file[@intFromEnum(crt_file)] = false;
} else |err| switch (err) {
error.SubCompilationFailed => return, // error reported already
else => comp.lockAndSetMiscFailure(.freebsd_crt_file, "unable to build FreeBSD {s}: {s}", .{
@tagName(crt_file), @errorName(err),
}),
}
}
fn buildFreeBSDSharedObjects(comp: *Compilation, prog_node: std.Progress.Node) void {
if (freebsd.buildSharedObjects(comp, prog_node)) |_| {
// The job should no longer be queued up since it succeeded.
comp.queued_jobs.freebsd_shared_objects = false;
} else |err| switch (err) {
error.SubCompilationFailed => return, // error reported already
else => comp.lockAndSetMiscFailure(.freebsd_shared_objects, "unable to build FreeBSD libc shared objects: {s}", .{
@errorName(err),
}),
}
}
fn buildMingwCrtFile(comp: *Compilation, crt_file: mingw.CrtFile, prog_node: std.Progress.Node) void {
if (mingw.buildCrtFile(comp, crt_file, prog_node)) |_| {
comp.queued_jobs.mingw_crt_file[@intFromEnum(crt_file)] = false;

1104
src/libs/freebsd.zig Normal file

File diff suppressed because it is too large Load Diff

View File

@ -2058,11 +2058,18 @@ fn linkWithLLD(self: *Elf, arena: Allocator, tid: Zcu.PerThread.Id, prog_node: s
try argv.append(lib_path);
}
try argv.append(try comp.crtFileAsString(arena, "libc_nonshared.a"));
} else if (target.abi.isMusl()) {
} else if (target.isMuslLibC()) {
try argv.append(try comp.crtFileAsString(arena, switch (link_mode) {
.static => "libc.a",
.dynamic => "libc.so",
}));
} else if (target.isFreeBSDLibC()) {
for (freebsd.libs) |lib| {
const lib_path = try std.fmt.allocPrint(arena, "{}{c}lib{s}.so.{d}", .{
comp.freebsd_so_files.?.dir_path, fs.path.sep, lib.name, lib.sover,
});
try argv.append(lib_path);
}
} else {
diags.flags.missing_libc = true;
}
@ -5280,8 +5287,9 @@ const dev = @import("../dev.zig");
const eh_frame = @import("Elf/eh_frame.zig");
const gc = @import("Elf/gc.zig");
const glibc = @import("../libs/glibc.zig");
const link = @import("../link.zig");
const musl = @import("../libs/musl.zig");
const freebsd = @import("../libs/freebsd.zig");
const link = @import("../link.zig");
const relocatable = @import("Elf/relocatable.zig");
const relocation = @import("Elf/relocation.zig");
const target_util = @import("../target.zig");