Skip to content

Commit a7e7bbf

Browse files
authored
Handle more "nonstandard" LLD flags (#84)
Turns out `-shared` isn't the only one, it's actually a lot. I ran into `-soname` today and upon reading LLD's source for option parsing turns out there's a lot more than anticipated. Adjust the parsing to handle the "more flags are nonstandard".
1 parent ee33b7d commit a7e7bbf

File tree

4 files changed

+118
-74
lines changed

4 files changed

+118
-74
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ pkg-fmt = "zip"
2626
[dependencies]
2727
anyhow = "1.0.80"
2828
clap = { version = "4.5.4", features = ['derive'] }
29+
clap_lex = "0.7.5"
2930
lexopt = "0.3.0"
3031
tempfile = "3.10.0"
3132
wasmparser = "0.241.0"

src/lib.rs

Lines changed: 99 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use anyhow::{bail, Context, Result};
22
use clap::{ArgAction, CommandFactory, FromArgMatches};
3+
use clap_lex::OsStrExt;
34
use lexopt::Arg;
45
use std::env;
56
use std::ffi::OsString;
@@ -31,6 +32,16 @@ struct LldFlag {
3132
long: Option<&'static str>,
3233
short: Option<char>,
3334
value: FlagValue,
35+
nonstandard: bool,
36+
}
37+
38+
impl LldFlag {
39+
const fn nonstandard(self) -> Self {
40+
LldFlag {
41+
nonstandard: true,
42+
..self
43+
}
44+
}
3445
}
3546

3647
enum FlagValue {
@@ -71,6 +82,7 @@ macro_rules! flag {
7182
long: Some(flag!(@name [] $($flag)*)),
7283
short: flag!(@short $($short)?),
7384
value: flag!(@value $($flag)*),
85+
nonstandard: false,
7486
}
7587
};
7688

@@ -81,6 +93,7 @@ macro_rules! flag {
8193
long: None,
8294
short: Some(flag!(@char $flag)),
8395
value: flag!(@value $flag $($val)*),
96+
nonstandard: false,
8497
}
8598
};
8699

@@ -126,111 +139,108 @@ macro_rules! flag {
126139
}
127140

128141
const LLD_FLAGS: &[LldFlag] = &[
129-
flag! { --allow-multiple-definition },
130-
flag! { --allow-undefined-file=PATH },
131-
flag! { --allow-undefined },
132-
flag! { --Bdynamic },
133-
flag! { --Bstatic },
134-
flag! { --Bsymbolic },
135-
flag! { --build-id[=VAL] },
136-
flag! { --call_shared },
142+
flag! { --allow-multiple-definition }.nonstandard(),
143+
flag! { --allow-undefined-file=PATH }.nonstandard(),
144+
flag! { --allow-undefined }.nonstandard(),
145+
flag! { --Bdynamic }.nonstandard(),
146+
flag! { --Bstatic }.nonstandard(),
147+
flag! { --Bsymbolic }.nonstandard(),
148+
flag! { --build-id[=VAL] }.nonstandard(),
149+
flag! { --call_shared }.nonstandard(),
137150
flag! { --check-features },
138-
flag! { --color-diagnostics[=VALUE] },
139-
flag! { --compress-relocations },
140-
flag! { --demangle },
141-
flag! { --dn },
142-
flag! { --dy },
143-
flag! { --emit-relocs },
144-
flag! { --end-lib },
145-
flag! { --entry SYM },
151+
flag! { --color-diagnostics[=VALUE] }.nonstandard(),
152+
flag! { --compress-relocations }.nonstandard(),
153+
flag! { --demangle }.nonstandard(),
154+
flag! { --dn }.nonstandard(),
155+
flag! { --dy }.nonstandard(),
156+
flag! { --emit-relocs }.nonstandard(),
157+
flag! { --end-lib }.nonstandard(),
158+
flag! { --entry SYM }.nonstandard(),
146159
flag! { --error-limit=N },
147-
flag! { --error-unresolved-symbols },
160+
flag! { --error-unresolved-symbols }.nonstandard(),
148161
flag! { --experimental-pic },
149162
flag! { --export-all },
150-
flag! { -E / --export-dynamic },
151-
flag! { --export-if-defined=SYM },
163+
flag! { -E / --export-dynamic }.nonstandard(),
164+
flag! { --export-if-defined=SYM }.nonstandard(),
152165
flag! { --export-memory[=NAME] },
153166
flag! { --export-table },
154-
flag! { --export=SYM },
155-
flag! { --extra-features=LIST },
156-
flag! { --fatal-warnings },
157-
flag! { --features=LIST },
158-
flag! { --gc-sections },
167+
flag! { --export=SYM }.nonstandard(),
168+
flag! { --extra-features=LIST }.nonstandard(),
169+
flag! { --fatal-warnings }.nonstandard(),
170+
flag! { --features=LIST }.nonstandard(),
171+
flag! { --gc-sections }.nonstandard(),
159172
flag! { --global-base=VALUE },
160173
flag! { --growable-table },
161174
flag! { --import-memory[=NAME] },
162175
flag! { --import-table },
163-
flag! { --import-undefined },
176+
flag! { --import-undefined }.nonstandard(),
164177
flag! { --initial-heap=SIZE },
165178
flag! { --initial-memory=SIZE },
166-
flag! { --keep-section=NAME },
179+
flag! { --keep-section=NAME }.nonstandard(),
167180
flag! { --lto-CGO=LEVEL },
168181
flag! { --lto-debug-pass-manager },
169182
flag! { --lto-O=LEVEL },
170183
flag! { --lto-partitions=NUM },
171184
flag! { -L PATH },
172185
flag! { -l LIB },
173-
flag! { --Map=FILE },
186+
flag! { --Map=FILE }.nonstandard(),
174187
flag! { --max-memory=SIZE },
175188
flag! { --merge-data-segments },
176-
flag! { --mllvm=FLAG },
189+
flag! { --mllvm=FLAG }.nonstandard(),
177190
flag! { -m ARCH },
178-
flag! { --no-allow-multiple-definition },
191+
flag! { --no-allow-multiple-definition }.nonstandard(),
179192
flag! { --no-check-features },
180-
flag! { --no-color-diagnostics },
181-
flag! { --no-demangle },
182-
flag! { --no-entry },
183-
flag! { --no-export-dynamic },
184-
flag! { --no-fatal-warnings },
185-
flag! { --no-gc-sections },
193+
flag! { --no-color-diagnostics }.nonstandard(),
194+
flag! { --no-demangle }.nonstandard(),
195+
flag! { --no-entry }.nonstandard(),
196+
flag! { --no-export-dynamic }.nonstandard(),
197+
flag! { --no-fatal-warnings }.nonstandard(),
198+
flag! { --no-gc-sections }.nonstandard(),
186199
flag! { --no-growable-memory },
187200
flag! { --no-merge-data-segments },
188-
flag! { --no-pie },
189-
flag! { --no-print-gc-sections },
201+
flag! { --no-pie }.nonstandard(),
202+
flag! { --no-print-gc-sections }.nonstandard(),
190203
flag! { --no-shlib-sigcheck },
191-
flag! { --no-whole-archive },
192-
flag! { --noinhibit-exec },
193-
flag! { --non_shared },
204+
flag! { --no-whole-archive }.nonstandard(),
205+
flag! { --noinhibit-exec }.nonstandard(),
206+
flag! { --non_shared }.nonstandard(),
194207
flag! { -O LEVEL },
195208
flag! { --page-size=VALUE },
196-
flag! { --pie },
197-
flag! { --print-gc-sections },
198-
flag! { -M / --print-map },
199-
flag! { --relocatable },
209+
flag! { --pie }.nonstandard(),
210+
flag! { --print-gc-sections }.nonstandard(),
211+
flag! { -M / --print-map }.nonstandard(),
212+
flag! { --relocatable }.nonstandard(),
200213
flag! { --reproduce=VALUE },
201-
flag! { --rpath=VALUE },
202-
flag! { --save-temps },
214+
flag! { --rpath=VALUE }.nonstandard(),
215+
flag! { --save-temps }.nonstandard(),
203216
flag! { --shared-memory },
204-
flag! { --shared },
205-
flag! { --soname=VALUE },
206-
flag! { --stack-first },
207-
flag! { --start-lib },
208-
flag! { --static },
209-
flag! { -s / --strip-all },
210-
flag! { -S / --strip-debug },
217+
flag! { --shared }.nonstandard(),
218+
flag! { --soname=VALUE }.nonstandard(),
219+
flag! { --stack-first }.nonstandard(),
220+
flag! { --start-lib }.nonstandard(),
221+
flag! { --static }.nonstandard(),
222+
flag! { -s / --strip-all }.nonstandard(),
223+
flag! { -S / --strip-debug }.nonstandard(),
211224
flag! { --table-base=VALUE },
212225
flag! { --thinlto-cache-dir=PATH },
213226
flag! { --thinlto-cache-policy=VALUE },
214227
flag! { --thinlto-jobs=N },
215-
flag! { --threads=N },
216-
flag! { -y / --trace-symbol=SYM },
217-
flag! { -t / --trace },
218-
flag! { --undefined=SYM },
219-
flag! { --unresolved-symbols=VALUE },
220-
flag! { --warn-unresolved-symbols },
221-
flag! { --whole-archive },
228+
flag! { --threads=N }.nonstandard(),
229+
flag! { -y / --trace-symbol=SYM }.nonstandard(),
230+
flag! { -t / --trace }.nonstandard(),
231+
flag! { --undefined=SYM }.nonstandard(),
232+
flag! { --unresolved-symbols=VALUE }.nonstandard(),
233+
flag! { --warn-unresolved-symbols }.nonstandard(),
234+
flag! { --whole-archive }.nonstandard(),
222235
flag! { --why-extract=MEMBER },
223-
flag! { --wrap=VALUE },
236+
flag! { --wrap=VALUE }.nonstandard(),
224237
flag! { -z OPT },
225238
];
226239

227-
const LLD_LONG_FLAGS_NONSTANDARD: &[&str] = &["-shared"];
228-
229240
#[derive(Default)]
230241
struct App {
231242
component: ComponentLdArgs,
232243
lld_args: Vec<OsString>,
233-
shared: bool,
234244
}
235245

236246
/// A linker to create a Component from input object files and libraries.
@@ -442,7 +452,6 @@ impl App {
442452
let mut command = ComponentLdArgs::command();
443453
let mut lld_args = Vec::new();
444454
let mut component_ld_args = vec![std::env::args_os().nth(0).unwrap()];
445-
let mut shared = false;
446455
let mut parser = lexopt::Parser::from_iter(args);
447456

448457
fn handle_lld_arg(
@@ -497,14 +506,31 @@ impl App {
497506
loop {
498507
if let Some(mut args) = parser.try_raw_args() {
499508
if let Some(arg) = args.peek() {
500-
let for_lld = LLD_LONG_FLAGS_NONSTANDARD.iter().any(|s| arg == *s);
501-
if for_lld {
502-
lld_args.push(arg.to_owned());
503-
if arg == "-shared" {
504-
shared = true;
509+
// If this is a `-...` flag then check to see if this is a
510+
// "nonstandard" flag like `-shared`. That's done by
511+
// looking at all `nonstandard` flags and testing if the
512+
// option is `-name...`. If so, then assume it's a nonstandard
513+
// flag and give it to LLD then move on.
514+
//
515+
// Note that if any flag has a value it'll get passed to
516+
// LLD below in `Arg::Value`, and otherwise if the option
517+
// has an embedded `=` in it that'll be handled here via
518+
// the `starts_with` check.
519+
//
520+
// Also note that `--foo` flags are all auto-skipped here
521+
// since the `starts_with` check won't pass for any of them
522+
// as `f.long` never starts with `-`.
523+
if let Some(flag) = arg.strip_prefix("-") {
524+
let for_lld = LLD_FLAGS
525+
.iter()
526+
.filter(|f| f.nonstandard)
527+
.filter_map(|f| f.long)
528+
.any(|f| flag.starts_with(f));
529+
if for_lld {
530+
lld_args.push(arg.to_owned());
531+
args.next();
532+
continue;
505533
}
506-
args.next();
507-
continue;
508534
}
509535
}
510536
}
@@ -555,7 +581,6 @@ impl App {
555581
Ok(matches) => Ok(App {
556582
component: ComponentLdArgs::from_arg_matches(&matches)?,
557583
lld_args,
558-
shared,
559584
}),
560585
Err(_) => {
561586
add_wasm_ld_options(ComponentLdArgs::command()).get_matches_from(component_ld_args);
@@ -716,7 +741,7 @@ impl App {
716741
self.component.skip_wit_component
717742
// Skip componentization with `--shared` since that's creating a
718743
// shared library that's not a component yet.
719-
|| self.shared
744+
|| self.lld_args.iter().any(|s| s == "-shared" || s == "--shared")
720745
}
721746

722747
fn lld(&self) -> Lld {

tests/all.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,23 @@ fn linker_flags() {
161161
],
162162
r#"
163163
fn main() {
164+
}
165+
"#,
166+
);
167+
assert_component(&output);
168+
169+
let output = compile(
170+
&[
171+
"-Clink-arg=--max-memory=65536",
172+
"-Clink-arg=-zstack-size=32",
173+
"-Clink-arg=--global-base=2048",
174+
"-Clink-arg=--append-lld-flag=--no-merge-data-segments",
175+
"-Clink-arg=-allow-multiple-definition",
176+
"-Clink-arg=-soname",
177+
"-Clink-arg=foo",
178+
],
179+
r#"
180+
fn main() {
164181
}
165182
"#,
166183
);

0 commit comments

Comments
 (0)