Skip to content

Cleanup rmake.rs setup in compiletest #127958

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 16 commits into from
Jul 21, 2024
Merged
Changes from 2 commits
Commits
Show all changes
16 commits
Select commit Hold shift + click to select a range
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
93 changes: 71 additions & 22 deletions src/tools/compiletest/src/runtest.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3433,29 +3433,64 @@ impl<'test> TestCx<'test> {

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`.
// (`rmake.rs`) to run the actual tests. The support library is already built as a tool rust
// library 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);
// 1. We need to build the recipe `rmake.rs` as a binary and link in the `run_make_support`
// library.
// 2. We need to run the recipe binary.

// FIXME(jieyouxu): path examples
// source_root="/home/gh-jieyouxu/rust"
// src_root="/home/gh-jieyouxu/rust"
// build_root="/home/gh-jieyouxu/rust/build/aarch64-unknown-linux-gnu"
// self.config.build_base="/home/gh-jieyouxu/rust/build/aarch64-unknown-linux-gnu/test/run-make"
// support_lib_deps="/home/gh-jieyouxu/rust/build/aarch64-unknown-linux-gnu/stage1-tools/aarch64-unknown-linux-gnu/release/deps"
// support_lib_deps_deps="/home/gh-jieyouxu/rust/build/aarch64-unknown-linux-gnu/stage1-tools/release/deps"
// recipe_bin="/home/gh-jieyouxu/rust/build/aarch64-unknown-linux-gnu/test/run-make/a-b-a-linker-guard/a-b-a-linker-guard/rmake"

// So we assume the rust-lang/rust project setup looks like (our `.` is the top-level
// directory, irrelevant entries to our purposes omitted):
//
// ```
// . // <- `source_root`
// ├── build/ // <- `build_root`
// ├── compiler/
// ├── library/
// ├── src/
// │ └── tools/
// │ └── run_make_support/
// └── tests
// └── run-make/
// ```

// `source_root` is the top-level directory containing the rust-lang/rust checkout.
let source_root =
self.config.find_rust_src_root().expect("could not determine rust source root");
debug!(?source_root);
// `self.config.build_base` is actually the build base folder + "test" + test suite name, it
// looks like `build/<host_tuplet>/test/run-make`. But we want `build/<host_tuplet>/`. Note
// that the `build` directory does not need to be called `build`, nor does it need to be
// under `source_root`, so we must compute it based off of `self.config.build_base`.
debug!(?self.config.build_base);
let build_root =
self.config.build_base.parent().and_then(Path::parent).unwrap().to_path_buf();
debug!(?build_root);

// We construct the following directory tree for each rmake.rs test:
// ```
// base_dir/
// rmake.exe
// rmake_out/
// ```
// having the executable separate from the output artifacts directory allows the recipes to
// `remove_dir_all($TMPDIR)` without running into permission denied issues because
// the executable is not under the `rmake_out/` directory.
// having the recipe executable separate from the output artifacts directory allows the
// recipes to `remove_dir_all($TMPDIR)` without running into issues related trying to remove
// a currently running executable because the recipe executable is not under the
// `rmake_out/` directory.
//
// This setup intentionally diverges from legacy Makefile run-make tests.
let base_dir = cwd.join(self.output_base_name());
// FIXME(jieyouxu): is there a better way to compute `base_dir`?
let base_dir = self.output_base_name();
if base_dir.exists() {
self.aggressive_rm_rf(&base_dir).unwrap();
}
Expand All @@ -3477,10 +3512,13 @@ impl<'test> TestCx<'test> {
}
}

// FIXME(jieyouxu): is there a better way to get the stage number or otherwise compute the
// required stage-specific build directories?
// 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.
// FIXME(jieyouxu): explain what the hecc we are doing here.
let mut support_lib_path = PathBuf::new();
support_lib_path.push(&build_root);
support_lib_path.push(format!("{}-tools-bin", stage));
Expand All @@ -3492,19 +3530,22 @@ impl<'test> TestCx<'test> {
stage_std_path.push("lib");

// Then, we need to build the recipe `rmake.rs` and link in the support library.
// FIXME(jieyouxu): use `std::env::consts::EXE_EXTENSION`.
let recipe_bin = base_dir.join(if self.config.target.contains("windows") {
"rmake.exe"
} else {
"rmake"
});

// FIXME(jieyouxu): explain what the hecc we are doing here.
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");

// FIXME(jieyouxu): explain what the hecc we are doing here.
let mut support_lib_deps_deps = PathBuf::new();
support_lib_deps_deps.push(&build_root);
support_lib_deps_deps.push(format!("{}-tools", stage));
Expand All @@ -3514,14 +3555,17 @@ impl<'test> TestCx<'test> {
debug!(?support_lib_deps);
debug!(?support_lib_deps_deps);

// FIXME(jieyouxu): explain what the hecc we are doing here.
let orig_dylib_env_paths =
Vec::from_iter(env::split_paths(&env::var(dylib_env_var()).unwrap()));

let mut host_dylib_env_paths = Vec::new();
host_dylib_env_paths.push(cwd.join(&self.config.compile_lib_path));
host_dylib_env_paths.push(self.config.compile_lib_path.clone());
host_dylib_env_paths.extend(orig_dylib_env_paths.iter().cloned());
let host_dylib_env_paths = env::join_paths(host_dylib_env_paths).unwrap();

// FIXME(jieyouxu): explain what the hecc we are doing here.
// FIXME(jieyouxu): audit these env vars. some of them only makes sense for make, not rustc!
let mut cmd = Command::new(&self.config.rustc_path);
cmd.arg("-o")
.arg(&recipe_bin)
Expand All @@ -3535,17 +3579,18 @@ impl<'test> TestCx<'test> {
.env("TARGET", &self.config.target)
.env("PYTHON", &self.config.python)
.env("RUST_BUILD_STAGE", &self.config.stage_id)
.env("RUSTC", cwd.join(&self.config.rustc_path))
.env("RUSTC", &self.config.rustc_path)
.env("LD_LIB_PATH_ENVVAR", dylib_env_var())
.env(dylib_env_var(), &host_dylib_env_paths)
.env("HOST_RPATH_DIR", cwd.join(&self.config.compile_lib_path))
.env("TARGET_RPATH_DIR", cwd.join(&self.config.run_lib_path))
.env("HOST_RPATH_DIR", &self.config.compile_lib_path)
.env("TARGET_RPATH_DIR", &self.config.run_lib_path)
.env("LLVM_COMPONENTS", &self.config.llvm_components);

// In test code we want to be very pedantic about values being silently discarded that are
// annotated with `#[must_use]`.
cmd.arg("-Dunused_must_use");

// FIXME(jieyouxu): explain this!
if std::env::var_os("COMPILETEST_FORCE_STAGE0").is_some() {
let mut stage0_sysroot = build_root.clone();
stage0_sysroot.push("stage0-sysroot");
Expand All @@ -3563,16 +3608,20 @@ impl<'test> TestCx<'test> {
// Finally, we need to run the recipe binary to build and run the actual tests.
debug!(?recipe_bin);

// FIXME(jieyouxu): explain what the hecc we are doing here.
let mut dylib_env_paths = orig_dylib_env_paths.clone();
dylib_env_paths.push(support_lib_path.parent().unwrap().to_path_buf());
dylib_env_paths.push(stage_std_path.join("rustlib").join(&self.config.host).join("lib"));
let dylib_env_paths = env::join_paths(dylib_env_paths).unwrap();

// FIXME(jieyouxu): explain what the hecc we are doing here.
let mut target_rpath_env_path = Vec::new();
target_rpath_env_path.push(&rmake_out_dir);
target_rpath_env_path.extend(&orig_dylib_env_paths);
let target_rpath_env_path = env::join_paths(target_rpath_env_path).unwrap();

// FIXME(jieyouxu): explain what the hecc we are doing here.
// FIXME(jieyouxu): audit these env vars. some of them only makes sense for make, not rustc!
let mut cmd = Command::new(&recipe_bin);
cmd.current_dir(&rmake_out_dir)
.stdout(Stdio::piped())
Expand All @@ -3582,15 +3631,15 @@ impl<'test> TestCx<'test> {
.env(dylib_env_var(), &dylib_env_paths)
.env("TARGET", &self.config.target)
.env("PYTHON", &self.config.python)
.env("SOURCE_ROOT", &src_root)
.env("SOURCE_ROOT", &source_root)
.env("RUST_BUILD_STAGE", &self.config.stage_id)
.env("RUSTC", cwd.join(&self.config.rustc_path))
.env("HOST_RPATH_DIR", cwd.join(&self.config.compile_lib_path))
.env("TARGET_RPATH_DIR", cwd.join(&self.config.run_lib_path))
.env("RUSTC", &self.config.rustc_path)
.env("HOST_RPATH_DIR", &self.config.compile_lib_path)
.env("TARGET_RPATH_DIR", &self.config.run_lib_path)
.env("LLVM_COMPONENTS", &self.config.llvm_components);

if let Some(ref rustdoc) = self.config.rustdoc_path {
cmd.env("RUSTDOC", cwd.join(rustdoc));
cmd.env("RUSTDOC", source_root.join(rustdoc));
}

if let Some(ref node) = self.config.nodejs {
Expand Down