Skip to content

Commit 53ddae6

Browse files
authored
Rollup merge of rust-lang#113026 - jieyouxu:run-make-v2, r=bjorn3
Introduce `run-make` V2 infrastructure, a `run_make_support` library and port over 2 tests as example See [issue rust-lang#40713: Switch run-make tests from Makefiles to rust](rust-lang#40713) for more context. ### Basic Description of `run-make` V2 `run-make` V2 aims to eliminate the dependency on `make` and `Makefile`s for building `run-make`-style tests. Makefiles are replaced by *recipes* (`rmake.rs`). The current implementation runs `run-make` V2 tests in 3 steps: 1. We build the support library `run_make_support` which the `rmake.rs` recipes depend on as a tool dylib. 2. We build the recipe `rmake.rs` and link in the support library. 3. We run the recipe to build and run the tests. `rmake.rs` is basically a replacement for `Makefile`, and allows running arbitrary Rust code. ### Planned Changes - [x] Get rid of the builder style patterns in `rmake_support` and instead use something like ```rust let output = rustc!(scx, "--cfg x -Cprefer-dynamic -Csymbol-mangling-version=legacy - Zunstable-options"); ``` as per Nils' suggestion. This can probably use something like `xshell`. - [x] Make `run_make_support` into a proper crate so it can have external dependencies like `xshell`. - [x] Instead of having an entire alternative directory `run-make-v2`, change how V2 tests are collected based on presence of `rmake.rs` recipe file. This should ease migration and prevent git history from being messed up by big moves. ### Disclaimer The current implementation is very much a **very very rough prototype** just to get the 2 example tests working. I would appreciate any feedback on the design and implementation.
2 parents 1280928 + c2a0d11 commit 53ddae6

File tree

12 files changed

+503
-32
lines changed

12 files changed

+503
-32
lines changed

Cargo.lock

+13
Original file line numberDiff line numberDiff line change
@@ -3258,6 +3258,13 @@ dependencies = [
32583258
"serde_json",
32593259
]
32603260

3261+
[[package]]
3262+
name = "run_make_support"
3263+
version = "0.0.0"
3264+
dependencies = [
3265+
"shell-words",
3266+
]
3267+
32613268
[[package]]
32623269
name = "rust-demangler"
32633270
version = "0.0.1"
@@ -4968,6 +4975,12 @@ version = "0.1.5"
49684975
source = "registry+https://github.com/rust-lang/crates.io-index"
49694976
checksum = "45bb67a18fa91266cc7807181f62f9178a6873bfad7dc788c42e6430db40184f"
49704977

4978+
[[package]]
4979+
name = "shell-words"
4980+
version = "1.1.0"
4981+
source = "registry+https://github.com/rust-lang/crates.io-index"
4982+
checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde"
4983+
49714984
[[package]]
49724985
name = "shlex"
49734986
version = "1.1.0"

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ members = [
1010
"src/tools/clippy",
1111
"src/tools/clippy/clippy_dev",
1212
"src/tools/compiletest",
13+
"src/tools/run-make-support",
1314
"src/tools/error_index_generator",
1415
"src/tools/linkchecker",
1516
"src/tools/lint-docs",

src/bootstrap/src/core/build_steps/test.rs

+82-1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ use crate::core::config::flags::get_completion;
2626
use crate::core::config::flags::Subcommand;
2727
use crate::core::config::TargetSelection;
2828
use crate::utils::cache::{Interned, INTERNER};
29+
use crate::utils::dylib::shared_lib_name;
2930
use crate::utils::exec::BootstrapCommand;
3031
use crate::utils::helpers::{
3132
self, add_link_lib_path, add_rustdoc_cargo_linker_args, dylib_path, dylib_path_var,
@@ -1326,6 +1327,53 @@ macro_rules! coverage_test_alias {
13261327
};
13271328
}
13281329

1330+
#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq, Ord, PartialOrd)]
1331+
pub struct RunMakeSupport {
1332+
pub compiler: Compiler,
1333+
pub target: TargetSelection,
1334+
}
1335+
1336+
impl Step for RunMakeSupport {
1337+
type Output = PathBuf;
1338+
const DEFAULT: bool = true;
1339+
1340+
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1341+
run.never()
1342+
}
1343+
1344+
fn make_run(run: RunConfig<'_>) {
1345+
let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1346+
run.builder.ensure(RunMakeSupport { compiler, target: run.target });
1347+
}
1348+
1349+
fn run(self, builder: &Builder<'_>) -> PathBuf {
1350+
builder.ensure(compile::Std::new(self.compiler, self.target));
1351+
1352+
let cargo = tool::prepare_tool_cargo(
1353+
builder,
1354+
self.compiler,
1355+
Mode::ToolStd,
1356+
self.target,
1357+
"build",
1358+
"src/tools/run-make-support",
1359+
SourceType::InTree,
1360+
&[],
1361+
);
1362+
1363+
let mut cargo = Command::from(cargo);
1364+
cargo.env("RUSTFLAGS", "-C prefer-dynamic");
1365+
builder.run(&mut cargo);
1366+
1367+
let lib_name = shared_lib_name("run_make_support", &self.target.to_string());
1368+
let lib = builder.tools_dir(self.compiler).join(&lib_name);
1369+
1370+
let cargo_out =
1371+
builder.cargo_out(self.compiler, Mode::ToolStd, self.target).join(&lib_name);
1372+
builder.copy(&cargo_out, &lib);
1373+
lib
1374+
}
1375+
}
1376+
13291377
default_test!(Ui { path: "tests/ui", mode: "ui", suite: "ui" });
13301378

13311379
default_test!(RunPassValgrind {
@@ -1360,7 +1408,40 @@ host_test!(RustdocJson { path: "tests/rustdoc-json", mode: "rustdoc-json", suite
13601408

13611409
host_test!(Pretty { path: "tests/pretty", mode: "pretty", suite: "pretty" });
13621410

1363-
default_test!(RunMake { path: "tests/run-make", mode: "run-make", suite: "run-make" });
1411+
// Special-handling is needed for `run-make`, so don't use `default_test` for defining `RunMake`
1412+
// tests.
1413+
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
1414+
pub struct RunMake {
1415+
pub compiler: Compiler,
1416+
pub target: TargetSelection,
1417+
}
1418+
1419+
impl Step for RunMake {
1420+
type Output = ();
1421+
const DEFAULT: bool = true;
1422+
const ONLY_HOSTS: bool = false;
1423+
1424+
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
1425+
run.suite_path("tests/run-make")
1426+
}
1427+
1428+
fn make_run(run: RunConfig<'_>) {
1429+
let compiler = run.builder.compiler(run.builder.top_stage, run.build_triple());
1430+
run.builder.ensure(RunMakeSupport { compiler, target: run.target });
1431+
run.builder.ensure(RunMake { compiler, target: run.target });
1432+
}
1433+
1434+
fn run(self, builder: &Builder<'_>) {
1435+
builder.ensure(Compiletest {
1436+
compiler: self.compiler,
1437+
target: self.target,
1438+
mode: "run-make",
1439+
suite: "run-make",
1440+
path: "tests/run-make",
1441+
compare_mode: None,
1442+
});
1443+
}
1444+
}
13641445

13651446
host_test!(RunMakeFullDeps {
13661447
path: "tests/run-make-fulldeps",

src/bootstrap/src/utils/dylib.rs

+13
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,16 @@ pub fn exe(name: &str, target: &str) -> String {
3838
name.to_string()
3939
}
4040
}
41+
42+
/// Given a shared library called `name`, return the filename for the
43+
/// shared library for a particular target.
44+
#[allow(dead_code)]
45+
pub fn shared_lib_name(name: &str, target: &str) -> String {
46+
if target.contains("windows") {
47+
format!("lib{name}.dll")
48+
} else if target.contains("apple") {
49+
format!("lib{name}.dylib")
50+
} else {
51+
format!("lib{name}.so")
52+
}
53+
}

src/tools/compiletest/src/lib.rs

+26-9
Original file line numberDiff line numberDiff line change
@@ -655,13 +655,21 @@ fn collect_tests_from_dir(
655655
return Ok(());
656656
}
657657

658-
if config.mode == Mode::RunMake && dir.join("Makefile").exists() {
659-
let paths = TestPaths {
660-
file: dir.to_path_buf(),
661-
relative_dir: relative_dir_path.parent().unwrap().to_path_buf(),
662-
};
663-
tests.extend(make_test(config, cache, &paths, inputs, poisoned));
664-
return Ok(());
658+
if config.mode == Mode::RunMake {
659+
if dir.join("Makefile").exists() && dir.join("rmake.rs").exists() {
660+
return Err(io::Error::other(
661+
"run-make tests cannot have both `Makefile` and `rmake.rs`",
662+
));
663+
}
664+
665+
if dir.join("Makefile").exists() || dir.join("rmake.rs").exists() {
666+
let paths = TestPaths {
667+
file: dir.to_path_buf(),
668+
relative_dir: relative_dir_path.parent().unwrap().to_path_buf(),
669+
};
670+
tests.extend(make_test(config, cache, &paths, inputs, poisoned));
671+
return Ok(());
672+
}
665673
}
666674

667675
// If we find a test foo/bar.rs, we have to build the
@@ -731,8 +739,17 @@ fn make_test(
731739
poisoned: &mut bool,
732740
) -> Vec<test::TestDescAndFn> {
733741
let test_path = if config.mode == Mode::RunMake {
734-
// Parse directives in the Makefile
735-
testpaths.file.join("Makefile")
742+
if testpaths.file.join("rmake.rs").exists() && testpaths.file.join("Makefile").exists() {
743+
panic!("run-make tests cannot have both `rmake.rs` and `Makefile`");
744+
}
745+
746+
if testpaths.file.join("rmake.rs").exists() {
747+
// Parse directives in rmake.rs.
748+
testpaths.file.join("rmake.rs")
749+
} else {
750+
// Parse directives in the Makefile.
751+
testpaths.file.join("Makefile")
752+
}
736753
} else {
737754
PathBuf::from(&testpaths.file)
738755
};

0 commit comments

Comments
 (0)