Skip to content

Commit ba3b426

Browse files
authored
Add an escape hatch for unknown LLD flags (#72)
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 ba3b426

File tree

2 files changed

+37
-7
lines changed

2 files changed

+37
-7
lines changed

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)