From 591e2e3a7a9e557a8e99826155aa9eb520e6e108 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sat, 8 Jun 2024 13:58:22 +1000 Subject: [PATCH] Port `tests/run-make/sysroot-crates-are-unstable` to rmake --- src/tools/run-make-support/src/command.rs | 5 + src/tools/run-make-support/src/lib.rs | 13 ++- .../tidy/src/allowed_run_make_makefiles.txt | 1 - .../sysroot-crates-are-unstable/Makefile | 2 - .../sysroot-crates-are-unstable/rmake.rs | 108 ++++++++++++++++++ .../sysroot-crates-are-unstable/test.py | 75 ------------ 6 files changed, 125 insertions(+), 79 deletions(-) delete mode 100644 tests/run-make/sysroot-crates-are-unstable/Makefile create mode 100644 tests/run-make/sysroot-crates-are-unstable/rmake.rs delete mode 100644 tests/run-make/sysroot-crates-are-unstable/test.py diff --git a/src/tools/run-make-support/src/command.rs b/src/tools/run-make-support/src/command.rs index cc395e491ee12..61ef2d95210f1 100644 --- a/src/tools/run-make-support/src/command.rs +++ b/src/tools/run-make-support/src/command.rs @@ -48,6 +48,11 @@ impl Command { output } + #[track_caller] + pub fn run_unchecked(&mut self) -> CompletedProcess { + self.command_output() + } + #[track_caller] pub(crate) fn command_output(&mut self) -> CompletedProcess { // let's make sure we piped all the input and outputs diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index cea1313e29d75..3edebc9b56b08 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -278,7 +278,7 @@ pub fn recursive_diff(dir1: impl AsRef, dir2: impl AsRef) { }); } -pub fn read_dir(dir: impl AsRef, callback: F) { +pub fn read_dir(dir: impl AsRef, mut callback: impl FnMut(&Path)) { for entry in fs::read_dir(dir).unwrap() { callback(&entry.unwrap().path()); } @@ -414,6 +414,17 @@ macro_rules! impl_common_helpers { self.cmd.run_fail() } + /// Run the constructed command, but don't check its result status. + /// The caller is responsible for performing any necessary checks. + /// + /// Prefer to call [`run`](Self::run) or [`run_fail`](Self::run_fail) + /// if possible. + #[must_use] + #[track_caller] + pub fn run_unchecked(&mut self) -> crate::command::CompletedProcess { + self.cmd.run_unchecked() + } + /// Set the path where the command will be run. pub fn current_dir>(&mut self, path: P) -> &mut Self { self.cmd.current_dir(path); diff --git a/src/tools/tidy/src/allowed_run_make_makefiles.txt b/src/tools/tidy/src/allowed_run_make_makefiles.txt index babf1abbe64ac..5935831d264db 100644 --- a/src/tools/tidy/src/allowed_run_make_makefiles.txt +++ b/src/tools/tidy/src/allowed_run_make_makefiles.txt @@ -234,7 +234,6 @@ run-make/symbols-include-type-name/Makefile run-make/symlinked-extern/Makefile run-make/symlinked-libraries/Makefile run-make/symlinked-rlib/Makefile -run-make/sysroot-crates-are-unstable/Makefile run-make/target-cpu-native/Makefile run-make/target-specs/Makefile run-make/target-without-atomic-cas/Makefile diff --git a/tests/run-make/sysroot-crates-are-unstable/Makefile b/tests/run-make/sysroot-crates-are-unstable/Makefile deleted file mode 100644 index 1e267fb9576ba..0000000000000 --- a/tests/run-make/sysroot-crates-are-unstable/Makefile +++ /dev/null @@ -1,2 +0,0 @@ -all: - '$(PYTHON)' test.py diff --git a/tests/run-make/sysroot-crates-are-unstable/rmake.rs b/tests/run-make/sysroot-crates-are-unstable/rmake.rs new file mode 100644 index 0000000000000..13e7eced025d5 --- /dev/null +++ b/tests/run-make/sysroot-crates-are-unstable/rmake.rs @@ -0,0 +1,108 @@ +//! Checks that all unstable library crates in the sysroot are actually treated +//! as unstable. +#![deny(warnings)] + +use run_make_support::{env_var, read_dir, rustc}; +use std::path::{Path, PathBuf}; +use std::str; + +#[derive(Debug)] +struct Lib { + name: String, + path: PathBuf, +} + +fn check_lib(lib: &Lib) -> Result<(), ()> { + let Lib { name, path } = lib; + + println!("verifying that sysroot crate '{name}' is an unstable crate"); + + let output = rustc() + .input("-") + .crate_type("rlib") + .target(&env_var("TARGET")) + .extern_(name, path) + .stdin(format!("extern crate {name};")) + .run_unchecked(); + + if !output.status().success() + && output.stderr_utf8().contains("use of unstable library feature") + { + return Ok(()); + } + + eprintln!(); + eprintln!("CRATE IS NOT UNSTABLE: `{name}` at {path:?}"); + eprintln!("output status: `{}`", output.status()); + eprintln!("=== STDOUT ==="); + eprint!("{}", output.stdout_utf8()); + eprintln!("=============="); + eprintln!("=== STDERR ==="); + eprint!("{}", output.stderr_utf8()); + eprintln!("=============="); + + Err(()) +} + +fn get_all_libs(libs_dir: &Path) -> Vec { + let mut libs = vec![]; + read_dir(libs_dir, |file| { + if !file.is_file() { + return; + }; + + // Treat a file as a library if it begins with `lib` and ends with `.rlib`. + // The library name is the part before the first hyphen (if any). + // FIXME: Use a `try` block once they're stable. + let Some(lib_name) = Some(file).and_then(|file| { + file.file_name()? + .to_str()? + .strip_prefix("lib")? + .strip_suffix(".rlib")? + .split('-') + .next() + }) else { + return; + }; + + libs.push(Lib { name: lib_name.to_owned(), path: file.to_owned() }); + }); + libs +} + +fn sysroot() -> PathBuf { + let sysroot = rustc().print("sysroot").run().stdout_utf8().lines().next().unwrap().to_owned(); + assert!(!sysroot.is_empty()); + PathBuf::from(sysroot) +} + +fn is_stable_crate(name: &str) -> bool { + matches!(name, "std" | "alloc" | "core" | "proc_macro") +} + +fn main() { + // Generate a list of all library crates in the sysroot. + let sysroot_libs_dir = sysroot().join("lib/rustlib").join(env_var("TARGET")).join("lib"); + let sysroot_libs = get_all_libs(&sysroot_libs_dir); + + // Self-check: If we didn't find `core`, we probably checked the wrong directory. + assert!( + sysroot_libs.iter().any(|lib| lib.name == "core"), + "couldn't find `core` in {sysroot_libs_dir:?}:\n{sysroot_libs:#?}" + ); + + let unstable_sysroot_libs = + sysroot_libs.iter().filter(|lib| !is_stable_crate(&lib.name)).collect::>(); + // Self-check: There should be at least one unstable lib in the directory. + assert!( + !unstable_sysroot_libs.is_empty(), + "couldn't find any unstable libs in {sysroot_libs_dir:?}:\n{sysroot_libs:#?}" + ); + + // Check all of the crates before actually failing, so that we report all + // errors instead of just the first one. + let results = unstable_sysroot_libs.iter().map(|lib| check_lib(lib)).collect::>(); + if results.iter().any(|r| r.is_err()) { + std::process::exit(1); + } +} diff --git a/tests/run-make/sysroot-crates-are-unstable/test.py b/tests/run-make/sysroot-crates-are-unstable/test.py deleted file mode 100644 index 45cfdd195b4e2..0000000000000 --- a/tests/run-make/sysroot-crates-are-unstable/test.py +++ /dev/null @@ -1,75 +0,0 @@ -import sys -import os -from os import listdir -from os.path import isfile, join -from subprocess import PIPE, Popen - - -# This is n list of files which are stable crates or simply are not crates, -# we don't check for the instability of these crates as they're all stable! -STABLE_CRATES = ['std', 'alloc', 'core', 'proc_macro', - 'rsbegin.o', 'rsend.o', 'dllcrt2.o', 'crt2.o', 'clang_rt'] - - -def convert_to_string(s): - if s.__class__.__name__ == 'bytes': - return s.decode('utf-8') - return s - - -def set_ld_lib_path(): - var = os.environ.get("LD_LIB_PATH_ENVVAR") - rpath = os.environ.get("HOST_RPATH_DIR") - if var and rpath: - path = os.environ.get(var) - if path: - os.environ[var] = rpath + os.pathsep + path - else: - os.environ[var] = rpath - - -def exec_command(command, to_input=None): - child = None - if to_input is None: - child = Popen(command, stdout=PIPE, stderr=PIPE) - else: - child = Popen(command, stdout=PIPE, stderr=PIPE, stdin=PIPE) - stdout, stderr = child.communicate(input=to_input) - return (convert_to_string(stdout), convert_to_string(stderr)) - - -def check_lib(lib): - if lib['name'] in STABLE_CRATES: - return True - print('verifying if {} is an unstable crate'.format(lib['name'])) - stdout, stderr = exec_command([os.environ['RUSTC'], '-', '--crate-type', 'rlib', - '--target', os.environ['TARGET'], - '--extern', '{}={}'.format(lib['name'], lib['path'])], - to_input=('extern crate {};'.format(lib['name'])).encode('utf-8')) - if 'use of unstable library feature' not in '{}{}'.format(stdout, stderr): - print('crate {} "{}" is not unstable'.format(lib['name'], lib['path'])) - print('{}{}'.format(stdout, stderr)) - print('') - return False - return True - -# Generate a list of all crates in the sysroot. To do this we list all files in -# rustc's sysroot, look at the filename, strip everything after the `-`, and -# strip the leading `lib` (if present) -def get_all_libs(dir_path): - return [{ 'path': join(dir_path, f), 'name': f[3:].split('-')[0] } - for f in listdir(dir_path) - if isfile(join(dir_path, f)) and f.endswith('.rlib') and f not in STABLE_CRATES] - - -set_ld_lib_path() -sysroot = exec_command([os.environ['RUSTC'], '--print', 'sysroot'])[0].replace('\n', '') -assert sysroot, "Could not read the rustc sysroot!" -libs = get_all_libs(join(sysroot, 'lib/rustlib/{}/lib'.format(os.environ['TARGET']))) - -ret = 0 -for lib in libs: - if not check_lib(lib): - # We continue so users can see all the not unstable crates. - ret = 1 -sys.exit(ret)