From bc5aeb14f54b76fcf5fdab80676c39a60d95d99f Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Sun, 10 Mar 2024 07:56:13 +0100 Subject: [PATCH 1/4] compiletest: Remove unneeded pub on get_lib_name() --- src/tools/compiletest/src/runtest.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 83c595ce2416e..52741d7486a4a 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -82,7 +82,7 @@ fn disable_error_reporting R, R>(f: F) -> R { } /// The platform-specific library name -pub fn get_lib_name(lib: &str, dylib: bool) -> String { +fn get_lib_name(lib: &str, dylib: bool) -> String { // In some casess (e.g. MUSL), we build a static // library, rather than a dynamic library. // In this case, the only path we can pass From 9de09218523f6fef45d3029d58acfc26d0cc0672 Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Sun, 10 Mar 2024 07:56:56 +0100 Subject: [PATCH 2/4] compiletest: Fix typos in get_lib_name() comment --- src/tools/compiletest/src/runtest.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 52741d7486a4a..c4a918dc5089a 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -83,10 +83,10 @@ fn disable_error_reporting R, R>(f: F) -> R { /// The platform-specific library name fn get_lib_name(lib: &str, dylib: bool) -> String { - // In some casess (e.g. MUSL), we build a static + // In some cases (e.g. MUSL), we build a static // library, rather than a dynamic library. // In this case, the only path we can pass - // with '--extern-meta' is the '.lib' file + // with '--extern-meta' is the '.rlib' file if !dylib { return format!("lib{}.rlib", lib); } From 4c95d7666038e37f75394554acd77de3cf3a00b0 Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Sun, 10 Mar 2024 07:40:08 +0100 Subject: [PATCH 3/4] compiletest: Replace bool with enum AuxType for clarity --- src/tools/compiletest/src/runtest.rs | 52 ++++++++++++++++------------ 1 file changed, 29 insertions(+), 23 deletions(-) diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index c4a918dc5089a..4b2136583493a 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -82,21 +82,22 @@ fn disable_error_reporting R, R>(f: F) -> R { } /// The platform-specific library name -fn get_lib_name(lib: &str, dylib: bool) -> String { - // In some cases (e.g. MUSL), we build a static - // library, rather than a dynamic library. - // In this case, the only path we can pass - // with '--extern-meta' is the '.rlib' file - if !dylib { - return format!("lib{}.rlib", lib); - } - - if cfg!(windows) { - format!("{}.dll", lib) - } else if cfg!(target_os = "macos") { - format!("lib{}.dylib", lib) - } else { - format!("lib{}.so", lib) +fn get_lib_name(lib: &str, aux_type: AuxType) -> String { + match aux_type { + // In some cases (e.g. MUSL), we build a static + // library, rather than a dynamic library. + // In this case, the only path we can pass + // with '--extern-meta' is the '.rlib' file + AuxType::Lib => format!("lib{}.rlib", lib), + AuxType::Dylib => { + if cfg!(windows) { + format!("{}.dll", lib) + } else if cfg!(target_os = "macos") { + format!("lib{}.dylib", lib) + } else { + format!("lib{}.so", lib) + } + } } } @@ -2107,9 +2108,9 @@ impl<'test> TestCx<'test> { } for (aux_name, aux_path) in &self.props.aux_crates { - let is_dylib = self.build_auxiliary(of, &aux_path, &aux_dir); + let aux_type = self.build_auxiliary(of, &aux_path, &aux_dir); let lib_name = - get_lib_name(&aux_path.trim_end_matches(".rs").replace('-', "_"), is_dylib); + get_lib_name(&aux_path.trim_end_matches(".rs").replace('-', "_"), aux_type); rustc.arg("--extern").arg(format!("{}={}/{}", aux_name, aux_dir.display(), lib_name)); } } @@ -2131,7 +2132,7 @@ impl<'test> TestCx<'test> { /// Builds an aux dependency. /// /// Returns whether or not it is a dylib. - fn build_auxiliary(&self, of: &TestPaths, source_path: &str, aux_dir: &Path) -> bool { + fn build_auxiliary(&self, of: &TestPaths, source_path: &str, aux_dir: &Path) -> AuxType { let aux_testpaths = self.compute_aux_test_paths(of, source_path); let aux_props = self.props.from_aux_file(&aux_testpaths.file, self.revision, self.config); let aux_output = TargetLocation::ThisDirectory(aux_dir.to_path_buf()); @@ -2159,8 +2160,8 @@ impl<'test> TestCx<'test> { } aux_rustc.envs(aux_props.rustc_env.clone()); - let (dylib, crate_type) = if aux_props.no_prefer_dynamic { - (true, None) + let (aux_type, crate_type) = if aux_props.no_prefer_dynamic { + (AuxType::Dylib, None) } else if self.config.target.contains("emscripten") || (self.config.target.contains("musl") && !aux_props.force_host @@ -2185,9 +2186,9 @@ impl<'test> TestCx<'test> { // Coverage tests want static linking by default so that coverage // mappings in auxiliary libraries can be merged into the final // executable. - (false, Some("lib")) + (AuxType::Lib, Some("lib")) } else { - (true, Some("dylib")) + (AuxType::Dylib, Some("dylib")) }; if let Some(crate_type) = crate_type { @@ -2211,7 +2212,7 @@ impl<'test> TestCx<'test> { &auxres, ); } - dylib + aux_type } fn read2_abbreviated(&self, child: Child) -> (Output, Truncated) { @@ -4826,3 +4827,8 @@ enum LinkToAux { Yes, No, } + +enum AuxType { + Lib, + Dylib, +} From 3a5eb35577f37544df95c7502344aba4ae7076ee Mon Sep 17 00:00:00 2001 From: Martin Nordholts Date: Sun, 17 Mar 2024 12:23:23 +0100 Subject: [PATCH 4/4] compiletest: Add support for `//@ aux-bin: foo.rs` Which enables ui tests to use auxiliary binaries. See the added self-test for an example. --- src/tools/compiletest/src/header.rs | 15 ++++ src/tools/compiletest/src/runtest.rs | 76 ++++++++++++++----- .../auxiliary/print-it-works.rs | 3 + .../ui/compiletest-self-test/test-aux-bin.rs | 9 +++ 4 files changed, 83 insertions(+), 20 deletions(-) create mode 100644 tests/ui/compiletest-self-test/auxiliary/print-it-works.rs create mode 100644 tests/ui/compiletest-self-test/test-aux-bin.rs diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index a512599f723b7..6ff47dbffbcba 100644 --- a/src/tools/compiletest/src/header.rs +++ b/src/tools/compiletest/src/header.rs @@ -36,6 +36,7 @@ impl HeadersCache { #[derive(Default)] pub struct EarlyProps { pub aux: Vec, + pub aux_bin: Vec, pub aux_crate: Vec<(String, String)>, pub revisions: Vec, } @@ -59,6 +60,12 @@ impl EarlyProps { config.push_name_value_directive(ln, directives::AUX_BUILD, &mut props.aux, |r| { r.trim().to_string() }); + config.push_name_value_directive( + ln, + directives::AUX_BIN, + &mut props.aux_bin, + |r| r.trim().to_string(), + ); config.push_name_value_directive( ln, directives::AUX_CRATE, @@ -95,6 +102,8 @@ pub struct TestProps { // directory as the test, but for backwards compatibility reasons // we also check the auxiliary directory) pub aux_builds: Vec, + // Auxiliary crates that should be compiled as `#![crate_type = "bin"]`. + pub aux_bins: Vec, // Similar to `aux_builds`, but a list of NAME=somelib.rs of dependencies // to build and pass with the `--extern` flag. pub aux_crates: Vec<(String, String)>, @@ -217,6 +226,7 @@ mod directives { pub const PRETTY_EXPANDED: &'static str = "pretty-expanded"; pub const PRETTY_MODE: &'static str = "pretty-mode"; pub const PRETTY_COMPARE_ONLY: &'static str = "pretty-compare-only"; + pub const AUX_BIN: &'static str = "aux-bin"; pub const AUX_BUILD: &'static str = "aux-build"; pub const AUX_CRATE: &'static str = "aux-crate"; pub const EXEC_ENV: &'static str = "exec-env"; @@ -252,6 +262,7 @@ impl TestProps { run_flags: None, pp_exact: None, aux_builds: vec![], + aux_bins: vec![], aux_crates: vec![], revisions: vec![], rustc_env: vec![("RUSTC_ICE".to_string(), "0".to_string())], @@ -417,6 +428,9 @@ impl TestProps { config.push_name_value_directive(ln, AUX_BUILD, &mut self.aux_builds, |r| { r.trim().to_string() }); + config.push_name_value_directive(ln, AUX_BIN, &mut self.aux_bins, |r| { + r.trim().to_string() + }); config.push_name_value_directive( ln, AUX_CRATE, @@ -683,6 +697,7 @@ pub fn line_directive<'line>( const KNOWN_DIRECTIVE_NAMES: &[&str] = &[ // tidy-alphabetical-start "assembly-output", + "aux-bin", "aux-build", "aux-crate", "build-aux-docs", diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 4b2136583493a..67db33abf65ff 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -82,22 +82,21 @@ fn disable_error_reporting R, R>(f: F) -> R { } /// The platform-specific library name -fn get_lib_name(lib: &str, aux_type: AuxType) -> String { +fn get_lib_name(lib: &str, aux_type: AuxType) -> Option { match aux_type { + AuxType::Bin => None, // In some cases (e.g. MUSL), we build a static // library, rather than a dynamic library. // In this case, the only path we can pass // with '--extern-meta' is the '.rlib' file - AuxType::Lib => format!("lib{}.rlib", lib), - AuxType::Dylib => { - if cfg!(windows) { - format!("{}.dll", lib) - } else if cfg!(target_os = "macos") { - format!("lib{}.dylib", lib) - } else { - format!("lib{}.so", lib) - } - } + AuxType::Lib => Some(format!("lib{}.rlib", lib)), + AuxType::Dylib => Some(if cfg!(windows) { + format!("{}.dll", lib) + } else if cfg!(target_os = "macos") { + format!("lib{}.dylib", lib) + } else { + format!("lib{}.so", lib) + }), } } @@ -2099,19 +2098,36 @@ impl<'test> TestCx<'test> { create_dir_all(&aux_dir).unwrap(); } + if !self.props.aux_bins.is_empty() { + let aux_bin_dir = self.aux_bin_output_dir_name(); + let _ = fs::remove_dir_all(&aux_bin_dir); + create_dir_all(&aux_bin_dir).unwrap(); + } + aux_dir } fn build_all_auxiliary(&self, of: &TestPaths, aux_dir: &Path, rustc: &mut Command) { for rel_ab in &self.props.aux_builds { - self.build_auxiliary(of, rel_ab, &aux_dir); + self.build_auxiliary(of, rel_ab, &aux_dir, false /* is_bin */); + } + + for rel_ab in &self.props.aux_bins { + self.build_auxiliary(of, rel_ab, &aux_dir, true /* is_bin */); } for (aux_name, aux_path) in &self.props.aux_crates { - let aux_type = self.build_auxiliary(of, &aux_path, &aux_dir); + let aux_type = self.build_auxiliary(of, &aux_path, &aux_dir, false /* is_bin */); let lib_name = get_lib_name(&aux_path.trim_end_matches(".rs").replace('-', "_"), aux_type); - rustc.arg("--extern").arg(format!("{}={}/{}", aux_name, aux_dir.display(), lib_name)); + if let Some(lib_name) = lib_name { + rustc.arg("--extern").arg(format!( + "{}={}/{}", + aux_name, + aux_dir.display(), + lib_name + )); + } } } @@ -2130,12 +2146,23 @@ impl<'test> TestCx<'test> { } /// Builds an aux dependency. - /// - /// Returns whether or not it is a dylib. - fn build_auxiliary(&self, of: &TestPaths, source_path: &str, aux_dir: &Path) -> AuxType { + fn build_auxiliary( + &self, + of: &TestPaths, + source_path: &str, + aux_dir: &Path, + is_bin: bool, + ) -> AuxType { let aux_testpaths = self.compute_aux_test_paths(of, source_path); let aux_props = self.props.from_aux_file(&aux_testpaths.file, self.revision, self.config); - let aux_output = TargetLocation::ThisDirectory(aux_dir.to_path_buf()); + let mut aux_dir = aux_dir.to_path_buf(); + if is_bin { + // On unix, the binary of `auxiliary/foo.rs` will be named + // `auxiliary/foo` which clashes with the _dir_ `auxiliary/foo`, so + // put bins in a `bin` subfolder. + aux_dir.push("bin"); + } + let aux_output = TargetLocation::ThisDirectory(aux_dir.clone()); let aux_cx = TestCx { config: self.config, props: &aux_props, @@ -2153,14 +2180,16 @@ impl<'test> TestCx<'test> { LinkToAux::No, Vec::new(), ); - aux_cx.build_all_auxiliary(of, aux_dir, &mut aux_rustc); + aux_cx.build_all_auxiliary(of, &aux_dir, &mut aux_rustc); for key in &aux_props.unset_rustc_env { aux_rustc.env_remove(key); } aux_rustc.envs(aux_props.rustc_env.clone()); - let (aux_type, crate_type) = if aux_props.no_prefer_dynamic { + let (aux_type, crate_type) = if is_bin { + (AuxType::Bin, Some("bin")) + } else if aux_props.no_prefer_dynamic { (AuxType::Dylib, None) } else if self.config.target.contains("emscripten") || (self.config.target.contains("musl") @@ -2678,6 +2707,12 @@ impl<'test> TestCx<'test> { .with_extra_extension(self.config.mode.aux_dir_disambiguator()) } + /// Gets the directory where auxiliary binaries are written. + /// E.g., `/.../testname.revision.mode/auxiliary/bin`. + fn aux_bin_output_dir_name(&self) -> PathBuf { + self.aux_output_dir_name().join("bin") + } + /// Generates a unique name for the test, such as `testname.revision.mode`. fn output_testname_unique(&self) -> PathBuf { output_testname_unique(self.config, self.testpaths, self.safe_revision()) @@ -4829,6 +4864,7 @@ enum LinkToAux { } enum AuxType { + Bin, Lib, Dylib, } diff --git a/tests/ui/compiletest-self-test/auxiliary/print-it-works.rs b/tests/ui/compiletest-self-test/auxiliary/print-it-works.rs new file mode 100644 index 0000000000000..09411eb121ceb --- /dev/null +++ b/tests/ui/compiletest-self-test/auxiliary/print-it-works.rs @@ -0,0 +1,3 @@ +fn main() { + println!("it works"); +} diff --git a/tests/ui/compiletest-self-test/test-aux-bin.rs b/tests/ui/compiletest-self-test/test-aux-bin.rs new file mode 100644 index 0000000000000..9e01e3ffabff1 --- /dev/null +++ b/tests/ui/compiletest-self-test/test-aux-bin.rs @@ -0,0 +1,9 @@ +//@ ignore-cross-compile because we run the compiled code +//@ aux-bin: print-it-works.rs +//@ run-pass + +fn main() { + let stdout = + std::process::Command::new("auxiliary/bin/print-it-works").output().unwrap().stdout; + assert_eq!(stdout, b"it works\n"); +}