compiler: handle -Xlinker args similarly to -Wl args

This commit is contained in:
Alex Rønne Petersen 2025-12-05 08:47:09 +01:00
parent 34f88722cd
commit 38415911c1
No known key found for this signature in database

View file

@ -2071,6 +2071,8 @@ fn buildOutputType(
.wl => { .wl => {
var split_it = mem.splitScalar(u8, it.only_arg, ','); var split_it = mem.splitScalar(u8, it.only_arg, ',');
while (split_it.next()) |linker_arg| { while (split_it.next()) |linker_arg| {
// Unfortunately duplicated with the `for_linker` handling below.
// Handle nested-joined args like `-Wl,-rpath=foo`. // Handle nested-joined args like `-Wl,-rpath=foo`.
// Must be prefixed with 1 or 2 dashes. // Must be prefixed with 1 or 2 dashes.
if (linker_arg.len >= 3 and if (linker_arg.len >= 3 and
@ -2080,6 +2082,10 @@ fn buildOutputType(
if (mem.indexOfScalar(u8, linker_arg, '=')) |equals_pos| { if (mem.indexOfScalar(u8, linker_arg, '=')) |equals_pos| {
const key = linker_arg[0..equals_pos]; const key = linker_arg[0..equals_pos];
const value = linker_arg[equals_pos + 1 ..]; const value = linker_arg[equals_pos + 1 ..];
// We have to handle these here because they would be ambiguous
// if split and added to `linker_args`, as there are argument-less
// variants of them.
if (mem.eql(u8, key, "--build-id")) { if (mem.eql(u8, key, "--build-id")) {
build_id = std.zig.BuildId.parse(value) catch |err| { build_id = std.zig.BuildId.parse(value) catch |err| {
fatal("unable to parse --build-id style '{s}': {s}", .{ fatal("unable to parse --build-id style '{s}': {s}", .{
@ -2092,22 +2098,19 @@ fn buildOutputType(
// is done below. // is done below.
continue; continue;
} }
try linker_args.append(key); try linker_args.append(key);
try linker_args.append(value); try linker_args.append(value);
continue; continue;
} }
} }
if (mem.eql(u8, linker_arg, "--build-id")) {
build_id = .fast; // These options are handled inline because their order matters for
} else if (mem.eql(u8, linker_arg, "--as-needed")) { // other non-linker options.
if (mem.eql(u8, linker_arg, "--as-needed")) {
needed = false; needed = false;
} else if (mem.eql(u8, linker_arg, "--no-as-needed")) { } else if (mem.eql(u8, linker_arg, "--no-as-needed")) {
needed = true; needed = true;
} else if (mem.eql(u8, linker_arg, "-no-pie")) {
create_module.opts.pie = false;
} else if (mem.eql(u8, linker_arg, "--sort-common")) {
// from ld.lld(1): --sort-common is ignored for GNU compatibility,
// this ignores plain --sort-common
} else if (mem.eql(u8, linker_arg, "--whole-archive") or } else if (mem.eql(u8, linker_arg, "--whole-archive") or
mem.eql(u8, linker_arg, "-whole-archive")) mem.eql(u8, linker_arg, "-whole-archive"))
{ {
@ -2280,7 +2283,74 @@ fn buildOutputType(
disable_c_depfile = true; disable_c_depfile = true;
try cc_argv.append(arena, "-###"); try cc_argv.append(arena, "-###");
}, },
.for_linker => try linker_args.append(it.only_arg), .for_linker => blk: {
// Unfortunately duplicated with the `wl` handling above.
// Handle joined args like `--dependency-file=foo.d`.
// Must be prefixed with 1 or 2 dashes.
if (it.only_arg.len >= 3 and it.only_arg[0] == '-' and it.only_arg[2] != '-') {
if (mem.indexOfScalar(u8, it.only_arg, '=')) |equals_pos| {
const key = it.only_arg[0..equals_pos];
const value = it.only_arg[equals_pos + 1 ..];
// We have to handle these here because they would be ambiguous
// if split and added to `linker_args`, as there are argument-less
// variants of them.
if (mem.eql(u8, key, "--build-id")) {
build_id = std.zig.BuildId.parse(value) catch |err| {
fatal("unable to parse --build-id style '{s}': {s}", .{
value, @errorName(err),
});
};
continue;
} else if (mem.eql(u8, key, "--sort-common")) {
// this ignores --sort-common=<anything>
continue;
}
try linker_args.append(key);
try linker_args.append(value);
break :blk;
}
}
// These options are handled inline because their order matters for
// other non-linker options.
if (mem.eql(u8, it.only_arg, "--as-needed")) {
needed = false;
} else if (mem.eql(u8, it.only_arg, "--no-as-needed")) {
needed = true;
} else if (mem.eql(u8, it.only_arg, "--whole-archive") or
mem.eql(u8, it.only_arg, "-whole-archive"))
{
must_link = true;
} else if (mem.eql(u8, it.only_arg, "--no-whole-archive") or
mem.eql(u8, it.only_arg, "-no-whole-archive"))
{
must_link = false;
} else if (mem.eql(u8, it.only_arg, "-Bdynamic") or
mem.eql(u8, it.only_arg, "-dy") or
mem.eql(u8, it.only_arg, "-call_shared"))
{
lib_search_strategy = .no_fallback;
lib_preferred_mode = .dynamic;
} else if (mem.eql(u8, it.only_arg, "-Bstatic") or
mem.eql(u8, it.only_arg, "-dn") or
mem.eql(u8, it.only_arg, "-non_shared") or
mem.eql(u8, it.only_arg, "-static"))
{
lib_search_strategy = .no_fallback;
lib_preferred_mode = .static;
} else if (mem.eql(u8, it.only_arg, "-search_paths_first")) {
lib_search_strategy = .paths_first;
lib_preferred_mode = .dynamic;
} else if (mem.eql(u8, it.only_arg, "-search_dylibs_first")) {
lib_search_strategy = .mode_first;
lib_preferred_mode = .dynamic;
} else {
try linker_args.append(it.only_arg);
}
},
.linker_input_z => { .linker_input_z => {
try linker_args.append("-z"); try linker_args.append("-z");
try linker_args.append(it.only_arg); try linker_args.append(it.only_arg);
@ -2410,6 +2480,13 @@ fn buildOutputType(
} }
} }
provided_name = name[prefix..end]; provided_name = name[prefix..end];
} else if (mem.eql(u8, arg, "--build-id")) {
build_id = .fast;
} else if (mem.eql(u8, arg, "-no-pie")) {
create_module.opts.pie = false;
} else if (mem.eql(u8, arg, "--sort-common")) {
// from ld.lld(1): --sort-common is ignored for GNU compatibility,
// this ignores plain --sort-common
} else if (mem.eql(u8, arg, "-rpath") or mem.eql(u8, arg, "--rpath") or mem.eql(u8, arg, "-R")) { } else if (mem.eql(u8, arg, "-rpath") or mem.eql(u8, arg, "--rpath") or mem.eql(u8, arg, "-R")) {
try create_module.rpath_list.append(arena, linker_args_it.nextOrFatal()); try create_module.rpath_list.append(arena, linker_args_it.nextOrFatal());
} else if (mem.eql(u8, arg, "--subsystem")) { } else if (mem.eql(u8, arg, "--subsystem")) {