authorgravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-12-05 08:47:09+01:00
committergravatar for alex@alexrp.comAlex Rønne Petersen <alex@alexrp.com> 2025-12-05 11:04:51+01:00
log38415911c10055b67d6932d7cbafd14e0b8b6775
tree9bcebdd4b4af96c604ae4dd3e5cba163b0e45f9d
parent34f88722cd6c206cbbc312377563340f3c3ab2b2
signaturebadge-check Signed by SSH key SHA256:7B/LJ7bpR1eX8aCXSr4mtd5M45VMPKcx9zY8e95b5QM

compiler: handle -Xlinker args similarly to -Wl args


1 files changed, 86 insertions(+), 9 deletions(-)

src/main.zig+86-9
......@@ -2071,6 +2071,8 @@ fn buildOutputType(
20712071 .wl => {
20722072 var split_it = mem.splitScalar(u8, it.only_arg, ',');
20732073 while (split_it.next()) |linker_arg| {
2074 // Unfortunately duplicated with the `for_linker` handling below.
2075
20742076 // Handle nested-joined args like `-Wl,-rpath=foo`.
20752077 // Must be prefixed with 1 or 2 dashes.
20762078 if (linker_arg.len >= 3 and
......@@ -2080,6 +2082,10 @@ fn buildOutputType(
20802082 if (mem.indexOfScalar(u8, linker_arg, '=')) |equals_pos| {
20812083 const key = linker_arg[0..equals_pos];
20822084 const value = linker_arg[equals_pos + 1 ..];
2085
2086 // We have to handle these here because they would be ambiguous
2087 // if split and added to `linker_args`, as there are argument-less
2088 // variants of them.
20832089 if (mem.eql(u8, key, "--build-id")) {
20842090 build_id = std.zig.BuildId.parse(value) catch |err| {
20852091 fatal("unable to parse --build-id style '{s}': {s}", .{
......@@ -2092,22 +2098,19 @@ fn buildOutputType(
20922098 // is done below.
20932099 continue;
20942100 }
2101
20952102 try linker_args.append(key);
20962103 try linker_args.append(value);
20972104 continue;
20982105 }
20992106 }
2100 if (mem.eql(u8, linker_arg, "--build-id")) {
2101 build_id = .fast;
2102 } else if (mem.eql(u8, linker_arg, "--as-needed")) {
2107
2108 // These options are handled inline because their order matters for
2109 // other non-linker options.
2110 if (mem.eql(u8, linker_arg, "--as-needed")) {
21032111 needed = false;
21042112 } else if (mem.eql(u8, linker_arg, "--no-as-needed")) {
21052113 needed = true;
2106 } else if (mem.eql(u8, linker_arg, "-no-pie")) {
2107 create_module.opts.pie = false;
2108 } else if (mem.eql(u8, linker_arg, "--sort-common")) {
2109 // from ld.lld(1): --sort-common is ignored for GNU compatibility,
2110 // this ignores plain --sort-common
21112114 } else if (mem.eql(u8, linker_arg, "--whole-archive") or
21122115 mem.eql(u8, linker_arg, "-whole-archive"))
21132116 {
......@@ -2280,7 +2283,74 @@ fn buildOutputType(
22802283 disable_c_depfile = true;
22812284 try cc_argv.append(arena, "-###");
22822285 },
2283 .for_linker => try linker_args.append(it.only_arg),
2286 .for_linker => blk: {
2287 // Unfortunately duplicated with the `wl` handling above.
2288
2289 // Handle joined args like `--dependency-file=foo.d`.
2290 // Must be prefixed with 1 or 2 dashes.
2291 if (it.only_arg.len >= 3 and it.only_arg[0] == '-' and it.only_arg[2] != '-') {
2292 if (mem.indexOfScalar(u8, it.only_arg, '=')) |equals_pos| {
2293 const key = it.only_arg[0..equals_pos];
2294 const value = it.only_arg[equals_pos + 1 ..];
2295
2296 // We have to handle these here because they would be ambiguous
2297 // if split and added to `linker_args`, as there are argument-less
2298 // variants of them.
2299 if (mem.eql(u8, key, "--build-id")) {
2300 build_id = std.zig.BuildId.parse(value) catch |err| {
2301 fatal("unable to parse --build-id style '{s}': {s}", .{
2302 value, @errorName(err),
2303 });
2304 };
2305 continue;
2306 } else if (mem.eql(u8, key, "--sort-common")) {
2307 // this ignores --sort-common=<anything>
2308 continue;
2309 }
2310
2311 try linker_args.append(key);
2312 try linker_args.append(value);
2313 break :blk;
2314 }
2315 }
2316
2317 // These options are handled inline because their order matters for
2318 // other non-linker options.
2319 if (mem.eql(u8, it.only_arg, "--as-needed")) {
2320 needed = false;
2321 } else if (mem.eql(u8, it.only_arg, "--no-as-needed")) {
2322 needed = true;
2323 } else if (mem.eql(u8, it.only_arg, "--whole-archive") or
2324 mem.eql(u8, it.only_arg, "-whole-archive"))
2325 {
2326 must_link = true;
2327 } else if (mem.eql(u8, it.only_arg, "--no-whole-archive") or
2328 mem.eql(u8, it.only_arg, "-no-whole-archive"))
2329 {
2330 must_link = false;
2331 } else if (mem.eql(u8, it.only_arg, "-Bdynamic") or
2332 mem.eql(u8, it.only_arg, "-dy") or
2333 mem.eql(u8, it.only_arg, "-call_shared"))
2334 {
2335 lib_search_strategy = .no_fallback;
2336 lib_preferred_mode = .dynamic;
2337 } else if (mem.eql(u8, it.only_arg, "-Bstatic") or
2338 mem.eql(u8, it.only_arg, "-dn") or
2339 mem.eql(u8, it.only_arg, "-non_shared") or
2340 mem.eql(u8, it.only_arg, "-static"))
2341 {
2342 lib_search_strategy = .no_fallback;
2343 lib_preferred_mode = .static;
2344 } else if (mem.eql(u8, it.only_arg, "-search_paths_first")) {
2345 lib_search_strategy = .paths_first;
2346 lib_preferred_mode = .dynamic;
2347 } else if (mem.eql(u8, it.only_arg, "-search_dylibs_first")) {
2348 lib_search_strategy = .mode_first;
2349 lib_preferred_mode = .dynamic;
2350 } else {
2351 try linker_args.append(it.only_arg);
2352 }
2353 },
22842354 .linker_input_z => {
22852355 try linker_args.append("-z");
22862356 try linker_args.append(it.only_arg);
......@@ -2410,6 +2480,13 @@ fn buildOutputType(
24102480 }
24112481 }
24122482 provided_name = name[prefix..end];
2483 } else if (mem.eql(u8, arg, "--build-id")) {
2484 build_id = .fast;
2485 } else if (mem.eql(u8, arg, "-no-pie")) {
2486 create_module.opts.pie = false;
2487 } else if (mem.eql(u8, arg, "--sort-common")) {
2488 // from ld.lld(1): --sort-common is ignored for GNU compatibility,
2489 // this ignores plain --sort-common
24132490 } else if (mem.eql(u8, arg, "-rpath") or mem.eql(u8, arg, "--rpath") or mem.eql(u8, arg, "-R")) {
24142491 try create_module.rpath_list.append(arena, linker_args_it.nextOrFatal());
24152492 } else if (mem.eql(u8, arg, "--subsystem")) {