diff options
| author | Matthias Krüger <matthias.krueger@famsik.de> | 2024-03-19 18:03:50 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2024-03-19 18:03:50 +0100 |
| commit | 42dec6f874c81fd1a6c72f05a8dc439916669bc7 (patch) | |
| tree | a6afbbd8744939fe2912c6c1de9204dfaa5c9f09 | |
| parent | 45e005df427154254d662f3941fef06581432f2b (diff) | |
| parent | 3a5eb35577f37544df95c7502344aba4ae7076ee (diff) | |
| download | rust-42dec6f874c81fd1a6c72f05a8dc439916669bc7.tar.gz rust-42dec6f874c81fd1a6c72f05a8dc439916669bc7.zip | |
Rollup merge of #122634 - Enselic:aux-bin, r=oli-obk
compiletest: Add support for `//@ aux-bin: foo.rs` Which enables ui tests to use auxiliary binaries. See the added self-test for an example. This is an enabler for the test in https://github.com/rust-lang/rust/pull/121573.
| -rw-r--r-- | src/tools/compiletest/src/header.rs | 15 | ||||
| -rw-r--r-- | src/tools/compiletest/src/runtest.rs | 100 | ||||
| -rw-r--r-- | tests/ui/compiletest-self-test/auxiliary/print-it-works.rs | 3 | ||||
| -rw-r--r-- | tests/ui/compiletest-self-test/test-aux-bin.rs | 9 |
4 files changed, 98 insertions, 29 deletions
diff --git a/src/tools/compiletest/src/header.rs b/src/tools/compiletest/src/header.rs index a512599f723..6ff47dbffbc 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<String>, + pub aux_bin: Vec<String>, pub aux_crate: Vec<(String, String)>, pub revisions: Vec<String>, } @@ -61,6 +62,12 @@ impl EarlyProps { }); 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, &mut props.aux_crate, Config::parse_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<String>, + // Auxiliary crates that should be compiled as `#![crate_type = "bin"]`. + pub aux_bins: Vec<String>, // 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 83c595ce241..67db33abf65 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -82,21 +82,21 @@ fn disable_error_reporting<F: FnOnce() -> R, R>(f: F) -> R { } /// The platform-specific library name -pub 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 - // with '--extern-meta' is the '.lib' 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) -> Option<String> { + 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 => 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) + }), } } @@ -2098,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 is_dylib = 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('-', "_"), is_dylib); - rustc.arg("--extern").arg(format!("{}={}/{}", aux_name, aux_dir.display(), lib_name)); + get_lib_name(&aux_path.trim_end_matches(".rs").replace('-', "_"), aux_type); + if let Some(lib_name) = lib_name { + rustc.arg("--extern").arg(format!( + "{}={}/{}", + aux_name, + aux_dir.display(), + lib_name + )); + } } } @@ -2129,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) -> bool { + 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, @@ -2152,15 +2180,17 @@ 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 (dylib, crate_type) = if aux_props.no_prefer_dynamic { - (true, None) + 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") && !aux_props.force_host @@ -2185,9 +2215,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 +2241,7 @@ impl<'test> TestCx<'test> { &auxres, ); } - dylib + aux_type } fn read2_abbreviated(&self, child: Child) -> (Output, Truncated) { @@ -2677,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()) @@ -4826,3 +4862,9 @@ enum LinkToAux { Yes, No, } + +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 00000000000..09411eb121c --- /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 00000000000..9e01e3ffabf --- /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"); +} |
