Skip to content

Rollup of 5 pull requests #129129

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

Closed
wants to merge 12 commits into from
Closed
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
4 changes: 1 addition & 3 deletions src/bootstrap/src/core/download.rs
Original file line number Diff line number Diff line change
@@ -703,9 +703,7 @@ download-rustc = false
let file_times = fs::FileTimes::new().set_accessed(now).set_modified(now);

let llvm_config = llvm_root.join("bin").join(exe("llvm-config", self.build));
let llvm_config_file = t!(File::options().write(true).open(llvm_config));

t!(llvm_config_file.set_times(file_times));
t!(crate::utils::helpers::set_file_times(llvm_config, file_times));

if self.should_fix_bins_and_dylibs() {
let llvm_lib = llvm_root.join("lib");
15 changes: 8 additions & 7 deletions src/bootstrap/src/lib.rs
Original file line number Diff line number Diff line change
@@ -37,7 +37,9 @@ use crate::core::builder;
use crate::core::builder::{Builder, Kind};
use crate::core::config::{flags, DryRun, LldMode, LlvmLibunwind, Target, TargetSelection};
use crate::utils::exec::{command, BehaviorOnFailure, BootstrapCommand, CommandOutput, OutputMode};
use crate::utils::helpers::{self, dir_is_empty, exe, libdir, mtime, output, symlink_dir};
use crate::utils::helpers::{
self, dir_is_empty, exe, libdir, mtime, output, set_file_times, symlink_dir,
};

mod core;
mod utils;
@@ -1774,21 +1776,20 @@ Executed at: {executed_at}"#,
}
}
if let Ok(()) = fs::hard_link(&src, dst) {
// Attempt to "easy copy" by creating a hard link
// (symlinks don't work on windows), but if that fails
// just fall back to a slow `copy` operation.
// Attempt to "easy copy" by creating a hard link (symlinks are priviledged on windows),
// but if that fails just fall back to a slow `copy` operation.
} else {
if let Err(e) = fs::copy(&src, dst) {
panic!("failed to copy `{}` to `{}`: {}", src.display(), dst.display(), e)
}
t!(fs::set_permissions(dst, metadata.permissions()));

// Restore file times because changing permissions on e.g. Linux using `chmod` can cause
// file access time to change.
let file_times = fs::FileTimes::new()
.set_accessed(t!(metadata.accessed()))
.set_modified(t!(metadata.modified()));

let dst_file = t!(fs::File::open(dst));
t!(dst_file.set_times(file_times));
t!(set_file_times(dst, file_times));
}
}

12 changes: 12 additions & 0 deletions src/bootstrap/src/utils/helpers.rs
Original file line number Diff line number Diff line change
@@ -544,3 +544,15 @@ pub fn get_closest_merge_base_commit(

Ok(output_result(git.as_command_mut())?.trim().to_owned())
}

/// Sets the file times for a given file at `path`.
pub fn set_file_times<P: AsRef<Path>>(path: P, times: fs::FileTimes) -> io::Result<()> {
// Windows requires file to be writable to modify file times. But on Linux CI the file does not
// need to be writable to modify file times and might be read-only.
let f = if cfg!(windows) {
fs::File::options().write(true).open(path)?
} else {
fs::File::open(path)?
};
f.set_times(times)
}
24 changes: 23 additions & 1 deletion src/bootstrap/src/utils/helpers/tests.rs
Original file line number Diff line number Diff line change
@@ -3,7 +3,8 @@ use std::io::Write;
use std::path::PathBuf;

use crate::utils::helpers::{
check_cfg_arg, extract_beta_rev, hex_encode, make, program_out_of_date, symlink_dir,
check_cfg_arg, extract_beta_rev, hex_encode, make, program_out_of_date, set_file_times,
symlink_dir,
};
use crate::{Config, Flags};

@@ -92,3 +93,24 @@ fn test_symlink_dir() {
#[cfg(not(windows))]
fs::remove_file(link_path).unwrap();
}

#[test]
fn test_set_file_times_sanity_check() {
let config = Config::parse(&["check".to_owned(), "--config=/does/not/exist".to_owned()]);
let tempfile = config.tempdir().join(".tmp-file");

{
File::create(&tempfile).unwrap().write_all(b"dummy value").unwrap();
assert!(tempfile.exists());
}

// This might only fail on Windows (if file is default read-only then we try to modify file
// times).
let unix_epoch = std::time::SystemTime::UNIX_EPOCH;
let target_time = fs::FileTimes::new().set_accessed(unix_epoch).set_modified(unix_epoch);
set_file_times(&tempfile, target_time).unwrap();

let found_metadata = fs::metadata(tempfile).unwrap();
assert_eq!(found_metadata.accessed().unwrap(), unix_epoch);
assert_eq!(found_metadata.modified().unwrap(), unix_epoch)
}
6 changes: 6 additions & 0 deletions src/tools/run-make-support/src/external_deps/llvm.rs
Original file line number Diff line number Diff line change
@@ -297,6 +297,12 @@ impl LlvmAr {
self
}

/// Print the table of contents.
pub fn table_of_contents(&mut self) -> &mut Self {
self.cmd.arg("t");
self
}

/// Provide an output, then an input file. Bundled in one function, as llvm-ar has
/// no "--output"-style flag.
pub fn output_input(&mut self, out: impl AsRef<Path>, input: impl AsRef<Path>) -> &mut Self {
7 changes: 0 additions & 7 deletions src/tools/tidy/src/allowed_run_make_makefiles.txt
Original file line number Diff line number Diff line change
@@ -1,21 +1,14 @@
run-make/branch-protection-check-IBT/Makefile
run-make/cat-and-grep-sanity-check/Makefile
run-make/dep-info-doesnt-run-much/Makefile
run-make/dep-info-spaces/Makefile
run-make/dep-info/Makefile
run-make/emit-to-stdout/Makefile
run-make/extern-fn-reachable/Makefile
run-make/incr-add-rust-src-component/Makefile
run-make/issue-84395-lto-embed-bitcode/Makefile
run-make/jobserver-error/Makefile
run-make/libs-through-symlinks/Makefile
run-make/libtest-json/Makefile
run-make/libtest-junit/Makefile
run-make/libtest-thread-limit/Makefile
run-make/macos-deployment-target/Makefile
run-make/native-link-modifier-bundle/Makefile
run-make/reproducible-build/Makefile
run-make/rlib-format-packed-bundled-libs/Makefile
run-make/split-debuginfo/Makefile
run-make/symbol-mangling-hashed/Makefile
run-make/translation/Makefile
4 changes: 0 additions & 4 deletions tests/run-make/dep-info-doesnt-run-much/Makefile

This file was deleted.

19 changes: 0 additions & 19 deletions tests/run-make/dep-info-spaces/Makefile

This file was deleted.

7 changes: 0 additions & 7 deletions tests/run-make/dep-info-spaces/Makefile.foo

This file was deleted.

1 change: 0 additions & 1 deletion tests/run-make/dep-info-spaces/bar.rs

This file was deleted.

25 changes: 0 additions & 25 deletions tests/run-make/dep-info/Makefile

This file was deleted.

7 changes: 0 additions & 7 deletions tests/run-make/dep-info/Makefile.foo

This file was deleted.

File renamed without changes.
File renamed without changes.
File renamed without changes.
37 changes: 37 additions & 0 deletions tests/run-make/dep-info/rmake.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// This is a simple smoke test for rustc's `--emit dep-info` feature. It prints out
// information about dependencies in a Makefile-compatible format, as a `.d` file.
// Note that this test does not check that the `.d` file is Makefile-compatible.

// This test first checks that emitting dep-info disables static analysis, preventing
// compilation of `erroneous.rs` from causing a compilation failure.
// Then, it checks that compilation using the flag is successful in general, even with
// empty source files or source files that contain a whitespace character.

// Finally, it removes one dependency and checks that compilation is still successful.
// See https://github.com/rust-lang/rust/pull/10698

use run_make_support::{rfs, rustc};

fn main() {
// We're only emitting dep info, so we shouldn't be running static analysis to
// figure out that this program is erroneous.
rustc().input("erroneous.rs").emit("dep-info").run();

rustc().input("lib.rs").emit("dep-info,link").crate_type("lib").run();
rfs::remove_file("foo.rs");
rfs::create_file("foo.rs");
// Compilation should succeed even if `foo.rs` is empty.
rustc().input("lib.rs").emit("dep-info,link").crate_type("lib").run();

// Again, with a space in the filename this time around.
rustc().input("lib_foofoo.rs").emit("dep-info,link").crate_type("lib").run();
rfs::remove_file("foo foo.rs");
rfs::create_file("foo foo.rs");
// Compilation should succeed even if `foo foo.rs` is empty.
rustc().input("lib_foofoo.rs").emit("dep-info,link").crate_type("lib").run();

// When a source file is deleted, compilation should still succeed if the library
// also loses this source file dependency.
rfs::remove_file("bar.rs");
rustc().input("lib2.rs").emit("dep-info,link").crate_type("lib").run();
}
20 changes: 0 additions & 20 deletions tests/run-make/libtest-json/Makefile

This file was deleted.

2 changes: 1 addition & 1 deletion tests/run-make/libtest-json/output-default.json
Original file line number Diff line number Diff line change
@@ -7,4 +7,4 @@
{ "type": "test", "name": "c", "event": "ok" }
{ "type": "test", "event": "started", "name": "d" }
{ "type": "test", "name": "d", "event": "ignored", "message": "msg" }
{ "type": "suite", "event": "failed", "passed": 2, "failed": 1, "ignored": 1, "measured": 0, "filtered_out": 0, "exec_time": $TIME }
{ "type": "suite", "event": "failed", "passed": 2, "failed": 1, "ignored": 1, "measured": 0, "filtered_out": 0, "exec_time": "$EXEC_TIME" }
2 changes: 1 addition & 1 deletion tests/run-make/libtest-json/output-stdout-success.json
Original file line number Diff line number Diff line change
@@ -7,4 +7,4 @@
{ "type": "test", "name": "c", "event": "ok", "stdout": "thread 'c' panicked at f.rs:15:5:\nassertion failed: false\n" }
{ "type": "test", "event": "started", "name": "d" }
{ "type": "test", "name": "d", "event": "ignored", "message": "msg" }
{ "type": "suite", "event": "failed", "passed": 2, "failed": 1, "ignored": 1, "measured": 0, "filtered_out": 0, "exec_time": $TIME }
{ "type": "suite", "event": "failed", "passed": 2, "failed": 1, "ignored": 1, "measured": 0, "filtered_out": 0, "exec_time": "$EXEC_TIME" }
31 changes: 31 additions & 0 deletions tests/run-make/libtest-json/rmake.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Check libtest's JSON output against snapshots.

//@ ignore-cross-compile
//@ needs-unwind (test file contains #[should_panic] test)

use run_make_support::{cmd, diff, python_command, rustc};

fn main() {
rustc().arg("--test").input("f.rs").run();

run_tests(&[], "output-default.json");
run_tests(&["--show-output"], "output-stdout-success.json");
}

#[track_caller]
fn run_tests(extra_args: &[&str], expected_file: &str) {
let cmd_out = cmd("./f")
.env("RUST_BACKTRACE", "0")
.args(&["-Zunstable-options", "--test-threads=1", "--format=json"])
.args(extra_args)
.run_fail();
let test_stdout = &cmd_out.stdout_utf8();

python_command().arg("validate_json.py").stdin(test_stdout).run();

diff()
.expected_file(expected_file)
.actual_text("stdout", test_stdout)
.normalize(r#"(?<prefix>"exec_time": )[0-9.]+"#, r#"${prefix}"$$EXEC_TIME""#)
.run();
}
20 changes: 0 additions & 20 deletions tests/run-make/libtest-junit/Makefile

This file was deleted.

31 changes: 31 additions & 0 deletions tests/run-make/libtest-junit/rmake.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Check libtest's JUnit (XML) output against snapshots.

//@ ignore-cross-compile
//@ needs-unwind (test file contains #[should_panic] test)

use run_make_support::{cmd, diff, python_command, rustc};

fn main() {
rustc().arg("--test").input("f.rs").run();

run_tests(&[], "output-default.xml");
run_tests(&["--show-output"], "output-stdout-success.xml");
}

#[track_caller]
fn run_tests(extra_args: &[&str], expected_file: &str) {
let cmd_out = cmd("./f")
.env("RUST_BACKTRACE", "0")
.args(&["-Zunstable-options", "--test-threads=1", "--format=junit"])
.args(extra_args)
.run_fail();
let test_stdout = &cmd_out.stdout_utf8();

python_command().arg("validate_junit.py").stdin(test_stdout).run();

diff()
.expected_file(expected_file)
.actual_text("stdout", test_stdout)
.normalize(r#"\btime="[0-9.]+""#, r#"time="$$TIME""#)
.run();
}
38 changes: 0 additions & 38 deletions tests/run-make/native-link-modifier-bundle/Makefile

This file was deleted.

90 changes: 90 additions & 0 deletions tests/run-make/native-link-modifier-bundle/rmake.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
// This test exercises the `bundle` link argument, which can be turned on or off.

// When building a rlib or staticlib, +bundle means that all object files from the native static
// library will be added to the rlib or staticlib archive, and then used from it during linking of
// the final binary.

// When building a rlib -bundle means that the native static library is registered as a dependency
// of that rlib "by name", and object files from it are included only during linking of the final
// binary, the file search by that name is also performed during final linking.
// When building a staticlib -bundle means that the native static library is simply not included
// into the archive and some higher level build system will need to add it later during linking of
// the final binary.

// This modifier has no effect when building other targets like executables or dynamic libraries.

// The default for this modifier is +bundle.
// See https://github.com/rust-lang/rust/pull/95818

//@ ignore-cross-compile
// Reason: cross-compilation fails to export native symbols

use run_make_support::{
build_native_static_lib, dynamic_lib_name, is_msvc, llvm_nm, rust_lib_name, rustc,
static_lib_name,
};

fn main() {
build_native_static_lib("native-staticlib");
// Build a staticlib and a rlib, the `native_func` symbol will be bundled into them
rustc().input("bundled.rs").crate_type("staticlib").crate_type("rlib").run();
llvm_nm()
.input(static_lib_name("bundled"))
.run()
.assert_stdout_contains_regex("T _*native_func");
llvm_nm()
.input(static_lib_name("bundled"))
.run()
.assert_stdout_contains_regex("U _*native_func");
llvm_nm().input(rust_lib_name("bundled")).run().assert_stdout_contains_regex("T _*native_func");
llvm_nm().input(rust_lib_name("bundled")).run().assert_stdout_contains_regex("U _*native_func");

// Build a staticlib and a rlib, the `native_func` symbol will not be bundled into it
build_native_static_lib("native-staticlib");
rustc().input("non-bundled.rs").crate_type("staticlib").crate_type("rlib").run();
llvm_nm()
.input(static_lib_name("non_bundled"))
.run()
.assert_stdout_not_contains_regex("T _*native_func");
llvm_nm()
.input(static_lib_name("non_bundled"))
.run()
.assert_stdout_contains_regex("U _*native_func");
llvm_nm()
.input(rust_lib_name("non_bundled"))
.run()
.assert_stdout_not_contains_regex("T _*native_func");
llvm_nm()
.input(rust_lib_name("non_bundled"))
.run()
.assert_stdout_contains_regex("U _*native_func");

// This part of the test does not function on Windows MSVC - no symbols are printed.
if !is_msvc() {
// Build a cdylib, `native-staticlib` will not appear on the linker line because it was
// bundled previously. The cdylib will contain the `native_func` symbol in the end.
rustc()
.input("cdylib-bundled.rs")
.crate_type("cdylib")
.print("link-args")
.run()
.assert_stdout_not_contains(r#"-l[" ]*native-staticlib"#);
llvm_nm()
.input(dynamic_lib_name("cdylib_bundled"))
.run()
.assert_stdout_contains_regex("[Tt] _*native_func");

// Build a cdylib, `native-staticlib` will appear on the linker line because it was not
// bundled previously. The cdylib will contain the `native_func` symbol in the end
rustc()
.input("cdylib-non-bundled.rs")
.crate_type("cdylib")
.print("link-args")
.run()
.assert_stdout_contains_regex(r#"-l[" ]*native-staticlib"#);
llvm_nm()
.input(dynamic_lib_name("cdylib_non_bundled"))
.run()
.assert_stdout_contains_regex("[Tt] _*native_func");
}
}
39 changes: 0 additions & 39 deletions tests/run-make/rlib-format-packed-bundled-libs/Makefile

This file was deleted.

84 changes: 84 additions & 0 deletions tests/run-make/rlib-format-packed-bundled-libs/rmake.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// `-Z packed_bundled_libs` is an unstable rustc flag that makes the compiler
// only require a native library and no supplementary object files to compile.
// Output files compiled with this flag should still contain all expected symbols -
// that is what this test checks.
// See https://github.com/rust-lang/rust/pull/100101

//@ ignore-cross-compile
// Reason: cross-compilation fails to export native symbols

use run_make_support::{
bin_name, build_native_static_lib, cwd, filename_contains, is_msvc, llvm_ar, llvm_nm, rfs,
rust_lib_name, rustc, shallow_find_files,
};

fn main() {
build_native_static_lib("native_dep_1");
build_native_static_lib("native_dep_2");
build_native_static_lib("native_dep_3");
rustc().input("rust_dep_up.rs").crate_type("rlib").arg("-Zpacked_bundled_libs").run();
llvm_nm()
.input(rust_lib_name("rust_dep_up"))
.run()
.assert_stdout_contains_regex("U.*native_f2");
llvm_nm()
.input(rust_lib_name("rust_dep_up"))
.run()
.assert_stdout_contains_regex("U.*native_f3");
llvm_nm()
.input(rust_lib_name("rust_dep_up"))
.run()
.assert_stdout_contains_regex("T.*rust_dep_up");
llvm_ar()
.table_of_contents()
.arg(rust_lib_name("rust_dep_up"))
.run()
.assert_stdout_contains("native_dep_2");
llvm_ar()
.table_of_contents()
.arg(rust_lib_name("rust_dep_up"))
.run()
.assert_stdout_contains("native_dep_3");
rustc()
.input("rust_dep_local.rs")
.extern_("rlib", rust_lib_name("rust_dep_up"))
.arg("-Zpacked_bundled_libs")
.crate_type("rlib")
.run();
llvm_nm()
.input(rust_lib_name("rust_dep_local"))
.run()
.assert_stdout_contains_regex("U.*native_f1");
llvm_nm()
.input(rust_lib_name("rust_dep_local"))
.run()
.assert_stdout_contains_regex("T.*rust_dep_local");
llvm_ar()
.table_of_contents()
.arg(rust_lib_name("rust_dep_local"))
.run()
.assert_stdout_contains("native_dep_1");

// Ensure the compiler will not use files it should not know about.
for file in shallow_find_files(cwd(), |path| filename_contains(path, "native_dep_")) {
rfs::remove_file(file);
}

rustc()
.input("main.rs")
.extern_("lib", rust_lib_name("rust_dep_local"))
.output(bin_name("main"))
.arg("-Zpacked_bundled_libs")
.print("link-args")
.run()
.assert_stdout_contains_regex("native_dep_1.*native_dep_2.*native_dep_3");

// The binary "main" will not contain any symbols on MSVC.
if !is_msvc() {
llvm_nm().input(bin_name("main")).run().assert_stdout_contains_regex("T.*native_f1");
llvm_nm().input(bin_name("main")).run().assert_stdout_contains_regex("T.*native_f2");
llvm_nm().input(bin_name("main")).run().assert_stdout_contains_regex("T.*native_f3");
llvm_nm().input(bin_name("main")).run().assert_stdout_contains_regex("T.*rust_dep_local");
llvm_nm().input(bin_name("main")).run().assert_stdout_contains_regex("T.*rust_dep_up");
}
}
101 changes: 99 additions & 2 deletions tests/run-make/sysroot-crates-are-unstable/rmake.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,102 @@
use run_make_support::python_command;
// Check that crates in the sysroot are treated as unstable, unless they are
// on a list of known-stable sysroot crates.

use std::path::{Path, PathBuf};
use std::str;

use run_make_support::{rfs, rustc, target};

fn is_stable_crate(name: &str) -> bool {
matches!(name, "std" | "alloc" | "core" | "proc_macro")
}

fn main() {
python_command().arg("test.py").run();
for cr in get_unstable_sysroot_crates() {
check_crate_is_unstable(&cr);
}
println!("Done");
}

#[derive(Debug)]
struct Crate {
name: String,
path: PathBuf,
}

fn check_crate_is_unstable(cr: &Crate) {
let Crate { name, path } = cr;

print!("- Verifying that sysroot crate '{name}' is an unstable crate ...");

// Trying to use this crate from a user program should fail.
let output = rustc()
.crate_type("rlib")
.target(target())
.extern_(name, path)
.input("-")
.stdin(format!("extern crate {name};"))
.run_fail();

// Make sure it failed for the intended reason, not some other reason.
// (The actual feature required varies between crates.)
output.assert_stderr_contains("use of unstable library feature");

println!(" OK");
}

fn get_unstable_sysroot_crates() -> Vec<Crate> {
let sysroot = PathBuf::from(rustc().print("sysroot").run().stdout_utf8().trim());
let sysroot_libs_dir = sysroot.join("lib").join("rustlib").join(target()).join("lib");
println!("Sysroot libs dir: {sysroot_libs_dir:?}");

// Generate a list of all library crates in the sysroot.
let sysroot_crates = get_all_crates_in_dir(&sysroot_libs_dir);
println!(
"Found {} sysroot crates: {:?}",
sysroot_crates.len(),
sysroot_crates.iter().map(|cr| &cr.name).collect::<Vec<_>>()
);

// Self-check: If we didn't find `core`, we probably checked the wrong directory.
assert!(
sysroot_crates.iter().any(|cr| cr.name == "core"),
"Couldn't find `core` in {sysroot_libs_dir:?}"
);

let unstable_sysroot_crates =
sysroot_crates.into_iter().filter(|cr| !is_stable_crate(&cr.name)).collect::<Vec<_>>();
// Self-check: There should be at least one unstable crate in the directory.
assert!(
!unstable_sysroot_crates.is_empty(),
"Couldn't find any unstable crates in {sysroot_libs_dir:?}"
);
unstable_sysroot_crates
}

fn get_all_crates_in_dir(libs_dir: &Path) -> Vec<Crate> {
let mut libs = vec![];
rfs::read_dir_entries(libs_dir, |path| {
if !path.is_file() {
return;
}
if let Some(name) = crate_name_from_path(path) {
libs.push(Crate { name, path: path.to_owned() });
}
});
libs.sort_by(|a, b| a.name.cmp(&b.name));
libs
}

/// Treat a file as a crate if its name begins with `lib` and ends with `.rlib`.
/// The crate name is the part before the first hyphen (if any).
fn crate_name_from_path(path: &Path) -> Option<String> {
let name = path
.file_name()?
.to_str()?
.strip_prefix("lib")?
.strip_suffix(".rlib")?
.split('-')
.next()
.expect("split always yields at least one string");
Some(name.to_owned())
}
75 changes: 0 additions & 75 deletions tests/run-make/sysroot-crates-are-unstable/test.py

This file was deleted.