Add supporting infrastructure for run-make
V2 tests
This commit is contained in:
parent
d3d145ea1c
commit
48e9f92ce2
@ -3274,6 +3274,10 @@ dependencies = [
|
||||
"serde_json",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "run_make_support"
|
||||
version = "0.0.0"
|
||||
|
||||
[[package]]
|
||||
name = "rust-demangler"
|
||||
version = "0.0.1"
|
||||
|
@ -10,6 +10,7 @@ members = [
|
||||
"src/tools/clippy",
|
||||
"src/tools/clippy/clippy_dev",
|
||||
"src/tools/compiletest",
|
||||
"src/tools/run-make-support",
|
||||
"src/tools/error_index_generator",
|
||||
"src/tools/linkchecker",
|
||||
"src/tools/lint-docs",
|
||||
|
@ -1327,6 +1327,52 @@ fn run(self, builder: &Builder<'_>) {
|
||||
};
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]
|
||||
pub struct RunMakeSupport {
|
||||
pub compiler: Compiler,
|
||||
pub target: TargetSelection,
|
||||
}
|
||||
|
||||
impl Step for RunMakeSupport {
|
||||
type Output = PathBuf;
|
||||
const DEFAULT: bool = true;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.never()
|
||||
}
|
||||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
|
||||
run.builder.ensure(RunMakeSupport { compiler, target: run.build_triple() });
|
||||
}
|
||||
|
||||
fn run(self, builder: &Builder<'_>) -> PathBuf {
|
||||
builder.ensure(compile::Std::new(self.compiler, self.target));
|
||||
|
||||
let cargo = tool::prepare_tool_cargo(
|
||||
builder,
|
||||
self.compiler,
|
||||
Mode::ToolStd,
|
||||
self.target,
|
||||
"build",
|
||||
"src/tools/run-make-support",
|
||||
SourceType::InTree,
|
||||
&[],
|
||||
);
|
||||
|
||||
let mut cargo = Command::from(cargo);
|
||||
builder.run(&mut cargo);
|
||||
|
||||
let lib_name = "librun_make_support.rlib";
|
||||
let lib = builder.tools_dir(self.compiler).join(&lib_name);
|
||||
|
||||
let cargo_out =
|
||||
builder.cargo_out(self.compiler, Mode::ToolStd, self.target).join(&lib_name);
|
||||
builder.copy(&cargo_out, &lib);
|
||||
lib
|
||||
}
|
||||
}
|
||||
|
||||
default_test!(Ui { path: "tests/ui", mode: "ui", suite: "ui" });
|
||||
|
||||
default_test!(RunPassValgrind {
|
||||
@ -1361,7 +1407,40 @@ fn run(self, builder: &Builder<'_>) {
|
||||
|
||||
host_test!(Pretty { path: "tests/pretty", mode: "pretty", suite: "pretty" });
|
||||
|
||||
default_test!(RunMake { path: "tests/run-make", mode: "run-make", suite: "run-make" });
|
||||
// Special-handling is needed for `run-make`, so don't use `default_test` for defining `RunMake`
|
||||
// tests.
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
|
||||
pub struct RunMake {
|
||||
pub compiler: Compiler,
|
||||
pub target: TargetSelection,
|
||||
}
|
||||
|
||||
impl Step for RunMake {
|
||||
type Output = ();
|
||||
const DEFAULT: bool = true;
|
||||
const ONLY_HOSTS: bool = false;
|
||||
|
||||
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
|
||||
run.suite_path("tests/run-make")
|
||||
}
|
||||
|
||||
fn make_run(run: RunConfig<'_>) {
|
||||
let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
|
||||
run.builder.ensure(RunMakeSupport { compiler, target: run.build_triple() });
|
||||
run.builder.ensure(RunMake { compiler, target: run.target });
|
||||
}
|
||||
|
||||
fn run(self, builder: &Builder<'_>) {
|
||||
builder.ensure(Compiletest {
|
||||
compiler: self.compiler,
|
||||
target: self.target,
|
||||
mode: "run-make",
|
||||
suite: "run-make",
|
||||
path: "tests/run-make",
|
||||
compare_mode: None,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
host_test!(RunMakeFullDeps {
|
||||
path: "tests/run-make-fulldeps",
|
||||
|
@ -655,7 +655,14 @@ fn collect_tests_from_dir(
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if config.mode == Mode::RunMake && dir.join("Makefile").exists() {
|
||||
if config.mode == Mode::RunMake {
|
||||
if dir.join("Makefile").exists() && dir.join("rmake.rs").exists() {
|
||||
return Err(io::Error::other(
|
||||
"run-make tests cannot have both `Makefile` and `rmake.rs`",
|
||||
));
|
||||
}
|
||||
|
||||
if dir.join("Makefile").exists() || dir.join("rmake.rs").exists() {
|
||||
let paths = TestPaths {
|
||||
file: dir.to_path_buf(),
|
||||
relative_dir: relative_dir_path.parent().unwrap().to_path_buf(),
|
||||
@ -663,6 +670,7 @@ fn collect_tests_from_dir(
|
||||
tests.extend(make_test(config, cache, &paths, inputs, poisoned));
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
|
||||
// If we find a test foo/bar.rs, we have to build the
|
||||
// output directory `$build/foo` so we can write
|
||||
@ -733,8 +741,17 @@ fn make_test(
|
||||
poisoned: &mut bool,
|
||||
) -> Vec<test::TestDescAndFn> {
|
||||
let test_path = if config.mode == Mode::RunMake {
|
||||
// Parse directives in the Makefile
|
||||
if testpaths.file.join("rmake.rs").exists() && testpaths.file.join("Makefile").exists() {
|
||||
panic!("run-make tests cannot have both `rmake.rs` and `Makefile`");
|
||||
}
|
||||
|
||||
if testpaths.file.join("rmake.rs").exists() {
|
||||
// Parse directives in rmake.rs.
|
||||
testpaths.file.join("rmake.rs")
|
||||
} else {
|
||||
// Parse directives in the Makefile.
|
||||
testpaths.file.join("Makefile")
|
||||
}
|
||||
} else {
|
||||
PathBuf::from(&testpaths.file)
|
||||
};
|
||||
|
@ -3570,6 +3570,17 @@ fn run_incremental_test(&self) {
|
||||
}
|
||||
|
||||
fn run_rmake_test(&self) {
|
||||
let test_dir = &self.testpaths.file;
|
||||
if test_dir.join("rmake.rs").exists() {
|
||||
self.run_rmake_v2_test();
|
||||
} else if test_dir.join("Makefile").exists() {
|
||||
self.run_rmake_legacy_test();
|
||||
} else {
|
||||
self.fatal("failed to find either `rmake.rs` or `Makefile`")
|
||||
}
|
||||
}
|
||||
|
||||
fn run_rmake_legacy_test(&self) {
|
||||
let cwd = env::current_dir().unwrap();
|
||||
let src_root = self.config.src_base.parent().unwrap().parent().unwrap();
|
||||
let src_root = cwd.join(&src_root);
|
||||
@ -3737,6 +3748,238 @@ fn aggressive_rm_rf(&self, path: &Path) -> io::Result<()> {
|
||||
fs::remove_dir(path)
|
||||
}
|
||||
|
||||
fn run_rmake_v2_test(&self) {
|
||||
// For `run-make` V2, we need to perform 2 steps to build and run a `run-make` V2 recipe
|
||||
// (`rmake.rs`) to run the actual tests. The support library is already built as a tool
|
||||
// dylib and is available under `build/$TARGET/stageN-tools-bin/librun_make_support.rlib`.
|
||||
//
|
||||
// 1. We need to build the recipe `rmake.rs` and link in the support library.
|
||||
// 2. We need to run the recipe to build and run the tests.
|
||||
let cwd = env::current_dir().unwrap();
|
||||
let src_root = self.config.src_base.parent().unwrap().parent().unwrap();
|
||||
let src_root = cwd.join(&src_root);
|
||||
let build_root = self.config.build_base.parent().unwrap().parent().unwrap();
|
||||
let build_root = cwd.join(&build_root);
|
||||
|
||||
let tmpdir = cwd.join(self.output_base_name());
|
||||
if tmpdir.exists() {
|
||||
self.aggressive_rm_rf(&tmpdir).unwrap();
|
||||
}
|
||||
create_dir_all(&tmpdir).unwrap();
|
||||
|
||||
// HACK: assume stageN-target, we only want stageN.
|
||||
let stage = self.config.stage_id.split('-').next().unwrap();
|
||||
|
||||
// First, we construct the path to the built support library.
|
||||
let mut support_lib_path = PathBuf::new();
|
||||
support_lib_path.push(&build_root);
|
||||
support_lib_path.push(format!("{}-tools-bin", stage));
|
||||
support_lib_path.push("librun_make_support.rlib");
|
||||
|
||||
let mut stage_std_path = PathBuf::new();
|
||||
stage_std_path.push(&build_root);
|
||||
stage_std_path.push(&stage);
|
||||
stage_std_path.push("lib");
|
||||
|
||||
// Then, we need to build the recipe `rmake.rs` and link in the support library.
|
||||
let recipe_bin =
|
||||
tmpdir.join(if self.config.target.contains("windows") { "rmake.exe" } else { "rmake" });
|
||||
|
||||
let mut support_lib_deps = PathBuf::new();
|
||||
support_lib_deps.push(&build_root);
|
||||
support_lib_deps.push(format!("{}-tools", stage));
|
||||
support_lib_deps.push(&self.config.host);
|
||||
support_lib_deps.push("release");
|
||||
support_lib_deps.push("deps");
|
||||
|
||||
let mut support_lib_deps_deps = PathBuf::new();
|
||||
support_lib_deps_deps.push(&build_root);
|
||||
support_lib_deps_deps.push(format!("{}-tools", stage));
|
||||
support_lib_deps_deps.push("release");
|
||||
support_lib_deps_deps.push("deps");
|
||||
|
||||
debug!(?support_lib_deps);
|
||||
debug!(?support_lib_deps_deps);
|
||||
|
||||
let res = self.cmd2procres(
|
||||
Command::new(&self.config.rustc_path)
|
||||
.arg("-o")
|
||||
.arg(&recipe_bin)
|
||||
.arg(format!(
|
||||
"-Ldependency={}",
|
||||
&support_lib_path.parent().unwrap().to_string_lossy()
|
||||
))
|
||||
.arg(format!("-Ldependency={}", &support_lib_deps.to_string_lossy()))
|
||||
.arg(format!("-Ldependency={}", &support_lib_deps_deps.to_string_lossy()))
|
||||
.arg("--extern")
|
||||
.arg(format!("run_make_support={}", &support_lib_path.to_string_lossy()))
|
||||
.arg(&self.testpaths.file.join("rmake.rs"))
|
||||
.env("TARGET", &self.config.target)
|
||||
.env("PYTHON", &self.config.python)
|
||||
.env("S", &src_root)
|
||||
.env("RUST_BUILD_STAGE", &self.config.stage_id)
|
||||
.env("RUSTC", cwd.join(&self.config.rustc_path))
|
||||
.env("TMPDIR", &tmpdir)
|
||||
.env("LD_LIB_PATH_ENVVAR", dylib_env_var())
|
||||
.env("HOST_RPATH_DIR", cwd.join(&self.config.compile_lib_path))
|
||||
.env("TARGET_RPATH_DIR", cwd.join(&self.config.run_lib_path))
|
||||
.env("LLVM_COMPONENTS", &self.config.llvm_components)
|
||||
// We for sure don't want these tests to run in parallel, so make
|
||||
// sure they don't have access to these vars if we run via `make`
|
||||
// at the top level
|
||||
.env_remove("MAKEFLAGS")
|
||||
.env_remove("MFLAGS")
|
||||
.env_remove("CARGO_MAKEFLAGS"),
|
||||
);
|
||||
if !res.status.success() {
|
||||
self.fatal_proc_rec("run-make test failed: could not build `rmake.rs` recipe", &res);
|
||||
}
|
||||
|
||||
// Finally, we need to run the recipe binary to build and run the actual tests.
|
||||
debug!(?recipe_bin);
|
||||
|
||||
let mut dylib_env_paths = String::new();
|
||||
dylib_env_paths.push_str(&env::var(dylib_env_var()).unwrap());
|
||||
dylib_env_paths.push(':');
|
||||
dylib_env_paths.push_str(&support_lib_path.parent().unwrap().to_string_lossy());
|
||||
dylib_env_paths.push(':');
|
||||
dylib_env_paths.push_str(
|
||||
&stage_std_path.join("rustlib").join(&self.config.host).join("lib").to_string_lossy(),
|
||||
);
|
||||
|
||||
let mut target_rpath_env_path = String::new();
|
||||
target_rpath_env_path.push_str(&tmpdir.to_string_lossy());
|
||||
target_rpath_env_path.push(':');
|
||||
target_rpath_env_path.push_str(&dylib_env_paths);
|
||||
|
||||
let mut cmd = Command::new(&recipe_bin);
|
||||
cmd.current_dir(&self.testpaths.file)
|
||||
.stdout(Stdio::piped())
|
||||
.stderr(Stdio::piped())
|
||||
.env("LD_LIB_PATH_ENVVAR", dylib_env_var())
|
||||
.env("TARGET_RPATH_ENV", &target_rpath_env_path)
|
||||
.env(dylib_env_var(), &dylib_env_paths)
|
||||
.env("TARGET", &self.config.target)
|
||||
.env("PYTHON", &self.config.python)
|
||||
.env("S", &src_root)
|
||||
.env("RUST_BUILD_STAGE", &self.config.stage_id)
|
||||
.env("RUSTC", cwd.join(&self.config.rustc_path))
|
||||
.env("TMPDIR", &tmpdir)
|
||||
.env("HOST_RPATH_DIR", cwd.join(&self.config.compile_lib_path))
|
||||
.env("TARGET_RPATH_DIR", cwd.join(&self.config.run_lib_path))
|
||||
.env("LLVM_COMPONENTS", &self.config.llvm_components)
|
||||
// We for sure don't want these tests to run in parallel, so make
|
||||
// sure they don't have access to these vars if we run via `make`
|
||||
// at the top level
|
||||
.env_remove("MAKEFLAGS")
|
||||
.env_remove("MFLAGS")
|
||||
.env_remove("CARGO_MAKEFLAGS");
|
||||
|
||||
if let Some(ref rustdoc) = self.config.rustdoc_path {
|
||||
cmd.env("RUSTDOC", cwd.join(rustdoc));
|
||||
}
|
||||
|
||||
if let Some(ref rust_demangler) = self.config.rust_demangler_path {
|
||||
cmd.env("RUST_DEMANGLER", cwd.join(rust_demangler));
|
||||
}
|
||||
|
||||
if let Some(ref node) = self.config.nodejs {
|
||||
cmd.env("NODE", node);
|
||||
}
|
||||
|
||||
if let Some(ref linker) = self.config.target_linker {
|
||||
cmd.env("RUSTC_LINKER", linker);
|
||||
}
|
||||
|
||||
if let Some(ref clang) = self.config.run_clang_based_tests_with {
|
||||
cmd.env("CLANG", clang);
|
||||
}
|
||||
|
||||
if let Some(ref filecheck) = self.config.llvm_filecheck {
|
||||
cmd.env("LLVM_FILECHECK", filecheck);
|
||||
}
|
||||
|
||||
if let Some(ref llvm_bin_dir) = self.config.llvm_bin_dir {
|
||||
cmd.env("LLVM_BIN_DIR", llvm_bin_dir);
|
||||
}
|
||||
|
||||
if let Some(ref remote_test_client) = self.config.remote_test_client {
|
||||
cmd.env("REMOTE_TEST_CLIENT", remote_test_client);
|
||||
}
|
||||
|
||||
// We don't want RUSTFLAGS set from the outside to interfere with
|
||||
// compiler flags set in the test cases:
|
||||
cmd.env_remove("RUSTFLAGS");
|
||||
|
||||
// Use dynamic musl for tests because static doesn't allow creating dylibs
|
||||
if self.config.host.contains("musl") {
|
||||
cmd.env("RUSTFLAGS", "-Ctarget-feature=-crt-static").env("IS_MUSL_HOST", "1");
|
||||
}
|
||||
|
||||
if self.config.bless {
|
||||
cmd.env("RUSTC_BLESS_TEST", "--bless");
|
||||
// Assume this option is active if the environment variable is "defined", with _any_ value.
|
||||
// As an example, a `Makefile` can use this option by:
|
||||
//
|
||||
// ifdef RUSTC_BLESS_TEST
|
||||
// cp "$(TMPDIR)"/actual_something.ext expected_something.ext
|
||||
// else
|
||||
// $(DIFF) expected_something.ext "$(TMPDIR)"/actual_something.ext
|
||||
// endif
|
||||
}
|
||||
|
||||
if self.config.target.contains("msvc") && self.config.cc != "" {
|
||||
// We need to pass a path to `lib.exe`, so assume that `cc` is `cl.exe`
|
||||
// and that `lib.exe` lives next to it.
|
||||
let lib = Path::new(&self.config.cc).parent().unwrap().join("lib.exe");
|
||||
|
||||
// MSYS doesn't like passing flags of the form `/foo` as it thinks it's
|
||||
// a path and instead passes `C:\msys64\foo`, so convert all
|
||||
// `/`-arguments to MSVC here to `-` arguments.
|
||||
let cflags = self
|
||||
.config
|
||||
.cflags
|
||||
.split(' ')
|
||||
.map(|s| s.replace("/", "-"))
|
||||
.collect::<Vec<_>>()
|
||||
.join(" ");
|
||||
let cxxflags = self
|
||||
.config
|
||||
.cxxflags
|
||||
.split(' ')
|
||||
.map(|s| s.replace("/", "-"))
|
||||
.collect::<Vec<_>>()
|
||||
.join(" ");
|
||||
|
||||
cmd.env("IS_MSVC", "1")
|
||||
.env("IS_WINDOWS", "1")
|
||||
.env("MSVC_LIB", format!("'{}' -nologo", lib.display()))
|
||||
.env("CC", format!("'{}' {}", self.config.cc, cflags))
|
||||
.env("CXX", format!("'{}' {}", &self.config.cxx, cxxflags));
|
||||
} else {
|
||||
cmd.env("CC", format!("{} {}", self.config.cc, self.config.cflags))
|
||||
.env("CXX", format!("{} {}", self.config.cxx, self.config.cxxflags))
|
||||
.env("AR", &self.config.ar);
|
||||
|
||||
if self.config.target.contains("windows") {
|
||||
cmd.env("IS_WINDOWS", "1");
|
||||
}
|
||||
}
|
||||
|
||||
let (Output { stdout, stderr, status }, truncated) =
|
||||
self.read2_abbreviated(cmd.spawn().expect("failed to spawn `rmake`"));
|
||||
if !status.success() {
|
||||
let res = ProcRes {
|
||||
status,
|
||||
stdout: String::from_utf8_lossy(&stdout).into_owned(),
|
||||
stderr: String::from_utf8_lossy(&stderr).into_owned(),
|
||||
truncated,
|
||||
cmdline: format!("{:?}", cmd),
|
||||
};
|
||||
self.fatal_proc_rec("rmake recipe failed to complete", &res);
|
||||
}
|
||||
}
|
||||
|
||||
fn run_js_doc_test(&self) {
|
||||
if let Some(nodejs) = &self.config.nodejs {
|
||||
let out_dir = self.output_base_dir();
|
||||
|
6
src/tools/run-make-support/Cargo.toml
Normal file
6
src/tools/run-make-support/Cargo.toml
Normal file
@ -0,0 +1,6 @@
|
||||
[package]
|
||||
name = "run_make_support"
|
||||
version = "0.0.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
151
src/tools/run-make-support/src/lib.rs
Normal file
151
src/tools/run-make-support/src/lib.rs
Normal file
@ -0,0 +1,151 @@
|
||||
use std::env;
|
||||
use std::path::{Path, PathBuf};
|
||||
use std::process::{Command, Output};
|
||||
|
||||
fn setup_common_build_cmd() -> Command {
|
||||
let rustc = env::var("RUSTC").unwrap();
|
||||
let mut cmd = Command::new(rustc);
|
||||
cmd.arg("--out-dir")
|
||||
.arg(env::var("TMPDIR").unwrap())
|
||||
.arg("-L")
|
||||
.arg(env::var("TMPDIR").unwrap());
|
||||
cmd
|
||||
}
|
||||
|
||||
fn handle_failed_output(cmd: &str, output: Output, caller_line_number: u32) -> ! {
|
||||
eprintln!("command failed at line {caller_line_number}");
|
||||
eprintln!("{cmd}");
|
||||
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)
|
||||
}
|
||||
|
||||
pub fn rustc() -> RustcInvocationBuilder {
|
||||
RustcInvocationBuilder::new()
|
||||
}
|
||||
|
||||
pub fn aux_build() -> AuxBuildInvocationBuilder {
|
||||
AuxBuildInvocationBuilder::new()
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct RustcInvocationBuilder {
|
||||
cmd: Command,
|
||||
}
|
||||
|
||||
impl RustcInvocationBuilder {
|
||||
fn new() -> Self {
|
||||
let cmd = setup_common_build_cmd();
|
||||
Self { cmd }
|
||||
}
|
||||
|
||||
pub fn arg(&mut self, arg: &str) -> &mut RustcInvocationBuilder {
|
||||
self.cmd.arg(arg);
|
||||
self
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn run(&mut self) -> Output {
|
||||
let caller_location = std::panic::Location::caller();
|
||||
let caller_line_number = caller_location.line();
|
||||
|
||||
let output = self.cmd.output().unwrap();
|
||||
if !output.status.success() {
|
||||
handle_failed_output(&format!("{:#?}", self.cmd), output, caller_line_number);
|
||||
}
|
||||
output
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AuxBuildInvocationBuilder {
|
||||
cmd: Command,
|
||||
}
|
||||
|
||||
impl AuxBuildInvocationBuilder {
|
||||
fn new() -> Self {
|
||||
let mut cmd = setup_common_build_cmd();
|
||||
cmd.arg("--crate-type=lib");
|
||||
Self { cmd }
|
||||
}
|
||||
|
||||
pub fn arg(&mut self, arg: &str) -> &mut AuxBuildInvocationBuilder {
|
||||
self.cmd.arg(arg);
|
||||
self
|
||||
}
|
||||
|
||||
#[track_caller]
|
||||
pub fn run(&mut self) -> Output {
|
||||
let caller_location = std::panic::Location::caller();
|
||||
let caller_line_number = caller_location.line();
|
||||
|
||||
let output = self.cmd.output().unwrap();
|
||||
if !output.status.success() {
|
||||
handle_failed_output(&format!("{:#?}", self.cmd), output, caller_line_number);
|
||||
}
|
||||
output
|
||||
}
|
||||
}
|
||||
|
||||
fn run_common(bin_name: &str) -> (Command, Output) {
|
||||
let target = env::var("TARGET").unwrap();
|
||||
|
||||
let bin_name =
|
||||
if target.contains("windows") { format!("{}.exe", bin_name) } else { bin_name.to_owned() };
|
||||
|
||||
let mut bin_path = PathBuf::new();
|
||||
bin_path.push(env::var("TMPDIR").unwrap());
|
||||
bin_path.push(&bin_name);
|
||||
let ld_lib_path_envvar = env::var("LD_LIB_PATH_ENVVAR").unwrap();
|
||||
let mut cmd = Command::new(bin_path);
|
||||
cmd.env(&ld_lib_path_envvar, {
|
||||
let mut paths = vec![];
|
||||
paths.push(PathBuf::from(env::var("TMPDIR").unwrap()));
|
||||
for p in env::split_paths(&env::var("TARGET_RPATH_ENV").unwrap()) {
|
||||
paths.push(p.to_path_buf());
|
||||
}
|
||||
for p in env::split_paths(&env::var(&ld_lib_path_envvar).unwrap()) {
|
||||
paths.push(p.to_path_buf());
|
||||
}
|
||||
env::join_paths(paths.iter()).unwrap()
|
||||
});
|
||||
|
||||
if target.contains("windows") {
|
||||
let mut paths = vec![];
|
||||
for p in env::split_paths(&std::env::var("PATH").unwrap_or(String::new())) {
|
||||
paths.push(p.to_path_buf());
|
||||
}
|
||||
paths.push(Path::new(&std::env::var("TARGET_RPATH_DIR").unwrap()).to_path_buf());
|
||||
cmd.env("PATH", env::join_paths(paths.iter()).unwrap());
|
||||
}
|
||||
|
||||
let output = cmd.output().unwrap();
|
||||
(cmd, output)
|
||||
}
|
||||
|
||||
/// Run a built binary and make sure it succeeds.
|
||||
#[track_caller]
|
||||
pub fn run(bin_name: &str) -> Output {
|
||||
let caller_location = std::panic::Location::caller();
|
||||
let caller_line_number = caller_location.line();
|
||||
|
||||
let (cmd, output) = run_common(bin_name);
|
||||
if !output.status.success() {
|
||||
handle_failed_output(&format!("{:#?}", cmd), output, caller_line_number);
|
||||
}
|
||||
output
|
||||
}
|
||||
|
||||
/// Run a built binary and make sure it fails.
|
||||
#[track_caller]
|
||||
pub fn run_fail(bin_name: &str) -> Output {
|
||||
let caller_location = std::panic::Location::caller();
|
||||
let caller_line_number = caller_location.line();
|
||||
|
||||
let (cmd, output) = run_common(bin_name);
|
||||
if output.status.success() {
|
||||
handle_failed_output(&format!("{:#?}", cmd), output, caller_line_number);
|
||||
}
|
||||
output
|
||||
}
|
@ -1,6 +0,0 @@
|
||||
include ../tools.mk
|
||||
|
||||
all:
|
||||
$(RUSTC) --emit=metadata --crate-type lib stable.rs
|
||||
$(RUSTC) --emit=metadata --extern stable=$(TMPDIR)/libstable.rmeta main.rs 2>&1 >/dev/null \
|
||||
| $(CGREP) -e "stable since $$(cat $(S)/src/version)(-[a-zA-Z]+)?"
|
27
tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs
Normal file
27
tests/run-make/CURRENT_RUSTC_VERSION/rmake.rs
Normal file
@ -0,0 +1,27 @@
|
||||
// ignore-tidy-linelength
|
||||
|
||||
extern crate run_make_support;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use run_make_support::{aux_build, rustc};
|
||||
|
||||
fn main() {
|
||||
aux_build()
|
||||
.arg("--emit=metadata")
|
||||
.arg("stable.rs")
|
||||
.run();
|
||||
let mut stable_path = PathBuf::from(env!("TMPDIR"));
|
||||
stable_path.push("libstable.rmeta");
|
||||
let output = rustc()
|
||||
.arg("--emit=metadata")
|
||||
.arg("--extern")
|
||||
.arg(&format!("stable={}", &stable_path.to_string_lossy()))
|
||||
.arg("main.rs")
|
||||
.run();
|
||||
|
||||
let stderr = String::from_utf8_lossy(&output.stderr);
|
||||
let version = include_str!(concat!(env!("S"), "/src/version"));
|
||||
let expected_string = format!("stable since {}", version.trim());
|
||||
assert!(stderr.contains(&expected_string));
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
# ignore-cross-compile
|
||||
include ../tools.mk
|
||||
|
||||
# Test that if we build `b` against a version of `a` that has one set
|
||||
# of types, it will not run with a dylib that has a different set of
|
||||
# types.
|
||||
|
||||
# NOTE(eddyb) this test only works with the `legacy` mangling,
|
||||
# and will probably get removed once `legacy` is gone.
|
||||
|
||||
all:
|
||||
$(RUSTC) a.rs --cfg x -C prefer-dynamic -Z unstable-options -C symbol-mangling-version=legacy
|
||||
$(RUSTC) b.rs -C prefer-dynamic -Z unstable-options -C symbol-mangling-version=legacy
|
||||
$(call RUN,b)
|
||||
$(RUSTC) a.rs --cfg y -C prefer-dynamic -Z unstable-options -C symbol-mangling-version=legacy
|
||||
$(call FAIL,b)
|
45
tests/run-make/a-b-a-linker-guard/rmake.rs
Normal file
45
tests/run-make/a-b-a-linker-guard/rmake.rs
Normal file
@ -0,0 +1,45 @@
|
||||
// ignore-tidy-linelength
|
||||
|
||||
extern crate run_make_support;
|
||||
|
||||
use run_make_support::{run, run_fail, rustc};
|
||||
|
||||
fn main() {
|
||||
rustc()
|
||||
.arg("a.rs")
|
||||
.arg("--cfg")
|
||||
.arg("x")
|
||||
.arg("-C")
|
||||
.arg("prefer-dynamic")
|
||||
.arg("-Z")
|
||||
.arg("unstable-options")
|
||||
.arg("-C")
|
||||
.arg("symbol-mangling-version=legacy")
|
||||
.run();
|
||||
|
||||
rustc()
|
||||
.arg("b.rs")
|
||||
.arg("-C")
|
||||
.arg("prefer-dynamic")
|
||||
.arg("-Z")
|
||||
.arg("unstable-options")
|
||||
.arg("-C")
|
||||
.arg("symbol-mangling-version=legacy")
|
||||
.run();
|
||||
|
||||
run("b");
|
||||
|
||||
rustc()
|
||||
.arg("a.rs")
|
||||
.arg("--cfg")
|
||||
.arg("y")
|
||||
.arg("-C")
|
||||
.arg("prefer-dynamic")
|
||||
.arg("-Z")
|
||||
.arg("unstable-options")
|
||||
.arg("-C")
|
||||
.arg("symbol-mangling-version=legacy")
|
||||
.run();
|
||||
|
||||
run_fail("b");
|
||||
}
|
Loading…
Reference in New Issue
Block a user