Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
7 changes: 7 additions & 0 deletions Cargo.lock
Original file line number Diff line number Diff line change
Expand Up @@ -879,6 +879,13 @@ dependencies = [
"windows 0.61.3",
]

[[package]]
name = "compiletest-lint-driver"
version = "0.1.0"
dependencies = [
"libloading 0.9.0",
]

[[package]]
name = "console"
version = "0.16.3"
Expand Down
1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ members = [
"src/tools/clippy/clippy_dev",
"src/tools/collect-license-metadata",
"src/tools/compiletest",
"src/tools/compiletest-lint-driver",
"src/tools/coverage-dump",
"src/tools/features-status-dump",
"src/tools/generate-copyright",
Expand Down
7 changes: 7 additions & 0 deletions src/bootstrap/src/core/build_steps/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -877,6 +877,13 @@ tool_check_step!(Compiletest {
default: false,
});

tool_check_step!(CompiletestLintDriver {
path: "src/tools/compiletest-lint-driver",
mode: Mode::ToolRustcPrivate,
allow_features: "rustc_private",
default: false,
});

// As with compiletest, rustdoc-gui-test is automatically built when running
// relevant tests. So being able to check it is mainly useful for people
// working on on rustdoc-gui-test itself, or on its compiletest dependency.
Expand Down
1 change: 1 addition & 0 deletions src/bootstrap/src/core/build_steps/clippy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -498,6 +498,7 @@ lint_any!(
Clippy, "src/tools/clippy", "clippy", Mode::ToolRustcPrivate;
CollectLicenseMetadata, "src/tools/collect-license-metadata", "collect-license-metadata", Mode::ToolTarget;
Compiletest, "src/tools/compiletest", "compiletest", Mode::ToolTarget;
CompiletestLintDriver, "src/tools/compiletest-lint-driver", "compiletest-lint-driver", Mode::ToolRustcPrivate;
CoverageDump, "src/tools/coverage-dump", "coverage-dump", Mode::ToolTarget;
Jsondocck, "src/tools/jsondocck", "jsondocck", Mode::ToolTarget;
Jsondoclint, "src/tools/jsondoclint", "jsondoclint", Mode::ToolTarget;
Expand Down
17 changes: 17 additions & 0 deletions src/bootstrap/src/core/build_steps/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2058,6 +2058,12 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
builder.ensure(compile::Rustc::new(test_compiler, target));
}

let lint_driver_compiler = query_compiler.unwrap_or(test_compiler);
if suite == "ui-fulldeps" {
builder.std(lint_driver_compiler, target);
builder.std(lint_driver_compiler, lint_driver_compiler.host);
}

if suite == "debuginfo" {
builder.ensure(dist::DebuggerScripts {
sysroot: builder.sysroot(test_compiler).to_path_buf(),
Expand Down Expand Up @@ -2096,6 +2102,17 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
cmd.arg("--compile-lib-path").arg(builder.rustc_libdir(test_compiler));
cmd.arg("--run-lib-path").arg(builder.sysroot_target_libdir(test_compiler, target));
cmd.arg("--rustc-path").arg(builder.rustc(test_compiler));
if suite == "ui-fulldeps" {
let lint_driver: PathBuf = builder
.ensure(tool::CompiletestLintDriver {
compiler: test_compiler,
target: test_compiler.host,
})
.tool_path;
Comment on lines +2106 to +2111

@clubby789 clubby789 Jun 10, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does add some tool+std builds unconditionally to any ui-fulldeps invoke; this should hopefully be relatively low impact in practice

View changes since the review

cmd.arg("--rustc-lint-driver-path").arg(lint_driver);
cmd.arg("--rustc-lint-driver-lib-path").arg(builder.rustc_libdir(lint_driver_compiler));
cmd.arg("--rustc-lint-driver-sysroot").arg(builder.sysroot(lint_driver_compiler));
}
if let Some(query_compiler) = query_compiler {
cmd.arg("--query-rustc-path").arg(builder.rustc(query_compiler));
}
Expand Down
41 changes: 41 additions & 0 deletions src/bootstrap/src/core/build_steps/tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -634,6 +634,47 @@ impl Step for ErrorIndex {
}
}

#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct CompiletestLintDriver {
pub compiler: Compiler,
pub target: TargetSelection,
}

impl Step for CompiletestLintDriver {
type Output = ToolBuildResult;
fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
run.path("src/tools/compiletest-lint-driver")
}

fn make_run(run: RunConfig<'_>) {
run.builder.ensure(CompiletestLintDriver {
compiler: run.builder.compiler(0, run.builder.config.host_target),
target: run.target,
});
}

fn run(self, builder: &Builder<'_>) -> ToolBuildResult {
builder.std(self.compiler, self.target);
builder.ensure(compile::Rustc::new(self.compiler, self.target));
builder.ensure(ToolBuild {
build_compiler: self.compiler,
target: self.target,
tool: "compiletest-lint-driver",
mode: Mode::ToolRustcPrivate,
path: "src/tools/compiletest-lint-driver",
source_type: SourceType::InTree,
extra_features: Vec::new(),
allow_features: "rustc_private",
cargo_args: Vec::new(),
artifact_kind: ToolArtifactKind::Binary,
})
}

fn metadata(&self) -> Option<StepMetadata> {
Some(StepMetadata::build("CompiletestLintDriver", self.target).built_by(self.compiler))
}
}

#[derive(Debug, Clone, Hash, PartialEq, Eq)]
pub struct RemoteTestServer {
pub build_compiler: Compiler,
Expand Down
3 changes: 3 additions & 0 deletions src/bootstrap/src/core/builder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,7 @@ impl<'a> Builder<'a> {
tool::Linkchecker,
tool::CargoTest,
tool::Compiletest,
tool::CompiletestLintDriver,
tool::RemoteTestServer,
tool::RemoteTestClient,
tool::RustInstaller,
Expand Down Expand Up @@ -815,6 +816,7 @@ impl<'a> Builder<'a> {
clippy::CodegenGcc,
clippy::CollectLicenseMetadata,
clippy::Compiletest,
clippy::CompiletestLintDriver,
clippy::CoverageDump,
clippy::Jsondocck,
clippy::Jsondoclint,
Expand Down Expand Up @@ -848,6 +850,7 @@ impl<'a> Builder<'a> {
check::Bootstrap,
check::RunMakeSupport,
check::Compiletest,
check::CompiletestLintDriver,
check::RustdocGuiTest,
check::FeaturesStatusDump,
check::CoverageDump,
Expand Down
12 changes: 9 additions & 3 deletions src/bootstrap/src/core/builder/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2098,6 +2098,7 @@ mod snapshot {
[test] compiletest-assembly-llvm 1 <host>
[test] compiletest-incremental 1 <host>
[test] compiletest-debuginfo 1 <host>
[build] rustc 0 <host> -> CompiletestLintDriver 1 <host>
[test] compiletest-ui-fulldeps 1 <host>
[build] rustdoc 1 <host>
[test] compiletest-rustdoc-html 1 <host>
Expand Down Expand Up @@ -2171,12 +2172,13 @@ mod snapshot {
insta::assert_snapshot!(
ctx.config("test")
.args(&["ui", "ui-fulldeps", "run-make", "rustdoc-html", "rustdoc-gui", "incremental"])
.render_steps(), @r"
.render_steps(), @"
[build] llvm <host>
[build] rustc 0 <host> -> rustc 1 <host>
[build] rustc 1 <host> -> std 1 <host>
[build] rustc 0 <host> -> Compiletest 1 <host>
[test] compiletest-ui 1 <host>
[build] rustc 0 <host> -> CompiletestLintDriver 1 <host>
[test] compiletest-ui-fulldeps 1 <host>
[build] rustc 0 <host> -> RunMakeSupport 1 <host>
[build] rustdoc 1 <host>
Expand All @@ -2195,7 +2197,7 @@ mod snapshot {
ctx.config("test")
.args(&["ui", "ui-fulldeps", "run-make", "rustdoc-html", "rustdoc-gui", "incremental"])
.stage(2)
.render_steps(), @r"
.render_steps(), @"
[build] llvm <host>
[build] rustc 0 <host> -> rustc 1 <host>
[build] rustc 1 <host> -> std 1 <host>
Expand All @@ -2204,6 +2206,7 @@ mod snapshot {
[build] rustc 0 <host> -> Compiletest 1 <host>
[test] compiletest-ui 2 <host>
[build] rustc 2 <host> -> rustc 3 <host>
[build] rustc 2 <host> -> CompiletestLintDriver 3 <host>
[test] compiletest-ui-fulldeps 2 <host>
[build] rustc 0 <host> -> RunMakeSupport 1 <host>
[build] rustdoc 2 <host>
Expand All @@ -2224,7 +2227,7 @@ mod snapshot {
.targets(&[TEST_TRIPLE_1])
.args(&["ui", "ui-fulldeps", "run-make", "rustdoc", "rustdoc-gui", "incremental"])
.stage(2)
.render_steps(), @r"
.render_steps(), @"
[build] llvm <host>
[build] rustc 0 <host> -> rustc 1 <host>
[build] rustc 1 <host> -> std 1 <host>
Expand All @@ -2236,6 +2239,8 @@ mod snapshot {
[test] compiletest-ui 2 <target1>
[build] llvm <target1>
[build] rustc 2 <host> -> rustc 3 <target1>
[build] rustc 2 <host> -> rustc 3 <host>
[build] rustc 2 <host> -> CompiletestLintDriver 3 <host>
[test] compiletest-ui-fulldeps 2 <target1>
[build] rustc 0 <host> -> RunMakeSupport 1 <host>
[build] rustdoc 2 <host>
Expand Down Expand Up @@ -2279,6 +2284,7 @@ mod snapshot {
[test] compiletest-incremental 2 <host>
[test] compiletest-debuginfo 2 <host>
[build] rustc 2 <host> -> rustc 3 <host>
[build] rustc 2 <host> -> CompiletestLintDriver 3 <host>
[test] compiletest-ui-fulldeps 2 <host>
[build] rustdoc 2 <host>
[test] compiletest-rustdoc-html 2 <host>
Expand Down
10 changes: 10 additions & 0 deletions src/tools/compiletest-lint-driver/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[package]
name = "compiletest-lint-driver"
version = "0.1.0"
edition = "2024"

[package.metadata.rust-analyzer]
rustc_private = true

[dependencies]
libloading = "0.9.0"
49 changes: 49 additions & 0 deletions src/tools/compiletest-lint-driver/src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#![feature(rustc_private)]
#![warn(unused_extern_crates)]

use std::process::ExitCode;
use std::sync::OnceLock;

use rustc_lint::LintStore;
use rustc_session::Session;

extern crate rustc_driver;
extern crate rustc_interface;
extern crate rustc_lint;
extern crate rustc_session;

struct Callbacks;

type LintRegisterFunc = unsafe extern "C" fn(&Session, &mut LintStore);

static LINT_LIBRARIES: OnceLock<Vec<libloading::Library>> = OnceLock::new();

impl rustc_driver::Callbacks for Callbacks {
fn config(&mut self, config: &mut rustc_interface::Config) {
let previous = config.register_lints.take();
config.register_lints = Some(Box::new(move |sess, lint_store| {
if let Some(previous) = &previous {
previous(sess, lint_store);
}
for library in LINT_LIBRARIES.get().unwrap() {
unsafe {
let register = library.get::<LintRegisterFunc>(b"register_lints").unwrap();
(*register)(sess, lint_store);
}
}
}))
}
}

fn main() -> ExitCode {
rustc_driver::catch_with_exit_code(|| {
let libraries = std::env::var("COMPILETEST_LINT_DRIVER_PATHS")
.expect("`COMPILETEST_LINT_DRIVER_PATHS` not provided")
.split(':')
.map(|path| unsafe { libloading::Library::new(path).unwrap() })
.collect();
LINT_LIBRARIES.set(libraries).unwrap();
let args = std::env::args().collect::<Vec<String>>();
rustc_driver::run_compiler(&args, &mut Callbacks);
})
}
9 changes: 9 additions & 0 deletions src/tools/compiletest/src/common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -326,6 +326,15 @@ pub(crate) struct Config {
/// bootstrap option `build.compiletest-allow-stage0=true` and specifying `--stage=0`.
pub(crate) rustc_path: Utf8PathBuf,

/// Path to the `compiletest-lint-driver` binary.
pub(crate) rustc_lint_driver_path: Option<Utf8PathBuf>,

/// Path to the libdir for the `compiletest-lint-driver` binary.
pub(crate) rustc_lint_driver_lib_path: Option<Utf8PathBuf>,

/// Path to the sysroot for the `compiletest-lint-driver` binary.
pub(crate) rustc_lint_driver_sysroot: Option<Utf8PathBuf>,

/// Path to a *staged* **host** platform cargo executable (unless stage 0 is forced). This
/// staged `cargo` is only used within `run-make` test recipes during recipe run time (and is
/// *not* used to compile the test recipes), and so must be staged as there may be differences
Expand Down
1 change: 1 addition & 0 deletions src/tools/compiletest/src/directives.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,7 @@ mod directives {
pub(crate) const AUX_BIN: &str = "aux-bin";
pub(crate) const AUX_BUILD: &str = "aux-build";
pub(crate) const AUX_CRATE: &str = "aux-crate";
pub(crate) const AUX_LINT: &str = "aux-lint";
pub(crate) const PROC_MACRO: &str = "proc-macro";
pub(crate) const AUX_CODEGEN_BACKEND: &str = "aux-codegen-backend";
pub(crate) const EXEC_ENV: &str = "exec-env";
Expand Down
8 changes: 6 additions & 2 deletions src/tools/compiletest/src/directives/auxiliary.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

use std::iter;

use super::directives::{AUX_BIN, AUX_BUILD, AUX_CODEGEN_BACKEND, AUX_CRATE, PROC_MACRO};
use super::directives::{AUX_BIN, AUX_BUILD, AUX_CODEGEN_BACKEND, AUX_CRATE, AUX_LINT, PROC_MACRO};
use crate::common::Config;
use crate::directives::DirectiveLine;
use crate::util::static_regex;
Expand Down Expand Up @@ -52,17 +52,20 @@ pub(crate) struct AuxProps {
/// Similar to `builds`, but also uses the resulting dylib as a
/// `-Zcodegen-backend` when compiling the test file.
pub(crate) codegen_backend: Option<String>,
/// Similar to `builds`, with the resulting dylibs passed to the lint test driver
pub(crate) lints: Vec<String>,
}

impl AuxProps {
/// Yields all of the paths (relative to `./auxiliary/`) that have been
/// specified in `aux-*` directives for this test.
pub(crate) fn all_aux_path_strings(&self) -> impl Iterator<Item = &str> {
let Self { builds, bins, crates, proc_macros, codegen_backend } = self;
let Self { builds, bins, crates, proc_macros, codegen_backend, lints } = self;

iter::empty()
.chain(builds.iter().map(String::as_str))
.chain(bins.iter().map(String::as_str))
.chain(lints.iter().map(String::as_str))
.chain(crates.iter().map(|c| c.path.as_str()))
.chain(proc_macros.iter().map(|p| p.path.as_str()))
.chain(codegen_backend.iter().map(String::as_str))
Expand All @@ -84,6 +87,7 @@ pub(super) fn parse_and_update_aux(

config.push_name_value_directive(ln, AUX_BUILD, &mut aux.builds, |r| r.trim().to_string());
config.push_name_value_directive(ln, AUX_BIN, &mut aux.bins, |r| r.trim().to_string());
config.push_name_value_directive(ln, AUX_LINT, &mut aux.lints, |r| r.trim().to_string());
config.push_name_value_directive(ln, AUX_CRATE, &mut aux.crates, parse_aux_crate);
config.push_name_value_directive(ln, PROC_MACRO, &mut aux.proc_macros, parse_proc_macro);

Expand Down
1 change: 1 addition & 0 deletions src/tools/compiletest/src/directives/directive_names.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub(crate) const KNOWN_DIRECTIVE_NAMES: &[&str] = &[
"aux-build",
"aux-codegen-backend",
"aux-crate",
"aux-lint",
"build-aux-docs",
"build-fail",
"build-pass",
Expand Down
2 changes: 1 addition & 1 deletion src/tools/compiletest/src/directives/handlers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ fn make_directive_handlers_map() -> HashMap<&'static str, Handler> {
config.set_name_directive(ln, PRETTY_COMPARE_ONLY, &mut props.pretty_compare_only);
}),
multi_handler(
&[AUX_BUILD, AUX_BIN, AUX_CRATE, PROC_MACRO, AUX_CODEGEN_BACKEND],
&[AUX_BUILD, AUX_BIN, AUX_CRATE, AUX_LINT, PROC_MACRO, AUX_CODEGEN_BACKEND],
|config, ln, props| {
// Call a helper method to deal with aux-related directives.
parse_and_update_aux(config, ln, &mut props.aux);
Expand Down
10 changes: 10 additions & 0 deletions src/tools/compiletest/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,9 @@ fn parse_config(args: Vec<String>) -> Config {
opts.reqopt("", "compile-lib-path", "path to host shared libraries", "PATH")
.reqopt("", "run-lib-path", "path to target shared libraries", "PATH")
.reqopt("", "rustc-path", "path to rustc to use for compiling", "PATH")
.optopt("", "rustc-lint-driver-path", "path to aux-lint rustc driver", "PATH")
.optopt("", "rustc-lint-driver-lib-path", "path to aux-lint rustc driver libdir", "PATH")
.optopt("", "rustc-lint-driver-sysroot", "path to aux-lint rustc driver sysroot", "PATH")
.optopt("", "cargo-path", "path to cargo to use for compiling", "PATH")
.optopt(
"",
Expand Down Expand Up @@ -406,6 +409,13 @@ fn parse_config(args: Vec<String>) -> Config {
host_compile_lib_path: make_absolute(opt_path(matches, "compile-lib-path")),
target_run_lib_path: make_absolute(opt_path(matches, "run-lib-path")),
rustc_path: opt_path(matches, "rustc-path"),
rustc_lint_driver_path: matches.opt_str("rustc-lint-driver-path").map(Utf8PathBuf::from),
rustc_lint_driver_lib_path: matches
.opt_str("rustc-lint-driver-lib-path")
.map(Utf8PathBuf::from),
rustc_lint_driver_sysroot: matches
.opt_str("rustc-lint-driver-sysroot")
.map(Utf8PathBuf::from),
cargo_path: matches.opt_str("cargo-path").map(Utf8PathBuf::from),
stage0_rustc_path: matches.opt_str("stage0-rustc-path").map(Utf8PathBuf::from),
query_rustc_path: matches.opt_str("query-rustc-path").map(Utf8PathBuf::from),
Expand Down
Loading
Loading