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(...@@ -2071,6 +2071,8 @@ fn buildOutputType(
2071 .wl => {2071 .wl => {
2072 var split_it = mem.splitScalar(u8, it.only_arg, ',');2072 var split_it = mem.splitScalar(u8, it.only_arg, ',');
2073 while (split_it.next()) |linker_arg| {2073 while (split_it.next()) |linker_arg| {
2074 // Unfortunately duplicated with the `for_linker` handling below.
2075
2074 // Handle nested-joined args like `-Wl,-rpath=foo`.2076 // Handle nested-joined args like `-Wl,-rpath=foo`.
2075 // Must be prefixed with 1 or 2 dashes.2077 // Must be prefixed with 1 or 2 dashes.
2076 if (linker_arg.len >= 3 and2078 if (linker_arg.len >= 3 and
...@@ -2080,6 +2082,10 @@ fn buildOutputType(...@@ -2080,6 +2082,10 @@ fn buildOutputType(
2080 if (mem.indexOfScalar(u8, linker_arg, '=')) |equals_pos| {2082 if (mem.indexOfScalar(u8, linker_arg, '=')) |equals_pos| {
2081 const key = linker_arg[0..equals_pos];2083 const key = linker_arg[0..equals_pos];
2082 const value = linker_arg[equals_pos + 1 ..];2084 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.
2083 if (mem.eql(u8, key, "--build-id")) {2089 if (mem.eql(u8, key, "--build-id")) {
2084 build_id = std.zig.BuildId.parse(value) catch |err| {2090 build_id = std.zig.BuildId.parse(value) catch |err| {
2085 fatal("unable to parse --build-id style '{s}': {s}", .{2091 fatal("unable to parse --build-id style '{s}': {s}", .{
...@@ -2092,22 +2098,19 @@ fn buildOutputType(...@@ -2092,22 +2098,19 @@ fn buildOutputType(
2092 // is done below.2098 // is done below.
2093 continue;2099 continue;
2094 }2100 }
2101
2095 try linker_args.append(key);2102 try linker_args.append(key);
2096 try linker_args.append(value);2103 try linker_args.append(value);
2097 continue;2104 continue;
2098 }2105 }
2099 }2106 }
2100 if (mem.eql(u8, linker_arg, "--build-id")) {2107
2101 build_id = .fast;2108 // These options are handled inline because their order matters for
2102 } else if (mem.eql(u8, linker_arg, "--as-needed")) {2109 // other non-linker options.
2110 if (mem.eql(u8, linker_arg, "--as-needed")) {
2103 needed = false;2111 needed = false;
2104 } else if (mem.eql(u8, linker_arg, "--no-as-needed")) {2112 } else if (mem.eql(u8, linker_arg, "--no-as-needed")) {
2105 needed = true;2113 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
2111 } else if (mem.eql(u8, linker_arg, "--whole-archive") or2114 } else if (mem.eql(u8, linker_arg, "--whole-archive") or
2112 mem.eql(u8, linker_arg, "-whole-archive"))2115 mem.eql(u8, linker_arg, "-whole-archive"))
2113 {2116 {
...@@ -2280,7 +2283,74 @@ fn buildOutputType(...@@ -2280,7 +2283,74 @@ fn buildOutputType(
2280 disable_c_depfile = true;2283 disable_c_depfile = true;
2281 try cc_argv.append(arena, "-###");2284 try cc_argv.append(arena, "-###");
2282 },2285 },
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 },
2284 .linker_input_z => {2354 .linker_input_z => {
2285 try linker_args.append("-z");2355 try linker_args.append("-z");
2286 try linker_args.append(it.only_arg);2356 try linker_args.append(it.only_arg);
...@@ -2410,6 +2480,13 @@ fn buildOutputType(...@@ -2410,6 +2480,13 @@ fn buildOutputType(
2410 }2480 }
2411 }2481 }
2412 provided_name = name[prefix..end];2482 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
2413 } else if (mem.eql(u8, arg, "-rpath") or mem.eql(u8, arg, "--rpath") or mem.eql(u8, arg, "-R")) {2490 } else if (mem.eql(u8, arg, "-rpath") or mem.eql(u8, arg, "--rpath") or mem.eql(u8, arg, "-R")) {
2414 try create_module.rpath_list.append(arena, linker_args_it.nextOrFatal());2491 try create_module.rpath_list.append(arena, linker_args_it.nextOrFatal());
2415 } else if (mem.eql(u8, arg, "--subsystem")) {2492 } else if (mem.eql(u8, arg, "--subsystem")) {