about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2024-03-19 18:03:50 +0100
committerGitHub <noreply@github.com>2024-03-19 18:03:50 +0100
commit42dec6f874c81fd1a6c72f05a8dc439916669bc7 (patch)
treea6afbbd8744939fe2912c6c1de9204dfaa5c9f09
parent45e005df427154254d662f3941fef06581432f2b (diff)
parent3a5eb35577f37544df95c7502344aba4ae7076ee (diff)
downloadrust-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.rs15
-rw-r--r--src/tools/compiletest/src/runtest.rs100
-rw-r--r--tests/ui/compiletest-self-test/auxiliary/print-it-works.rs3
-rw-r--r--tests/ui/compiletest-self-test/test-aux-bin.rs9
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");
+}