Skip to content

run-make: refactor out command wrappers for clang and llvm-readobj #123729

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Apr 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions src/tools/run-make-support/src/clang.rs
Original file line number Diff line number Diff line change
@@ -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
}
}
4 changes: 4 additions & 0 deletions src/tools/run-make-support/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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};
Expand Down
44 changes: 44 additions & 0 deletions src/tools/run-make-support/src/llvm_readobj.rs
Original file line number Diff line number Diff line change
@@ -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
}
}
61 changes: 19 additions & 42 deletions tests/run-make/cross-lang-lto-riscv-abi/rmake.rs
Original file line number Diff line number Diff line change
@@ -1,24 +1,17 @@
//! 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,
process::{Command, Output},
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
Expand All @@ -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() {
Expand Down
Loading