Skip to content

Allow linking rustc and rustdoc against the same single tracing crate #140627

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

Merged
merged 1 commit into from
May 5, 2025
Merged
Show file tree
Hide file tree
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
13 changes: 11 additions & 2 deletions compiler/rustc_log/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ use std::env::{self, VarError};
use std::fmt::{self, Display};
use std::io::{self, IsTerminal};

use tracing::dispatcher::SetGlobalDefaultError;
use tracing_core::{Event, Subscriber};
use tracing_subscriber::filter::{Directive, EnvFilter, LevelFilter};
use tracing_subscriber::fmt::FmtContext;
Expand Down Expand Up @@ -131,10 +132,10 @@ pub fn init_logger(cfg: LoggerConfig) -> Result<(), Error> {
.without_time()
.event_format(BacktraceFormatter { backtrace_target });
let subscriber = subscriber.with(fmt_layer);
tracing::subscriber::set_global_default(subscriber).unwrap();
tracing::subscriber::set_global_default(subscriber)?;
}
Err(_) => {
tracing::subscriber::set_global_default(subscriber).unwrap();
tracing::subscriber::set_global_default(subscriber)?;
}
};

Expand Down Expand Up @@ -180,6 +181,7 @@ pub enum Error {
InvalidColorValue(String),
NonUnicodeColorValue,
InvalidWraptree(String),
AlreadyInit(SetGlobalDefaultError),
}

impl std::error::Error for Error {}
Expand All @@ -199,6 +201,13 @@ impl Display for Error {
formatter,
"invalid log WRAPTREE value '{value}': expected a non-negative integer",
),
Error::AlreadyInit(tracing_error) => Display::fmt(tracing_error, formatter),
}
}
}

impl From<SetGlobalDefaultError> for Error {
fn from(tracing_error: SetGlobalDefaultError) -> Self {
Error::AlreadyInit(tracing_error)
}
}
26 changes: 21 additions & 5 deletions src/librustdoc/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -170,12 +170,28 @@ pub fn main() {
// NOTE: this compiles both versions of tracing unconditionally, because
// - The compile time hit is not that bad, especially compared to rustdoc's incremental times, and
// - Otherwise, there's no warning that logging is being ignored when `download-rustc` is enabled
// NOTE: The reason this doesn't show double logging when `download-rustc = false` and
// `debug_logging = true` is because all rustc logging goes to its version of tracing (the one
// in the sysroot), and all of rustdoc's logging goes to its version (the one in Cargo.toml).

init_logging(&early_dcx);
rustc_driver::init_logger(&early_dcx, rustc_log::LoggerConfig::from_env("RUSTDOC_LOG"));
crate::init_logging(&early_dcx);
match rustc_log::init_logger(rustc_log::LoggerConfig::from_env("RUSTDOC_LOG")) {
Ok(()) => {}
// With `download-rustc = true` there are definitely 2 distinct tracing crates in the
// dependency graph: one in the downloaded sysroot and one built just now as a dependency of
// rustdoc. So the sysroot's tracing is definitely not yet initialized here.
//
// But otherwise, depending on link style, there may or may not be 2 tracing crates in play.
// The one we just initialized in `crate::init_logging` above is rustdoc's direct dependency
// on tracing. When rustdoc is built by x.py using Cargo, rustc_driver's and rustc_log's
// tracing dependency is distinct from this one and also needs to be initialized (using the
// same RUSTDOC_LOG environment variable for both). Other build systems may use just a
// single tracing crate throughout the rustc and rustdoc build.
//
// The reason initializing 2 tracings does not show double logging when `download-rustc =
// false` and `debug_logging = true` is because all rustc logging goes only to its version
// of tracing (the one in the sysroot) and all of rustdoc's logging only goes to its version
// (the one in Cargo.toml).
Err(rustc_log::Error::AlreadyInit(_)) => {}
Err(error) => early_dcx.early_fatal(error.to_string()),
}

let exit_code = rustc_driver::catch_with_exit_code(|| {
let at_args = rustc_driver::args::raw_args(&early_dcx);
Expand Down
Loading