target: check for backend support for the new linker

Closes #25343
This commit is contained in:
Jacob Young 2025-09-24 12:09:05 -04:00 committed by Andrew Kelley
parent 9b3b7aa911
commit 561e556aaf
2 changed files with 55 additions and 52 deletions

View File

@ -34,7 +34,6 @@ any_error_tracing: bool,
any_sanitize_thread: bool,
any_sanitize_c: std.zig.SanitizeC,
any_fuzz: bool,
pie: bool,
/// If this is true then linker code is responsible for making an LLVM IR
/// Module, outputting it to an object file, and then linking that together
/// with link options and other objects. Otherwise (depending on `use_lld`)
@ -48,8 +47,9 @@ use_lib_llvm: bool,
/// and updates the final binary.
use_lld: bool,
c_frontend: CFrontend,
lto: std.zig.LtoMode,
use_new_linker: bool,
pie: bool,
lto: std.zig.LtoMode,
incremental: bool,
/// WASI-only. Type of WASI execution model ("command" or "reactor").
/// Always set to `command` for non-WASI targets.
@ -100,13 +100,13 @@ pub const Options = struct {
link_libc: ?bool = null,
link_libcpp: ?bool = null,
link_libunwind: ?bool = null,
pie: ?bool = null,
use_llvm: ?bool = null,
use_lib_llvm: ?bool = null,
use_lld: ?bool = null,
use_clang: ?bool = null,
lto: ?std.zig.LtoMode = null,
use_new_linker: ?bool = null,
pie: ?bool = null,
lto: ?std.zig.LtoMode = null,
incremental: bool = false,
/// WASI-only. Type of WASI execution model ("command" or "reactor").
wasi_exec_model: ?std.builtin.WasiExecModel = null,
@ -324,33 +324,6 @@ pub fn resolve(options: Options) ResolveError!Config {
break :b !import_memory;
};
const pie: bool = b: {
switch (options.output_mode) {
.Exe => if (target.os.tag == .fuchsia or
(target.abi.isAndroid() and link_mode == .dynamic))
{
if (options.pie == false) return error.TargetRequiresPie;
break :b true;
},
.Lib => if (link_mode == .dynamic) {
if (options.pie == true) return error.DynamicLibraryPrecludesPie;
break :b false;
},
.Obj => {},
}
if (options.any_sanitize_thread) {
if (options.pie == false) return error.SanitizeThreadRequiresPie;
break :b true;
}
if (options.pie) |pie| break :b pie;
break :b if (options.output_mode == .Exe) switch (target.os.tag) {
.fuchsia,
.openbsd,
=> true,
else => target.os.tag.isDarwin(),
} else false;
};
const is_dyn_lib = switch (options.output_mode) {
.Obj, .Exe => false,
.Lib => link_mode == .dynamic,
@ -405,6 +378,7 @@ pub fn resolve(options: Options) ResolveError!Config {
// we are confident in the robustness of the backend.
break :b !target_util.selfHostedBackendIsAsRobustAsLlvm(target);
};
const backend = target_util.zigBackend(target, use_llvm);
if (options.emit_bin and options.have_zcu) {
if (!use_lib_llvm and use_llvm) {
@ -413,7 +387,7 @@ pub fn resolve(options: Options) ResolveError!Config {
return error.EmittingBinaryRequiresLlvmLibrary;
}
if (target_util.zigBackend(target, use_llvm) == .other) {
if (backend == .other) {
// There is no compiler backend available for this target.
return error.ZigLacksTargetSupport;
}
@ -451,6 +425,49 @@ pub fn resolve(options: Options) ResolveError!Config {
break :b use_llvm;
};
const use_new_linker = b: {
if (use_lld) {
if (options.use_new_linker == true) return error.NewLinkerIncompatibleWithLld;
break :b false;
}
if (!target_util.hasNewLinkerSupport(target.ofmt, backend)) {
if (options.use_new_linker == true) return error.NewLinkerIncompatibleObjectFormat;
break :b false;
}
if (options.use_new_linker) |x| break :b x;
break :b options.incremental;
};
const pie = b: {
switch (options.output_mode) {
.Exe => if (target.os.tag == .fuchsia or
(target.abi.isAndroid() and link_mode == .dynamic))
{
if (options.pie == false) return error.TargetRequiresPie;
break :b true;
},
.Lib => if (link_mode == .dynamic) {
if (options.pie == true) return error.DynamicLibraryPrecludesPie;
break :b false;
},
.Obj => {},
}
if (options.any_sanitize_thread) {
if (options.pie == false) return error.SanitizeThreadRequiresPie;
break :b true;
}
if (options.pie) |pie| break :b pie;
break :b if (options.output_mode == .Exe) switch (target.os.tag) {
.fuchsia,
.openbsd,
=> true,
else => target.os.tag.isDarwin(),
} else false;
};
const lto: std.zig.LtoMode = b: {
if (!use_lld) {
// zig ld LTO support is tracked by
@ -464,22 +481,6 @@ pub fn resolve(options: Options) ResolveError!Config {
break :b .none;
};
const use_new_linker = b: {
if (use_lld) {
if (options.use_new_linker == true) return error.NewLinkerIncompatibleWithLld;
break :b false;
}
if (!target_util.hasNewLinkerSupport(target.ofmt)) {
if (options.use_new_linker == true) return error.NewLinkerIncompatibleObjectFormat;
break :b false;
}
if (options.use_new_linker) |x| break :b x;
break :b options.incremental;
};
const root_strip = b: {
if (options.root_strip) |x| break :b x;
if (root_optimize_mode == .ReleaseSmall) break :b true;
@ -501,7 +502,6 @@ pub fn resolve(options: Options) ResolveError!Config {
};
};
const backend = target_util.zigBackend(target, use_llvm);
const backend_supports_error_tracing = target_util.backendSupportsFeature(backend, .error_return_trace);
const root_error_tracing = b: {
@ -551,9 +551,9 @@ pub fn resolve(options: Options) ResolveError!Config {
.any_fuzz = options.any_fuzz,
.san_cov_trace_pc_guard = options.san_cov_trace_pc_guard,
.root_error_tracing = root_error_tracing,
.use_new_linker = use_new_linker,
.pie = pie,
.lto = lto,
.use_new_linker = use_new_linker,
.incremental = options.incremental,
.import_memory = import_memory,
.export_memory = export_memory,

View File

@ -231,9 +231,12 @@ pub fn hasLldSupport(ofmt: std.Target.ObjectFormat) bool {
};
}
pub fn hasNewLinkerSupport(ofmt: std.Target.ObjectFormat) bool {
pub fn hasNewLinkerSupport(ofmt: std.Target.ObjectFormat, backend: std.builtin.CompilerBackend) bool {
return switch (ofmt) {
.elf => true,
.elf => switch (backend) {
.stage2_x86_64 => true,
else => false,
},
else => false,
};
}