Skip to content

Commit f00f850

Browse files
committed
Auto merge of #127760 - jieyouxu:rmake-support-reorganize, r=Kobzol
Reorganize the `run-make-support` library The `run_make_support` library has a kitchen sink `lib.rs` that make discovery/learning very difficult. Let's try to improve that by breaking up `lib.rs` into smaller more organized modules. This is a precursor to improving the documentation and learnability of the `run_make_support` library. ### Changes - Breakup `lib.rs` into smaller modules according to functionality - Rename `recursive_diff` -> `assert_dirs_are_equal` - Rename one of the `read_dir` with callback interface as `read_dir_entries` - Coalesced fs-related stuff onto a `fs` module, re-exported to tests as `rfs` - Minor doc improvements / fixes in a few places (I have a follow-up documentation PR planned) This PR is best reviewed commit-by-commit. r? `@Kobzol` (or Mark, or T-compiler or T-bootstrap) try-job: x86_64-msvc try-job: aarch64-apple try-job: test-various try-job: armhf-gnu try-job: dist-x86_64-linux
2 parents 08cdc2f + d69cc1c commit f00f850

File tree

104 files changed

+1063
-904
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

104 files changed

+1063
-904
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
//! A collection of helpers to construct artifact names, such as names of dynamic or static
2+
//! librarys which are target-dependent.
3+
4+
use crate::targets::{is_darwin, is_msvc, is_windows};
5+
6+
/// Construct the static library name based on the target.
7+
#[must_use]
8+
pub fn static_lib_name(name: &str) -> String {
9+
// See tools.mk (irrelevant lines omitted):
10+
//
11+
// ```makefile
12+
// ifeq ($(UNAME),Darwin)
13+
// STATICLIB = $(TMPDIR)/lib$(1).a
14+
// else
15+
// ifdef IS_WINDOWS
16+
// ifdef IS_MSVC
17+
// STATICLIB = $(TMPDIR)/$(1).lib
18+
// else
19+
// STATICLIB = $(TMPDIR)/lib$(1).a
20+
// endif
21+
// else
22+
// STATICLIB = $(TMPDIR)/lib$(1).a
23+
// endif
24+
// endif
25+
// ```
26+
assert!(!name.contains(char::is_whitespace), "static library name cannot contain whitespace");
27+
28+
if is_msvc() { format!("{name}.lib") } else { format!("lib{name}.a") }
29+
}
30+
31+
/// Construct the dynamic library name based on the target.
32+
#[must_use]
33+
pub fn dynamic_lib_name(name: &str) -> String {
34+
// See tools.mk (irrelevant lines omitted):
35+
//
36+
// ```makefile
37+
// ifeq ($(UNAME),Darwin)
38+
// DYLIB = $(TMPDIR)/lib$(1).dylib
39+
// else
40+
// ifdef IS_WINDOWS
41+
// DYLIB = $(TMPDIR)/$(1).dll
42+
// else
43+
// DYLIB = $(TMPDIR)/lib$(1).so
44+
// endif
45+
// endif
46+
// ```
47+
assert!(!name.contains(char::is_whitespace), "dynamic library name cannot contain whitespace");
48+
49+
let extension = dynamic_lib_extension();
50+
if is_darwin() {
51+
format!("lib{name}.{extension}")
52+
} else if is_windows() {
53+
format!("{name}.{extension}")
54+
} else {
55+
format!("lib{name}.{extension}")
56+
}
57+
}
58+
59+
/// Construct the dynamic library extension based on the target.
60+
#[must_use]
61+
pub fn dynamic_lib_extension() -> &'static str {
62+
if is_darwin() {
63+
"dylib"
64+
} else if is_windows() {
65+
"dll"
66+
} else {
67+
"so"
68+
}
69+
}
70+
71+
/// Construct the name of a rust library (rlib).
72+
#[must_use]
73+
pub fn rust_lib_name(name: &str) -> String {
74+
format!("lib{name}.rlib")
75+
}
76+
77+
/// Construct the binary (executable) name based on the target.
78+
#[must_use]
79+
pub fn bin_name(name: &str) -> String {
80+
if is_windows() { format!("{name}.exe") } else { name.to_string() }
81+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
//! Collection of assertions and assertion-related helpers.
2+
3+
use std::panic;
4+
use std::path::Path;
5+
6+
use crate::fs;
7+
8+
/// Assert that `actual` is equal to `expected`.
9+
#[track_caller]
10+
pub fn assert_equals<A: AsRef<str>, E: AsRef<str>>(actual: A, expected: E) {
11+
let actual = actual.as_ref();
12+
let expected = expected.as_ref();
13+
if actual != expected {
14+
eprintln!("=== ACTUAL TEXT ===");
15+
eprintln!("{}", actual);
16+
eprintln!("=== EXPECTED ===");
17+
eprintln!("{}", expected);
18+
panic!("expected text was not found in actual text");
19+
}
20+
}
21+
22+
/// Assert that `haystack` contains `needle`.
23+
#[track_caller]
24+
pub fn assert_contains<H: AsRef<str>, N: AsRef<str>>(haystack: H, needle: N) {
25+
let haystack = haystack.as_ref();
26+
let needle = needle.as_ref();
27+
if !haystack.contains(needle) {
28+
eprintln!("=== HAYSTACK ===");
29+
eprintln!("{}", haystack);
30+
eprintln!("=== NEEDLE ===");
31+
eprintln!("{}", needle);
32+
panic!("needle was not found in haystack");
33+
}
34+
}
35+
36+
/// Assert that `haystack` does not contain `needle`.
37+
#[track_caller]
38+
pub fn assert_not_contains<H: AsRef<str>, N: AsRef<str>>(haystack: H, needle: N) {
39+
let haystack = haystack.as_ref();
40+
let needle = needle.as_ref();
41+
if haystack.contains(needle) {
42+
eprintln!("=== HAYSTACK ===");
43+
eprintln!("{}", haystack);
44+
eprintln!("=== NEEDLE ===");
45+
eprintln!("{}", needle);
46+
panic!("needle was unexpectedly found in haystack");
47+
}
48+
}
49+
50+
/// Assert that all files in `dir1` exist and have the same content in `dir2`
51+
pub fn assert_dirs_are_equal(dir1: impl AsRef<Path>, dir2: impl AsRef<Path>) {
52+
let dir2 = dir2.as_ref();
53+
fs::read_dir_entries(dir1, |entry_path| {
54+
let entry_name = entry_path.file_name().unwrap();
55+
if entry_path.is_dir() {
56+
assert_dirs_are_equal(&entry_path, &dir2.join(entry_name));
57+
} else {
58+
let path2 = dir2.join(entry_name);
59+
let file1 = fs::read(&entry_path);
60+
let file2 = fs::read(&path2);
61+
62+
// We don't use `assert_eq!` because they are `Vec<u8>`, so not great for display.
63+
// Why not using String? Because there might be minified files or even potentially
64+
// binary ones, so that would display useless output.
65+
assert!(
66+
file1 == file2,
67+
"`{}` and `{}` have different content",
68+
entry_path.display(),
69+
path2.display(),
70+
);
71+
}
72+
});
73+
}

src/tools/run-make-support/src/command.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ use std::panic;
55
use std::path::Path;
66
use std::process::{Command as StdCommand, ExitStatus, Output, Stdio};
77

8-
use crate::{assert_contains, assert_equals, assert_not_contains, handle_failed_output};
8+
use crate::util::handle_failed_output;
9+
use crate::{assert_contains, assert_equals, assert_not_contains};
10+
911
use build_helper::drop_bomb::DropBomb;
1012

1113
/// This is a custom command wrapper that simplifies working with commands and makes it easier to

src/tools/run-make-support/src/diff/mod.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1+
use std::path::{Path, PathBuf};
2+
13
use regex::Regex;
24
use similar::TextDiff;
3-
use std::path::{Path, PathBuf};
45

5-
use crate::fs_wrapper;
66
use build_helper::drop_bomb::DropBomb;
77

8+
use crate::fs;
9+
810
#[cfg(test)]
911
mod tests;
1012

@@ -43,7 +45,7 @@ impl Diff {
4345
/// Specify the expected output for the diff from a file.
4446
pub fn expected_file<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
4547
let path = path.as_ref();
46-
let content = fs_wrapper::read_to_string(path);
48+
let content = fs::read_to_string(path);
4749
let name = path.to_string_lossy().to_string();
4850

4951
self.expected_file = Some(path.into());
@@ -62,7 +64,7 @@ impl Diff {
6264
/// Specify the actual output for the diff from a file.
6365
pub fn actual_file<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
6466
let path = path.as_ref();
65-
let content = fs_wrapper::read_to_string(path);
67+
let content = fs::read_to_string(path);
6668
let name = path.to_string_lossy().to_string();
6769

6870
self.actual = Some(content);
@@ -116,7 +118,7 @@ impl Diff {
116118
if let Some(ref expected_file) = self.expected_file {
117119
if std::env::var("RUSTC_BLESS_TEST").is_ok() {
118120
println!("Blessing `{}`", expected_file.display());
119-
fs_wrapper::write(expected_file, actual);
121+
fs::write(expected_file, actual);
120122
return;
121123
}
122124
}
@@ -138,7 +140,7 @@ impl Diff {
138140
if let Some(ref expected_file) = self.expected_file {
139141
if std::env::var("RUSTC_BLESS_TEST").is_ok() {
140142
println!("Blessing `{}`", expected_file.display());
141-
fs_wrapper::write(expected_file, actual);
143+
fs::write(expected_file, actual);
142144
return;
143145
}
144146
}

src/tools/run-make-support/src/env.rs

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
use std::ffi::OsString;
2+
3+
#[track_caller]
4+
#[must_use]
5+
pub fn env_var(name: &str) -> String {
6+
match std::env::var(name) {
7+
Ok(v) => v,
8+
Err(err) => panic!("failed to retrieve environment variable {name:?}: {err:?}"),
9+
}
10+
}
11+
12+
#[track_caller]
13+
#[must_use]
14+
pub fn env_var_os(name: &str) -> OsString {
15+
match std::env::var_os(name) {
16+
Some(v) => v,
17+
None => panic!("failed to retrieve environment variable {name:?}"),
18+
}
19+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
use std::path::PathBuf;
2+
3+
use crate::artifact_names::static_lib_name;
4+
use crate::external_deps::cc::cc;
5+
use crate::external_deps::llvm::llvm_ar;
6+
use crate::path_helpers::path;
7+
use crate::targets::is_msvc;
8+
9+
/// Builds a static lib (`.lib` on Windows MSVC and `.a` for the rest) with the given name.
10+
#[track_caller]
11+
pub fn build_native_static_lib(lib_name: &str) -> PathBuf {
12+
let obj_file = if is_msvc() { format!("{lib_name}") } else { format!("{lib_name}.o") };
13+
let src = format!("{lib_name}.c");
14+
let lib_path = static_lib_name(lib_name);
15+
if is_msvc() {
16+
cc().arg("-c").out_exe(&obj_file).input(src).run();
17+
} else {
18+
cc().arg("-v").arg("-c").out_exe(&obj_file).input(src).run();
19+
};
20+
let obj_file = if is_msvc() {
21+
PathBuf::from(format!("{lib_name}.obj"))
22+
} else {
23+
PathBuf::from(format!("{lib_name}.o"))
24+
};
25+
llvm_ar().obj_to_ar().output_input(&lib_path, &obj_file).run();
26+
path(lib_path)
27+
}

src/tools/run-make-support/src/cc.rs src/tools/run-make-support/src/external_deps/cc.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
use std::path::Path;
22

33
use crate::command::Command;
4-
use crate::{cygpath_windows, env_var, is_msvc, is_windows, uname};
4+
use crate::{env_var, is_msvc, is_windows, uname};
5+
6+
// FIXME(jieyouxu): can we get rid of the `cygpath` external dependency?
7+
use super::cygpath::get_windows_path;
58

69
/// Construct a new platform-specific C compiler invocation.
710
///
@@ -20,7 +23,7 @@ pub struct Cc {
2023
cmd: Command,
2124
}
2225

23-
crate::impl_common_helpers!(Cc);
26+
crate::macros::impl_common_helpers!(Cc);
2427

2528
impl Cc {
2629
/// Construct a new platform-specific C compiler invocation.
@@ -72,10 +75,10 @@ impl Cc {
7275

7376
if is_msvc() {
7477
path.set_extension("exe");
75-
let fe_path = cygpath_windows(&path);
78+
let fe_path = get_windows_path(&path);
7679
path.set_extension("");
7780
path.set_extension("obj");
78-
let fo_path = cygpath_windows(path);
81+
let fo_path = get_windows_path(path);
7982
self.cmd.arg(format!("-Fe:{fe_path}"));
8083
self.cmd.arg(format!("-Fo:{fo_path}"));
8184
} else {

src/tools/run-make-support/src/clang.rs src/tools/run-make-support/src/external_deps/clang.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ pub struct Clang {
1616
cmd: Command,
1717
}
1818

19-
crate::impl_common_helpers!(Clang);
19+
crate::macros::impl_common_helpers!(Clang);
2020

2121
impl Clang {
2222
/// Construct a new `clang` invocation. `clang` is not always available for all targets.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
use std::panic;
2+
use std::path::Path;
3+
4+
use crate::command::Command;
5+
use crate::util::handle_failed_output;
6+
7+
/// Use `cygpath -w` on a path to get a Windows path string back. This assumes that `cygpath` is
8+
/// available on the platform!
9+
///
10+
/// # FIXME
11+
///
12+
/// FIXME(jieyouxu): we should consider not depending on `cygpath`.
13+
///
14+
/// > The cygpath program is a utility that converts Windows native filenames to Cygwin POSIX-style
15+
/// > pathnames and vice versa.
16+
/// >
17+
/// > [irrelevant entries omitted...]
18+
/// >
19+
/// > `-w, --windows print Windows form of NAMEs (C:\WINNT)`
20+
/// >
21+
/// > -- *from [cygpath documentation](https://cygwin.com/cygwin-ug-net/cygpath.html)*.
22+
#[track_caller]
23+
#[must_use]
24+
pub fn get_windows_path<P: AsRef<Path>>(path: P) -> String {
25+
let caller = panic::Location::caller();
26+
let mut cygpath = Command::new("cygpath");
27+
cygpath.arg("-w");
28+
cygpath.arg(path.as_ref());
29+
let output = cygpath.run();
30+
if !output.status().success() {
31+
handle_failed_output(&cygpath, output, caller.line());
32+
}
33+
// cygpath -w can attach a newline
34+
output.stdout_utf8().trim().to_string()
35+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
use crate::command::Command;
2+
use crate::source_root;
3+
4+
use super::python::python_command;
5+
6+
/// `htmldocck` is a python script which is used for rustdoc test suites, it is assumed to be
7+
/// available at `$SOURCE_ROOT/src/etc/htmldocck.py`.
8+
#[track_caller]
9+
#[must_use]
10+
pub fn htmldocck() -> Command {
11+
let mut python = python_command();
12+
python.arg(source_root().join("src/etc/htmldocck.py"));
13+
python
14+
}

src/tools/run-make-support/src/llvm.rs src/tools/run-make-support/src/external_deps/llvm.rs

+7-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::path::{Path, PathBuf};
22

3-
use crate::{env_var, Command};
3+
use crate::command::Command;
4+
use crate::env::env_var;
45

56
/// Construct a new `llvm-readobj` invocation with the `GNU` output style.
67
/// This assumes that `llvm-readobj` is available at `$LLVM_BIN_DIR/llvm-readobj`.
@@ -70,11 +71,11 @@ pub struct LlvmAr {
7071
cmd: Command,
7172
}
7273

73-
crate::impl_common_helpers!(LlvmReadobj);
74-
crate::impl_common_helpers!(LlvmProfdata);
75-
crate::impl_common_helpers!(LlvmFilecheck);
76-
crate::impl_common_helpers!(LlvmObjdump);
77-
crate::impl_common_helpers!(LlvmAr);
74+
crate::macros::impl_common_helpers!(LlvmReadobj);
75+
crate::macros::impl_common_helpers!(LlvmProfdata);
76+
crate::macros::impl_common_helpers!(LlvmFilecheck);
77+
crate::macros::impl_common_helpers!(LlvmObjdump);
78+
crate::macros::impl_common_helpers!(LlvmAr);
7879

7980
/// Generate the path to the bin directory of LLVM.
8081
#[must_use]

0 commit comments

Comments
 (0)