Skip to content

Commit f49e0e6

Browse files
committed
Add an escape hatch for unknown LLD flags
Ideally they're all recognized to idiomatically pass, but in case they're not add an escape hatch to thread it through.
1 parent 5d9b5bc commit f49e0e6

2 files changed

Lines changed: 37 additions & 7 deletions

File tree

src/lib.rs

Lines changed: 19 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,11 @@ struct ComponentLdArgs {
322322
/// Skip the `wit-component`-based process to generate a component.
323323
#[clap(long)]
324324
skip_wit_component: bool,
325+
326+
/// Raw flags to pass to the end of the `lld` invocation in case they're
327+
/// not already recognized by this wrapper executable.
328+
#[clap(long)]
329+
append_lld_flag: Vec<OsString>,
325330
}
326331

327332
fn parse_adapter(s: &str) -> Result<(String, Vec<u8>)> {
@@ -527,16 +532,18 @@ impl App {
527532
handle_lld_arg(lld, &mut parser, &mut lld_args)?;
528533
}
529534
None => {
530-
component_ld_args.push(format!("--{c}").into());
535+
let mut flag = OsString::from(format!("--{c}"));
531536
if let Some(arg) = command.get_arguments().find(|a| a.get_long() == Some(c))
532537
{
533538
match arg.get_action() {
534539
ArgAction::Set | ArgAction::Append => {
535-
component_ld_args.push(parser.value()?)
540+
flag.push("=");
541+
flag.push(parser.value()?);
536542
}
537543
_ => (),
538544
}
539545
}
546+
component_ld_args.push(flag);
540547
}
541548
},
542549
None => break,
@@ -585,8 +592,13 @@ impl App {
585592
}
586593

587594
let linker = &lld.exe;
595+
let lld_flags = self
596+
.lld_args
597+
.iter()
598+
.chain(&self.component.append_lld_flag)
599+
.collect::<Vec<_>>();
588600
let status = lld
589-
.status(&temp_dir, &self.lld_args)
601+
.status(&temp_dir, &lld_flags)
590602
.with_context(|| format!("failed to spawn {linker:?}"))?;
591603
if !status.success() {
592604
bail!("failed to invoke LLD: {status}");
@@ -762,7 +774,7 @@ impl Lld {
762774
self.output = Some(dst.into());
763775
}
764776

765-
fn status(&self, tmpdir: &tempfile::TempDir, args: &[OsString]) -> Result<ExitStatus> {
777+
fn status(&self, tmpdir: &tempfile::TempDir, args: &[&OsString]) -> Result<ExitStatus> {
766778
// If we can probably pass `args` natively, try to do so. In some cases
767779
// though just skip this entirely and go straight to below.
768780
if !self.probably_too_big(args) {
@@ -800,15 +812,15 @@ impl Lld {
800812
std::fs::write(&path, &argfile).with_context(|| format!("failed to write {path:?}"))?;
801813
let mut argfile_arg = OsString::from("@");
802814
argfile_arg.push(&path);
803-
let status = self.run(&["--rsp-quoting=posix".into(), argfile_arg.into()])?;
815+
let status = self.run(&[&"--rsp-quoting=posix".into(), &argfile_arg])?;
804816
Ok(status)
805817
}
806818

807819
/// Tests whether the `args` array is too large to execute natively.
808820
///
809821
/// Windows `cmd.exe` has a very small limit of around 8k so perform a
810822
/// guess up to 6k. This isn't 100% accurate.
811-
fn probably_too_big(&self, args: &[OsString]) -> bool {
823+
fn probably_too_big(&self, args: &[&OsString]) -> bool {
812824
let args_size = args
813825
.iter()
814826
.map(|s| s.as_encoded_bytes().len())
@@ -831,7 +843,7 @@ impl Lld {
831843
}
832844
}
833845

834-
fn run(&self, args: &[OsString]) -> std::io::Result<ExitStatus> {
846+
fn run(&self, args: &[&OsString]) -> std::io::Result<ExitStatus> {
835847
let mut cmd = Command::new(&self.exe);
836848
if self.needs_flavor {
837849
cmd.arg("-flavor").arg("wasm");

tests/all.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -157,6 +157,7 @@ fn linker_flags() {
157157
"-Clink-arg=--max-memory=65536",
158158
"-Clink-arg=-zstack-size=32",
159159
"-Clink-arg=--global-base=2048",
160+
"-Clink-arg=--append-lld-flag=--no-merge-data-segments",
160161
],
161162
r#"
162163
fn main() {
@@ -166,6 +167,23 @@ fn main() {
166167
assert_component(&output);
167168
}
168169

170+
#[test]
171+
fn invalid_lld_flag() {
172+
let result = Project::new().try_compile(
173+
&["-Clink-arg=--append-lld-flag=--nonexistent-lld-flag"],
174+
r#"
175+
fn main() {
176+
println!("hello!");
177+
}
178+
"#,
179+
false,
180+
);
181+
let err = result.unwrap_err();
182+
let err = format!("{err:?}");
183+
println!("error: {err}");
184+
assert!(err.contains("error: unknown argument: --nonexistent-lld-flag"));
185+
}
186+
169187
#[test]
170188
fn component_type_wit_file() {
171189
let project = Project::new();

0 commit comments

Comments
 (0)