about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/tools/run-make-support/src/clang.rs73
-rw-r--r--src/tools/run-make-support/src/lib.rs4
-rw-r--r--src/tools/run-make-support/src/llvm_readobj.rs44
-rw-r--r--tests/run-make/cross-lang-lto-riscv-abi/rmake.rs61
4 files changed, 140 insertions, 42 deletions
diff --git a/src/tools/run-make-support/src/clang.rs b/src/tools/run-make-support/src/clang.rs
new file mode 100644
index 00000000000..ed9f8383dc3
--- /dev/null
+++ b/src/tools/run-make-support/src/clang.rs
@@ -0,0 +1,73 @@
+use std::env;
+use std::path::Path;
+use std::process::Command;
+
+use crate::{bin_name, handle_failed_output, tmp_dir};
+
+/// Construct a new `clang` invocation. `clang` is not always available for all targets.
+pub fn clang() -> Clang {
+    Clang::new()
+}
+
+/// A `clang` invocation builder.
+#[derive(Debug)]
+pub struct Clang {
+    cmd: Command,
+}
+
+crate::impl_common_helpers!(Clang);
+
+impl Clang {
+    /// Construct a new `clang` invocation. `clang` is not always available for all targets.
+    pub fn new() -> Self {
+        let clang =
+            env::var("CLANG").expect("`CLANG` not specified, but this is required to find `clang`");
+        let cmd = Command::new(clang);
+        Self { cmd }
+    }
+
+    /// Provide an input file.
+    pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
+        self.cmd.arg(path.as_ref());
+        self
+    }
+
+    /// Specify the name of the executable. The executable will be placed under `$TMPDIR`, and the
+    /// extension will be determined by [`bin_name`].
+    pub fn out_exe(&mut self, name: &str) -> &mut Self {
+        self.cmd.arg("-o");
+        self.cmd.arg(tmp_dir().join(bin_name(name)));
+        self
+    }
+
+    /// Specify which target triple clang should target.
+    pub fn target(&mut self, target_triple: &str) -> &mut Self {
+        self.cmd.arg("-target");
+        self.cmd.arg(target_triple);
+        self
+    }
+
+    /// Pass `-nostdlib` to disable linking the C standard library.
+    pub fn no_stdlib(&mut self) -> &mut Self {
+        self.cmd.arg("-nostdlib");
+        self
+    }
+
+    /// Specify architecture.
+    pub fn arch(&mut self, arch: &str) -> &mut Self {
+        self.cmd.arg(format!("-march={arch}"));
+        self
+    }
+
+    /// Specify LTO settings.
+    pub fn lto(&mut self, lto: &str) -> &mut Self {
+        self.cmd.arg(format!("-flto={lto}"));
+        self
+    }
+
+    /// Specify which ld to use.
+    pub fn use_ld(&mut self, ld: &str) -> &mut Self {
+        self.cmd.arg(format!("-fuse-ld={ld}"));
+        self
+    }
+}
diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs
index 9a4fdff5d15..e723e824ed6 100644
--- a/src/tools/run-make-support/src/lib.rs
+++ b/src/tools/run-make-support/src/lib.rs
@@ -4,6 +4,8 @@
 //! as `object` or `wasmparser`, they can be re-exported and be made available through this library.
 
 pub mod cc;
+pub mod clang;
+pub mod llvm_readobj;
 pub mod run;
 pub mod rustc;
 pub mod rustdoc;
@@ -17,6 +19,8 @@ pub use regex;
 pub use wasmparser;
 
 pub use cc::{cc, extra_c_flags, extra_cxx_flags, Cc};
+pub use clang::{clang, Clang};
+pub use llvm_readobj::{llvm_readobj, LlvmReadobj};
 pub use run::{run, run_fail};
 pub use rustc::{aux_build, rustc, Rustc};
 pub use rustdoc::{bare_rustdoc, rustdoc, Rustdoc};
diff --git a/src/tools/run-make-support/src/llvm_readobj.rs b/src/tools/run-make-support/src/llvm_readobj.rs
new file mode 100644
index 00000000000..32ea07e932e
--- /dev/null
+++ b/src/tools/run-make-support/src/llvm_readobj.rs
@@ -0,0 +1,44 @@
+use std::env;
+use std::path::{Path, PathBuf};
+use std::process::Command;
+
+use crate::handle_failed_output;
+
+/// Construct a new `llvm-readobj` invocation. This assumes that `llvm-readobj` is available
+/// at `$LLVM_BIN_DIR/llvm-readobj`.
+pub fn llvm_readobj() -> LlvmReadobj {
+    LlvmReadobj::new()
+}
+
+/// A `llvm-readobj` invocation builder.
+#[derive(Debug)]
+pub struct LlvmReadobj {
+    cmd: Command,
+}
+
+crate::impl_common_helpers!(LlvmReadobj);
+
+impl LlvmReadobj {
+    /// Construct a new `llvm-readobj` invocation. This assumes that `llvm-readobj` is available
+    /// at `$LLVM_BIN_DIR/llvm-readobj`.
+    pub fn new() -> Self {
+        let llvm_bin_dir = env::var("LLVM_BIN_DIR")
+            .expect("`LLVM_BIN_DIR` not specified, but this is required to find `llvm-readobj`");
+        let llvm_bin_dir = PathBuf::from(llvm_bin_dir);
+        let llvm_readobj = llvm_bin_dir.join("llvm-readobj");
+        let cmd = Command::new(llvm_readobj);
+        Self { cmd }
+    }
+
+    /// Provide an input file.
+    pub fn input<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
+        self.cmd.arg(path.as_ref());
+        self
+    }
+
+    /// Pass `--file-header` to display file headers.
+    pub fn file_header(&mut self) -> &mut Self {
+        self.cmd.arg("--file-header");
+        self
+    }
+}
diff --git a/tests/run-make/cross-lang-lto-riscv-abi/rmake.rs b/tests/run-make/cross-lang-lto-riscv-abi/rmake.rs
index 2f13cf17169..b534a99f8cf 100644
--- a/tests/run-make/cross-lang-lto-riscv-abi/rmake.rs
+++ b/tests/run-make/cross-lang-lto-riscv-abi/rmake.rs
@@ -1,10 +1,10 @@
 //! Make sure that cross-language LTO works on riscv targets,
-//! which requires extra abi metadata to be emitted.
+//! which requires extra `target-abi` metadata to be emitted.
 //@ needs-matching-clang
 //@ needs-llvm-components riscv
 extern crate run_make_support;
 
-use run_make_support::{bin_name, rustc, tmp_dir};
+use run_make_support::{bin_name, clang, llvm_readobj, rustc, tmp_dir};
 use std::{
     env,
     path::PathBuf,
@@ -12,13 +12,6 @@ use std::{
     str,
 };
 
-fn handle_failed_output(output: Output) {
-    eprintln!("output status: `{}`", output.status);
-    eprintln!("=== STDOUT ===\n{}\n\n", String::from_utf8(output.stdout).unwrap());
-    eprintln!("=== STDERR ===\n{}\n\n", String::from_utf8(output.stderr).unwrap());
-    std::process::exit(1)
-}
-
 fn check_target(target: &str, clang_target: &str, carch: &str, is_double_float: bool) {
     eprintln!("Checking target {target}");
     // Rust part
@@ -30,40 +23,24 @@ fn check_target(target: &str, clang_target: &str, carch: &str, is_double_float:
         .linker_plugin_lto("on")
         .run();
     // C part
-    let clang = env::var("CLANG").unwrap();
-    let mut cmd = Command::new(clang);
-    let executable = tmp_dir().join("riscv-xlto");
-    cmd.arg("-target")
-        .arg(clang_target)
-        .arg(format!("-march={carch}"))
-        .arg(format!("-flto=thin"))
-        .arg(format!("-fuse-ld=lld"))
-        .arg("-nostdlib")
-        .arg("-o")
-        .arg(&executable)
-        .arg("cstart.c")
-        .arg(tmp_dir().join("libriscv_xlto.rlib"));
-    eprintln!("{cmd:?}");
-    let output = cmd.output().unwrap();
-    if !output.status.success() {
-        handle_failed_output(output);
-    }
+    clang()
+        .target(clang_target)
+        .arch(carch)
+        .lto("thin")
+        .use_ld("lld")
+        .no_stdlib()
+        .out_exe("riscv-xlto")
+        .input("cstart.c")
+        .input(tmp_dir().join("libriscv_xlto.rlib"))
+        .run();
+
     // Check that the built binary has correct float abi
-    let llvm_readobj =
-        PathBuf::from(env::var("LLVM_BIN_DIR").unwrap()).join(bin_name("llvm-readobj"));
-    let mut cmd = Command::new(llvm_readobj);
-    cmd.arg("--file-header").arg(executable);
-    eprintln!("{cmd:?}");
-    let output = cmd.output().unwrap();
-    if output.status.success() {
-        assert!(
-            !(is_double_float
-                ^ dbg!(str::from_utf8(&output.stdout).unwrap())
-                    .contains("EF_RISCV_FLOAT_ABI_DOUBLE"))
-        )
-    } else {
-        handle_failed_output(output);
-    }
+    let executable = tmp_dir().join(bin_name("riscv-xlto"));
+    let output = llvm_readobj().input(&executable).file_header().run();
+    let stdout = String::from_utf8_lossy(&output.stdout);
+    eprintln!("obj:\n{}", stdout);
+
+    assert!(!(is_double_float ^ stdout.contains("EF_RISCV_FLOAT_ABI_DOUBLE")));
 }
 
 fn main() {