diff --git a/libwild/src/fs.rs b/libwild/src/fs.rs index 499622000..f9459cfd4 100644 --- a/libwild/src/fs.rs +++ b/libwild/src/fs.rs @@ -2,8 +2,10 @@ use crate::error::Result; use std::fs::File; use std::path::PathBuf; +/// Make the the supplied file executable by adding execute permissions for all users that have read +/// permissions. On non-Unix platforms, this is a no-op. #[allow(clippy::unnecessary_wraps)] -pub(crate) fn make_executable(_file: &File) -> Result { +pub fn make_executable(_file: &File) -> Result { #[cfg(unix)] { use std::os::unix::prelude::PermissionsExt; diff --git a/libwild/src/lib.rs b/libwild/src/lib.rs index 3d68918fa..ee6e59043 100644 --- a/libwild/src/lib.rs +++ b/libwild/src/lib.rs @@ -89,6 +89,7 @@ use crate::version_script::VersionScript; use colosseum::sync::Arena; use crossbeam_utils::atomic::AtomicCell; use error::AlreadyInitialised; +pub use fs::make_executable; use input_data::FileLoader; use input_data::InputFile; use input_data::InputLinkerScript; diff --git a/wild/tests/external_tests/mod.rs b/wild/tests/external_tests/mod.rs index f5b4cf8e0..c06285fc3 100644 --- a/wild/tests/external_tests/mod.rs +++ b/wild/tests/external_tests/mod.rs @@ -5,6 +5,7 @@ use crate::Filter; use crate::Result; use libtest_mimic::Trial; use std::env; +use std::io::Write; use std::path::Path; use std::path::PathBuf; use std::process::Command; @@ -97,7 +98,7 @@ fn get_external_linker() -> &'static ExternalLinker { fn get_fakes_dir() -> &'static Path { static DIR: OnceLock = OnceLock::new(); - DIR.get_or_init(|| FakesDir::new(get_external_linker())) + DIR.get_or_init(|| FakesDir::new(get_external_linker()).unwrap()) .path() } @@ -107,7 +108,7 @@ enum FakesDir { } impl FakesDir { - fn new(linker: &ExternalLinker) -> Self { + fn new(linker: &ExternalLinker) -> Result { match linker { ExternalLinker::Wild => { let current_dir = env::current_dir().expect("failed to get current directory"); @@ -117,7 +118,7 @@ impl FakesDir { "fakes-debug directory not found at {}", fakes.display() ); - FakesDir::Static(fakes) + Ok(FakesDir::Static(fakes)) } ExternalLinker::ThirdParty { path, name } => { let tmp = tempfile::tempdir() @@ -126,13 +127,12 @@ impl FakesDir { for link_name in &["mold", "ld", "ld.lld"] { let link = tmp_path.join(link_name); - std::os::unix::fs::symlink(path, &link).unwrap_or_else(|e| { - panic!( - "failed to create symlink {} -> {}: {e}", - link.display(), - path.display() - ) - }); + // Note, we can't just create a symlink, since lld requires that it's invoked as + // "ld.lld" to work properly. Instead, we create a wrapper script. + let script_contents = format!("#!/bin/bash\nexec {} \"$@\"\n", path.display()); + let mut file = std::fs::File::create(&link)?; + file.write_all(script_contents.as_bytes())?; + libwild::make_executable(&file)?; } eprintln!( @@ -141,7 +141,7 @@ impl FakesDir { tmp_path.display() ); - FakesDir::Temp(tmp) + Ok(FakesDir::Temp(tmp)) } } }