Merge from rustc
This commit is contained in:
commit
dc0faecfcf
196 changed files with 2754 additions and 1531 deletions
|
|
@ -36,6 +36,14 @@ macro_rules! check_ci_llvm {
|
|||
};
|
||||
}
|
||||
|
||||
/// This file is embedded in the overlay directory of the tarball sources. It is
|
||||
/// useful in scenarios where developers want to see how the tarball sources were
|
||||
/// generated.
|
||||
///
|
||||
/// We also use this file to compare the host's config.toml against the CI rustc builder
|
||||
/// configuration to detect any incompatible options.
|
||||
pub(crate) const BUILDER_CONFIG_FILENAME: &str = "builder-config";
|
||||
|
||||
#[derive(Clone, Default)]
|
||||
pub enum DryRun {
|
||||
/// This isn't a dry run.
|
||||
|
|
@ -47,7 +55,7 @@ pub enum DryRun {
|
|||
UserSelected,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Default, PartialEq, Eq)]
|
||||
#[derive(Copy, Clone, Default, Debug, Eq, PartialEq)]
|
||||
pub enum DebuginfoLevel {
|
||||
#[default]
|
||||
None,
|
||||
|
|
@ -117,7 +125,7 @@ impl Display for DebuginfoLevel {
|
|||
/// 2) MSVC
|
||||
/// - Self-contained: `-Clinker=<path to rust-lld>`
|
||||
/// - External: `-Clinker=lld`
|
||||
#[derive(Default, Copy, Clone)]
|
||||
#[derive(Copy, Clone, Default, Debug, PartialEq)]
|
||||
pub enum LldMode {
|
||||
/// Do not use LLD
|
||||
#[default]
|
||||
|
|
@ -1203,40 +1211,42 @@ impl Config {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn parse(flags: Flags) -> Config {
|
||||
#[cfg(test)]
|
||||
fn get_toml(_: &Path) -> TomlConfig {
|
||||
TomlConfig::default()
|
||||
}
|
||||
|
||||
#[cfg(not(test))]
|
||||
fn get_toml(file: &Path) -> TomlConfig {
|
||||
let contents =
|
||||
t!(fs::read_to_string(file), format!("config file {} not found", file.display()));
|
||||
// Deserialize to Value and then TomlConfig to prevent the Deserialize impl of
|
||||
// TomlConfig and sub types to be monomorphized 5x by toml.
|
||||
toml::from_str(&contents)
|
||||
.and_then(|table: toml::Value| TomlConfig::deserialize(table))
|
||||
.unwrap_or_else(|err| {
|
||||
if let Ok(Some(changes)) = toml::from_str(&contents)
|
||||
.and_then(|table: toml::Value| ChangeIdWrapper::deserialize(table)).map(|change_id| change_id.inner.map(crate::find_recent_config_change_ids))
|
||||
{
|
||||
if !changes.is_empty() {
|
||||
println!(
|
||||
"WARNING: There have been changes to x.py since you last updated:\n{}",
|
||||
crate::human_readable_changes(&changes)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
eprintln!("failed to parse TOML configuration '{}': {err}", file.display());
|
||||
exit!(2);
|
||||
})
|
||||
}
|
||||
Self::parse_inner(flags, get_toml)
|
||||
#[cfg(test)]
|
||||
fn get_toml(_: &Path) -> Result<TomlConfig, toml::de::Error> {
|
||||
Ok(TomlConfig::default())
|
||||
}
|
||||
|
||||
pub(crate) fn parse_inner(mut flags: Flags, get_toml: impl Fn(&Path) -> TomlConfig) -> Config {
|
||||
#[cfg(not(test))]
|
||||
fn get_toml(file: &Path) -> Result<TomlConfig, toml::de::Error> {
|
||||
let contents =
|
||||
t!(fs::read_to_string(file), format!("config file {} not found", file.display()));
|
||||
// Deserialize to Value and then TomlConfig to prevent the Deserialize impl of
|
||||
// TomlConfig and sub types to be monomorphized 5x by toml.
|
||||
toml::from_str(&contents)
|
||||
.and_then(|table: toml::Value| TomlConfig::deserialize(table))
|
||||
.inspect_err(|_| {
|
||||
if let Ok(Some(changes)) = toml::from_str(&contents)
|
||||
.and_then(|table: toml::Value| ChangeIdWrapper::deserialize(table))
|
||||
.map(|change_id| change_id.inner.map(crate::find_recent_config_change_ids))
|
||||
{
|
||||
if !changes.is_empty() {
|
||||
println!(
|
||||
"WARNING: There have been changes to x.py since you last updated:\n{}",
|
||||
crate::human_readable_changes(&changes)
|
||||
);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn parse(flags: Flags) -> Config {
|
||||
Self::parse_inner(flags, Self::get_toml)
|
||||
}
|
||||
|
||||
pub(crate) fn parse_inner(
|
||||
mut flags: Flags,
|
||||
get_toml: impl Fn(&Path) -> Result<TomlConfig, toml::de::Error>,
|
||||
) -> Config {
|
||||
let mut config = Config::default_opts();
|
||||
|
||||
// Set flags.
|
||||
|
|
@ -1344,7 +1354,10 @@ impl Config {
|
|||
} else {
|
||||
toml_path.clone()
|
||||
});
|
||||
get_toml(&toml_path)
|
||||
get_toml(&toml_path).unwrap_or_else(|e| {
|
||||
eprintln!("ERROR: Failed to parse '{}': {e}", toml_path.display());
|
||||
exit!(2);
|
||||
})
|
||||
} else {
|
||||
config.config = None;
|
||||
TomlConfig::default()
|
||||
|
|
@ -1375,7 +1388,13 @@ impl Config {
|
|||
include_path.push("bootstrap");
|
||||
include_path.push("defaults");
|
||||
include_path.push(format!("config.{include}.toml"));
|
||||
let included_toml = get_toml(&include_path);
|
||||
let included_toml = get_toml(&include_path).unwrap_or_else(|e| {
|
||||
eprintln!(
|
||||
"ERROR: Failed to parse default config profile at '{}': {e}",
|
||||
include_path.display()
|
||||
);
|
||||
exit!(2);
|
||||
});
|
||||
toml.merge(included_toml, ReplaceOpt::IgnoreDuplicate);
|
||||
}
|
||||
|
||||
|
|
@ -1591,24 +1610,6 @@ impl Config {
|
|||
let mut is_user_configured_rust_channel = false;
|
||||
|
||||
if let Some(rust) = toml.rust {
|
||||
if let Some(commit) = config.download_ci_rustc_commit(rust.download_rustc.clone()) {
|
||||
// Primarily used by CI runners to avoid handling download-rustc incompatible
|
||||
// options one by one on shell scripts.
|
||||
let disable_ci_rustc_if_incompatible =
|
||||
env::var_os("DISABLE_CI_RUSTC_IF_INCOMPATIBLE")
|
||||
.is_some_and(|s| s == "1" || s == "true");
|
||||
|
||||
if let Err(e) = check_incompatible_options_for_ci_rustc(&rust) {
|
||||
if disable_ci_rustc_if_incompatible {
|
||||
config.download_rustc_commit = None;
|
||||
} else {
|
||||
panic!("{}", e);
|
||||
}
|
||||
} else {
|
||||
config.download_rustc_commit = Some(commit);
|
||||
}
|
||||
}
|
||||
|
||||
let Rust {
|
||||
optimize: optimize_toml,
|
||||
debug: debug_toml,
|
||||
|
|
@ -1656,7 +1657,7 @@ impl Config {
|
|||
new_symbol_mangling,
|
||||
profile_generate,
|
||||
profile_use,
|
||||
download_rustc: _,
|
||||
download_rustc,
|
||||
lto,
|
||||
validate_mir_opts,
|
||||
frame_pointers,
|
||||
|
|
@ -1668,6 +1669,8 @@ impl Config {
|
|||
is_user_configured_rust_channel = channel.is_some();
|
||||
set(&mut config.channel, channel.clone());
|
||||
|
||||
config.download_rustc_commit = config.download_ci_rustc_commit(download_rustc);
|
||||
|
||||
debug = debug_toml;
|
||||
debug_assertions = debug_assertions_toml;
|
||||
debug_assertions_std = debug_assertions_std_toml;
|
||||
|
|
@ -2345,6 +2348,45 @@ impl Config {
|
|||
None => None,
|
||||
Some(commit) => {
|
||||
self.download_ci_rustc(commit);
|
||||
|
||||
if let Some(config_path) = &self.config {
|
||||
let builder_config_path =
|
||||
self.out.join(self.build.triple).join("ci-rustc").join(BUILDER_CONFIG_FILENAME);
|
||||
|
||||
let ci_config_toml = match Self::get_toml(&builder_config_path) {
|
||||
Ok(ci_config_toml) => ci_config_toml,
|
||||
Err(e) if e.to_string().contains("unknown field") => {
|
||||
println!("WARNING: CI rustc has some fields that are no longer supported in bootstrap; download-rustc will be disabled.");
|
||||
println!("HELP: Consider rebasing to a newer commit if available.");
|
||||
return None;
|
||||
},
|
||||
Err(e) => {
|
||||
eprintln!("ERROR: Failed to parse CI rustc config at '{}': {e}", builder_config_path.display());
|
||||
exit!(2);
|
||||
},
|
||||
};
|
||||
|
||||
let current_config_toml = Self::get_toml(config_path).unwrap();
|
||||
|
||||
// Check the config compatibility
|
||||
// FIXME: this doesn't cover `--set` flags yet.
|
||||
let res = check_incompatible_options_for_ci_rustc(
|
||||
current_config_toml,
|
||||
ci_config_toml,
|
||||
);
|
||||
|
||||
let disable_ci_rustc_if_incompatible =
|
||||
env::var_os("DISABLE_CI_RUSTC_IF_INCOMPATIBLE")
|
||||
.is_some_and(|s| s == "1" || s == "true");
|
||||
|
||||
if disable_ci_rustc_if_incompatible && res.is_err() {
|
||||
println!("WARNING: download-rustc is disabled with `DISABLE_CI_RUSTC_IF_INCOMPATIBLE` env.");
|
||||
return None;
|
||||
}
|
||||
|
||||
res.unwrap();
|
||||
}
|
||||
|
||||
Some(commit.clone())
|
||||
}
|
||||
})
|
||||
|
|
@ -2662,31 +2704,52 @@ impl Config {
|
|||
}
|
||||
}
|
||||
|
||||
/// Checks the CI rustc incompatible options by destructuring the `Rust` instance
|
||||
/// and makes sure that no rust options from config.toml are missed.
|
||||
fn check_incompatible_options_for_ci_rustc(rust: &Rust) -> Result<(), String> {
|
||||
/// Compares the current Rust options against those in the CI rustc builder and detects any incompatible options.
|
||||
/// It does this by destructuring the `Rust` instance to make sure every `Rust` field is covered and not missing.
|
||||
fn check_incompatible_options_for_ci_rustc(
|
||||
current_config_toml: TomlConfig,
|
||||
ci_config_toml: TomlConfig,
|
||||
) -> Result<(), String> {
|
||||
macro_rules! err {
|
||||
($name:expr) => {
|
||||
if $name.is_some() {
|
||||
return Err(format!(
|
||||
"ERROR: Setting `rust.{}` is incompatible with `rust.download-rustc`.",
|
||||
stringify!($name).replace("_", "-")
|
||||
));
|
||||
}
|
||||
($current:expr, $expected:expr) => {
|
||||
if let Some(current) = &$current {
|
||||
if Some(current) != $expected.as_ref() {
|
||||
return Err(format!(
|
||||
"ERROR: Setting `rust.{}` is incompatible with `rust.download-rustc`. \
|
||||
Current value: {:?}, Expected value(s): {}{:?}",
|
||||
stringify!($expected).replace("_", "-"),
|
||||
$current,
|
||||
if $expected.is_some() { "None/" } else { "" },
|
||||
$expected,
|
||||
));
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! warn {
|
||||
($name:expr) => {
|
||||
if $name.is_some() {
|
||||
println!(
|
||||
"WARNING: `rust.{}` has no effect with `rust.download-rustc`.",
|
||||
stringify!($name).replace("_", "-")
|
||||
);
|
||||
}
|
||||
($current:expr, $expected:expr) => {
|
||||
if let Some(current) = &$current {
|
||||
if Some(current) != $expected.as_ref() {
|
||||
println!(
|
||||
"WARNING: `rust.{}` has no effect with `rust.download-rustc`. \
|
||||
Current value: {:?}, Expected value(s): {}{:?}",
|
||||
stringify!($expected).replace("_", "-"),
|
||||
$current,
|
||||
if $expected.is_some() { "None/" } else { "" },
|
||||
$expected,
|
||||
);
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
let (Some(current_rust_config), Some(ci_rust_config)) =
|
||||
(current_config_toml.rust, ci_config_toml.rust)
|
||||
else {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
let Rust {
|
||||
// Following options are the CI rustc incompatible ones.
|
||||
optimize,
|
||||
|
|
@ -2744,7 +2807,7 @@ fn check_incompatible_options_for_ci_rustc(rust: &Rust) -> Result<(), String> {
|
|||
download_rustc: _,
|
||||
validate_mir_opts: _,
|
||||
frame_pointers: _,
|
||||
} = rust;
|
||||
} = ci_rust_config;
|
||||
|
||||
// There are two kinds of checks for CI rustc incompatible options:
|
||||
// 1. Checking an option that may change the compiler behaviour/output.
|
||||
|
|
@ -2752,22 +2815,23 @@ fn check_incompatible_options_for_ci_rustc(rust: &Rust) -> Result<(), String> {
|
|||
//
|
||||
// If the option belongs to the first category, we call `err` macro for a hard error;
|
||||
// otherwise, we just print a warning with `warn` macro.
|
||||
err!(optimize);
|
||||
err!(debug_logging);
|
||||
err!(debuginfo_level_rustc);
|
||||
err!(default_linker);
|
||||
err!(rpath);
|
||||
err!(strip);
|
||||
err!(stack_protector);
|
||||
err!(lld_mode);
|
||||
err!(llvm_tools);
|
||||
err!(llvm_bitcode_linker);
|
||||
err!(jemalloc);
|
||||
err!(lto);
|
||||
|
||||
warn!(channel);
|
||||
warn!(description);
|
||||
warn!(incremental);
|
||||
err!(current_rust_config.optimize, optimize);
|
||||
err!(current_rust_config.debug_logging, debug_logging);
|
||||
err!(current_rust_config.debuginfo_level_rustc, debuginfo_level_rustc);
|
||||
err!(current_rust_config.rpath, rpath);
|
||||
err!(current_rust_config.strip, strip);
|
||||
err!(current_rust_config.lld_mode, lld_mode);
|
||||
err!(current_rust_config.llvm_tools, llvm_tools);
|
||||
err!(current_rust_config.llvm_bitcode_linker, llvm_bitcode_linker);
|
||||
err!(current_rust_config.jemalloc, jemalloc);
|
||||
err!(current_rust_config.default_linker, default_linker);
|
||||
err!(current_rust_config.stack_protector, stack_protector);
|
||||
err!(current_rust_config.lto, lto);
|
||||
|
||||
warn!(current_rust_config.channel, channel);
|
||||
warn!(current_rust_config.description, description);
|
||||
warn!(current_rust_config.incremental, incremental);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ use crate::core::config::{LldMode, Target, TargetSelection, TomlConfig};
|
|||
fn parse(config: &str) -> Config {
|
||||
Config::parse_inner(
|
||||
Flags::parse(&["check".to_string(), "--config=/does/not/exist".to_string()]),
|
||||
|&_| toml::from_str(&config).unwrap(),
|
||||
|&_| toml::from_str(&config),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
@ -151,7 +151,6 @@ runner = "x86_64-runner"
|
|||
|
||||
"#,
|
||||
)
|
||||
.unwrap()
|
||||
},
|
||||
);
|
||||
assert_eq!(config.change_id, Some(1), "setting top-level value");
|
||||
|
|
@ -208,13 +207,13 @@ fn override_toml_duplicate() {
|
|||
"--set=change-id=1".to_owned(),
|
||||
"--set=change-id=2".to_owned(),
|
||||
]),
|
||||
|&_| toml::from_str("change-id = 0").unwrap(),
|
||||
|&_| toml::from_str("change-id = 0"),
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn profile_user_dist() {
|
||||
fn get_toml(file: &Path) -> TomlConfig {
|
||||
fn get_toml(file: &Path) -> Result<TomlConfig, toml::de::Error> {
|
||||
let contents =
|
||||
if file.ends_with("config.toml") || env::var_os("RUST_BOOTSTRAP_CONFIG").is_some() {
|
||||
"profile = \"user\"".to_owned()
|
||||
|
|
@ -223,9 +222,7 @@ fn profile_user_dist() {
|
|||
std::fs::read_to_string(file).unwrap()
|
||||
};
|
||||
|
||||
toml::from_str(&contents)
|
||||
.and_then(|table: toml::Value| TomlConfig::deserialize(table))
|
||||
.unwrap()
|
||||
toml::from_str(&contents).and_then(|table: toml::Value| TomlConfig::deserialize(table))
|
||||
}
|
||||
Config::parse_inner(Flags::parse(&["check".to_owned()]), get_toml);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ use std::sync::OnceLock;
|
|||
use build_helper::ci::CiEnv;
|
||||
use xz2::bufread::XzDecoder;
|
||||
|
||||
use crate::core::config::BUILDER_CONFIG_FILENAME;
|
||||
use crate::utils::exec::{command, BootstrapCommand};
|
||||
use crate::utils::helpers::{check_run, exe, hex_encode, move_file, program_out_of_date};
|
||||
use crate::{t, Config};
|
||||
|
|
@ -273,11 +274,12 @@ impl Config {
|
|||
|
||||
let mut tar = tar::Archive::new(decompressor);
|
||||
|
||||
let is_ci_rustc = dst.ends_with("ci-rustc");
|
||||
|
||||
// `compile::Sysroot` needs to know the contents of the `rustc-dev` tarball to avoid adding
|
||||
// it to the sysroot unless it was explicitly requested. But parsing the 100 MB tarball is slow.
|
||||
// Cache the entries when we extract it so we only have to read it once.
|
||||
let mut recorded_entries =
|
||||
if dst.ends_with("ci-rustc") { recorded_entries(dst, pattern) } else { None };
|
||||
let mut recorded_entries = if is_ci_rustc { recorded_entries(dst, pattern) } else { None };
|
||||
|
||||
for member in t!(tar.entries()) {
|
||||
let mut member = t!(member);
|
||||
|
|
@ -287,10 +289,12 @@ impl Config {
|
|||
continue;
|
||||
}
|
||||
let mut short_path = t!(original_path.strip_prefix(directory_prefix));
|
||||
if !short_path.starts_with(pattern) {
|
||||
let is_builder_config = short_path.to_str() == Some(BUILDER_CONFIG_FILENAME);
|
||||
|
||||
if !(short_path.starts_with(pattern) || (is_ci_rustc && is_builder_config)) {
|
||||
continue;
|
||||
}
|
||||
short_path = t!(short_path.strip_prefix(pattern));
|
||||
short_path = short_path.strip_prefix(pattern).unwrap_or(short_path);
|
||||
let dst_path = dst.join(short_path);
|
||||
self.verbose(|| {
|
||||
println!("extracting {} to {}", original_path.display(), dst.display())
|
||||
|
|
@ -703,9 +707,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");
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
@ -1056,11 +1058,29 @@ Executed at: {executed_at}"#,
|
|||
}
|
||||
};
|
||||
|
||||
let fail = |message: &str| {
|
||||
let fail = |message: &str, output: CommandOutput| -> ! {
|
||||
if self.is_verbose() {
|
||||
println!("{message}");
|
||||
} else {
|
||||
println!("Command has failed. Rerun with -v to see more details.");
|
||||
let (stdout, stderr) = (output.stdout_if_present(), output.stderr_if_present());
|
||||
// If the command captures output, the user would not see any indication that
|
||||
// it has failed. In this case, print a more verbose error, since to provide more
|
||||
// context.
|
||||
if stdout.is_some() || stderr.is_some() {
|
||||
if let Some(stdout) =
|
||||
output.stdout_if_present().take_if(|s| !s.trim().is_empty())
|
||||
{
|
||||
println!("STDOUT:\n{stdout}\n");
|
||||
}
|
||||
if let Some(stderr) =
|
||||
output.stderr_if_present().take_if(|s| !s.trim().is_empty())
|
||||
{
|
||||
println!("STDERR:\n{stderr}\n");
|
||||
}
|
||||
println!("Command {command:?} has failed. Rerun with -v to see more details.");
|
||||
} else {
|
||||
println!("Command has failed. Rerun with -v to see more details.");
|
||||
}
|
||||
}
|
||||
exit!(1);
|
||||
};
|
||||
|
|
@ -1069,14 +1089,14 @@ Executed at: {executed_at}"#,
|
|||
match command.failure_behavior {
|
||||
BehaviorOnFailure::DelayFail => {
|
||||
if self.fail_fast {
|
||||
fail(&message);
|
||||
fail(&message, output);
|
||||
}
|
||||
|
||||
let mut failures = self.delayed_failures.borrow_mut();
|
||||
failures.push(message);
|
||||
}
|
||||
BehaviorOnFailure::Exit => {
|
||||
fail(&message);
|
||||
fail(&message, output);
|
||||
}
|
||||
BehaviorOnFailure::Ignore => {
|
||||
// If failures are allowed, either the error has been printed already
|
||||
|
|
@ -1774,21 +1794,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));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -291,6 +291,11 @@ impl CommandOutput {
|
|||
.expect("Cannot parse process stdout as UTF-8")
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn stdout_if_present(&self) -> Option<String> {
|
||||
self.stdout.as_ref().and_then(|s| String::from_utf8(s.clone()).ok())
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn stdout_if_ok(&self) -> Option<String> {
|
||||
if self.is_success() { Some(self.stdout()) } else { None }
|
||||
|
|
@ -303,6 +308,11 @@ impl CommandOutput {
|
|||
)
|
||||
.expect("Cannot parse process stderr as UTF-8")
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
pub fn stderr_if_present(&self) -> Option<String> {
|
||||
self.stderr.as_ref().and_then(|s| String::from_utf8(s.clone()).ok())
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for CommandOutput {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,25 @@ 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(Flags::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)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ use std::path::{Path, PathBuf};
|
|||
|
||||
use crate::core::build_steps::dist::distdir;
|
||||
use crate::core::builder::{Builder, Kind};
|
||||
use crate::core::config::BUILDER_CONFIG_FILENAME;
|
||||
use crate::utils::exec::BootstrapCommand;
|
||||
use crate::utils::helpers::{move_file, t};
|
||||
use crate::utils::{channel, helpers};
|
||||
|
|
@ -320,7 +321,7 @@ impl<'a> Tarball<'a> {
|
|||
|
||||
// Add config file if present.
|
||||
if let Some(config) = &self.builder.config.config {
|
||||
self.add_renamed_file(config, &self.overlay_dir, "builder-config");
|
||||
self.add_renamed_file(config, &self.overlay_dir, BUILDER_CONFIG_FILENAME);
|
||||
}
|
||||
|
||||
for file in self.overlay.legal_and_readme() {
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 67fa536768013d9d5a13f3a06790521d511ef711
|
||||
Subproject commit 04bc1396bb857f35b5dda1d773c9571e1f253304
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 5454de3d12b9ccc6375b629cf7ccda8264640aac
|
||||
Subproject commit aeeb287d41a0332c210da122bea8e0e91844ab3e
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 0ebdacadbda8ce2cd8fbf93985e15af61a7ab895
|
||||
Subproject commit 6ecf95c5f2bfa0e6314dfe282bf775fd1405f7e9
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 2e191814f163ee1e77e2d6094eee4dd78a289c5b
|
||||
Subproject commit 62cd0df95061ba0ac886333f5cd7f3012f149da1
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 89aecb6951b77bc746da73df8c9f2b2ceaad494a
|
||||
Subproject commit 8f94061936e492159f4f6c09c0f917a7521893ff
|
||||
|
|
@ -1 +1 @@
|
|||
Subproject commit 0c4d55cb59fe440d1a630e4e5774d043968edb3f
|
||||
Subproject commit 43d83780db545a1ed6d45773312fc578987e3968
|
||||
|
|
@ -61,6 +61,7 @@
|
|||
- [mipsisa\*r6\*-unknown-linux-gnu\*](platform-support/mips-release-6.md)
|
||||
- [nvptx64-nvidia-cuda](platform-support/nvptx64-nvidia-cuda.md)
|
||||
- [powerpc-unknown-openbsd](platform-support/powerpc-unknown-openbsd.md)
|
||||
- [powerpc-unknown-linux-muslspe](platform-support/powerpc-unknown-linux-muslspe.md)
|
||||
- [powerpc64-ibm-aix](platform-support/aix.md)
|
||||
- [riscv32im-risc0-zkvm-elf](platform-support/riscv32im-risc0-zkvm-elf.md)
|
||||
- [riscv32imac-unknown-xous-elf](platform-support/riscv32imac-unknown-xous-elf.md)
|
||||
|
|
|
|||
|
|
@ -332,6 +332,7 @@ target | std | host | notes
|
|||
`msp430-none-elf` | * | | 16-bit MSP430 microcontrollers
|
||||
`powerpc-unknown-linux-gnuspe` | ✓ | | PowerPC SPE Linux
|
||||
`powerpc-unknown-linux-musl` | ? | | PowerPC Linux with musl 1.2.3
|
||||
[`powerpc-unknown-linux-muslspe`](platform-support/powerpc-unknown-linux-muslspe.md) | ? | | PowerPC SPE Linux
|
||||
[`powerpc-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD 32-bit powerpc systems
|
||||
[`powerpc-unknown-openbsd`](platform-support/powerpc-unknown-openbsd.md) | * | |
|
||||
[`powerpc-wrs-vxworks-spe`](platform-support/vxworks.md) | ✓ | |
|
||||
|
|
|
|||
|
|
@ -61,3 +61,8 @@ Currently the `riscv64-linux-android` target requires the following architecture
|
|||
* `Zba` (address calculation instructions)
|
||||
* `Zbb` (base instructions)
|
||||
* `Zbs` (single-bit instructions)
|
||||
|
||||
### aarch64-linux-android on Nightly compilers
|
||||
|
||||
As soon as `-Zfixed-x18` compiler flag is supplied, the [`ShadowCallStack` sanitizer](https://releases.llvm.org/7.0.1/tools/clang/docs/ShadowCallStack.html)
|
||||
instrumentation is also made avaiable by supplying the second compiler flag `-Zsanitizer=shadow-call-stack`.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,32 @@
|
|||
# powerpc-unknown-linux-muslspe
|
||||
|
||||
**Tier: 3**
|
||||
|
||||
This target is very similar to already existing ones like `powerpc_unknown_linux_musl` and `powerpc_unknown_linux_gnuspe`.
|
||||
This one has PowerPC SPE support for musl. Unfortunately, the last supported gcc version with PowerPC SPE is 8.4.0.
|
||||
|
||||
## Target maintainers
|
||||
|
||||
- [@BKPepe](https://github.com/BKPepe)
|
||||
|
||||
## Requirements
|
||||
|
||||
This target is cross-compiled. There is no support for `std`. There is no
|
||||
default allocator, but it's possible to use `alloc` by supplying an allocator.
|
||||
|
||||
This target generated binaries in the ELF format.
|
||||
|
||||
## Building the target
|
||||
|
||||
This target was tested and used within the `OpenWrt` build system for CZ.NIC Turris 1.x routers using Freescale P2020.
|
||||
|
||||
## Building Rust programs
|
||||
|
||||
Rust does not yet ship pre-compiled artifacts for this target. To compile for
|
||||
this target, you will either need to build Rust with the target enabled (see
|
||||
"Building the target" above), or build your own copy of `core` by using
|
||||
`build-std` or similar.
|
||||
|
||||
## Testing
|
||||
|
||||
This is a cross-compiled target and there is no support to run rustc test suite.
|
||||
|
|
@ -515,6 +515,9 @@ pub fn no_documentation() {}
|
|||
|
||||
Note that the third item is the crate root, which in this case is undocumented.
|
||||
|
||||
If you want the JSON output to be displayed on `stdout` instead of having a file generated, you can
|
||||
use `-o -`.
|
||||
|
||||
### `-w`/`--output-format`: output format
|
||||
|
||||
`--output-format json` emits documentation in the experimental
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# `fixed-x18`
|
||||
|
||||
This option prevents the compiler from using the x18 register. It is only
|
||||
supported on aarch64.
|
||||
supported on `aarch64`.
|
||||
|
||||
From the [ABI spec][arm-abi]:
|
||||
|
||||
|
|
@ -23,6 +23,11 @@ Currently, the `-Zsanitizer=shadow-call-stack` flag is only supported on
|
|||
platforms that always treat x18 as a reserved register, and the `-Zfixed-x18`
|
||||
flag is not required to use the sanitizer on such platforms. However, the
|
||||
sanitizer may be supported on targets where this is not the case in the future.
|
||||
One way to do so now on Nightly compilers is to explicitly supply this `-Zfixed-x18`
|
||||
flag with `aarch64` targets, so that the sanitizer is available for instrumentation
|
||||
on targets like `aarch64-unknown-none`, for instance. However, discretion is still
|
||||
required to make sure that the runtime support is in place for this sanitizer
|
||||
to be effective.
|
||||
|
||||
It is undefined behavior for `-Zsanitizer=shadow-call-stack` code to call into
|
||||
code where x18 is a temporary register. On the other hand, when you are *not*
|
||||
|
|
|
|||
|
|
@ -787,6 +787,10 @@ A runtime must be provided by the application or operating system.
|
|||
|
||||
See the [Clang ShadowCallStack documentation][clang-scs] for more details.
|
||||
|
||||
* `aarch64-unknown-none`
|
||||
|
||||
In addition to support from a runtime by the application or operating system, the `-Zfixed-x18` flag is also mandatory.
|
||||
|
||||
# ThreadSanitizer
|
||||
|
||||
ThreadSanitizer is a data race detection tool. It is supported on the following
|
||||
|
|
|
|||
|
|
@ -286,6 +286,9 @@ pub(crate) struct RenderOptions {
|
|||
pub(crate) no_emit_shared: bool,
|
||||
/// If `true`, HTML source code pages won't be generated.
|
||||
pub(crate) html_no_source: bool,
|
||||
/// This field is only used for the JSON output. If it's set to true, no file will be created
|
||||
/// and content will be displayed in stdout directly.
|
||||
pub(crate) output_to_stdout: bool,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
|
||||
|
|
@ -548,16 +551,17 @@ impl Options {
|
|||
dcx.fatal("the `--test` flag must be passed to enable `--no-run`");
|
||||
}
|
||||
|
||||
let mut output_to_stdout = false;
|
||||
let test_builder_wrappers =
|
||||
matches.opt_strs("test-builder-wrapper").iter().map(PathBuf::from).collect();
|
||||
let out_dir = matches.opt_str("out-dir").map(|s| PathBuf::from(&s));
|
||||
let output = matches.opt_str("output").map(|s| PathBuf::from(&s));
|
||||
let output = match (out_dir, output) {
|
||||
let output = match (matches.opt_str("out-dir"), matches.opt_str("output")) {
|
||||
(Some(_), Some(_)) => {
|
||||
dcx.fatal("cannot use both 'out-dir' and 'output' at once");
|
||||
}
|
||||
(Some(out_dir), None) => out_dir,
|
||||
(None, Some(output)) => output,
|
||||
(Some(out_dir), None) | (None, Some(out_dir)) => {
|
||||
output_to_stdout = out_dir == "-";
|
||||
PathBuf::from(out_dir)
|
||||
}
|
||||
(None, None) => PathBuf::from("doc"),
|
||||
};
|
||||
|
||||
|
|
@ -818,6 +822,7 @@ impl Options {
|
|||
call_locations,
|
||||
no_emit_shared: false,
|
||||
html_no_source,
|
||||
output_to_stdout,
|
||||
};
|
||||
Some((options, render_options))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -9,16 +9,19 @@ mod import_finder;
|
|||
|
||||
use std::cell::RefCell;
|
||||
use std::fs::{create_dir_all, File};
|
||||
use std::io::{BufWriter, Write};
|
||||
use std::io::{stdout, BufWriter, Write};
|
||||
use std::path::PathBuf;
|
||||
use std::rc::Rc;
|
||||
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_hir::def_id::{DefId, DefIdSet};
|
||||
use rustc_middle::ty::TyCtxt;
|
||||
use rustc_session::Session;
|
||||
use rustc_span::def_id::LOCAL_CRATE;
|
||||
use rustdoc_json_types as types;
|
||||
// It's important to use the FxHashMap from rustdoc_json_types here, instead of
|
||||
// the one from rustc_data_structures, as they're different types due to sysroots.
|
||||
// See #110051 and #127456 for details
|
||||
use rustdoc_json_types::FxHashMap;
|
||||
|
||||
use crate::clean::types::{ExternalCrate, ExternalLocation};
|
||||
use crate::clean::ItemKind;
|
||||
|
|
@ -37,7 +40,7 @@ pub(crate) struct JsonRenderer<'tcx> {
|
|||
/// level field of the JSON blob.
|
||||
index: Rc<RefCell<FxHashMap<types::Id, types::Item>>>,
|
||||
/// The directory where the blob will be written to.
|
||||
out_path: PathBuf,
|
||||
out_path: Option<PathBuf>,
|
||||
cache: Rc<Cache>,
|
||||
imported_items: DefIdSet,
|
||||
}
|
||||
|
|
@ -97,6 +100,20 @@ impl<'tcx> JsonRenderer<'tcx> {
|
|||
})
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
fn write<T: Write>(
|
||||
&self,
|
||||
output: types::Crate,
|
||||
mut writer: BufWriter<T>,
|
||||
path: &str,
|
||||
) -> Result<(), Error> {
|
||||
self.tcx
|
||||
.sess
|
||||
.time("rustdoc_json_serialization", || serde_json::ser::to_writer(&mut writer, &output))
|
||||
.unwrap();
|
||||
try_err!(writer.flush(), path);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
|
||||
|
|
@ -120,7 +137,7 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
|
|||
JsonRenderer {
|
||||
tcx,
|
||||
index: Rc::new(RefCell::new(FxHashMap::default())),
|
||||
out_path: options.output,
|
||||
out_path: if options.output_to_stdout { None } else { Some(options.output) },
|
||||
cache: Rc::new(cache),
|
||||
imported_items,
|
||||
},
|
||||
|
|
@ -220,14 +237,11 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
|
|||
let index = (*self.index).clone().into_inner();
|
||||
|
||||
debug!("Constructing Output");
|
||||
// This needs to be the default HashMap for compatibility with the public interface for
|
||||
// rustdoc-json-types
|
||||
#[allow(rustc::default_hash_types)]
|
||||
let output = types::Crate {
|
||||
root: types::Id(format!("0:0:{}", e.name(self.tcx).as_u32())),
|
||||
crate_version: self.cache.crate_version.clone(),
|
||||
includes_private: self.cache.document_private,
|
||||
index: index.into_iter().collect(),
|
||||
index,
|
||||
paths: self
|
||||
.cache
|
||||
.paths
|
||||
|
|
@ -264,20 +278,21 @@ impl<'tcx> FormatRenderer<'tcx> for JsonRenderer<'tcx> {
|
|||
.collect(),
|
||||
format_version: types::FORMAT_VERSION,
|
||||
};
|
||||
let out_dir = self.out_path.clone();
|
||||
try_err!(create_dir_all(&out_dir), out_dir);
|
||||
if let Some(ref out_path) = self.out_path {
|
||||
let out_dir = out_path.clone();
|
||||
try_err!(create_dir_all(&out_dir), out_dir);
|
||||
|
||||
let mut p = out_dir;
|
||||
p.push(output.index.get(&output.root).unwrap().name.clone().unwrap());
|
||||
p.set_extension("json");
|
||||
let mut file = BufWriter::new(try_err!(File::create(&p), p));
|
||||
self.tcx
|
||||
.sess
|
||||
.time("rustdoc_json_serialization", || serde_json::ser::to_writer(&mut file, &output))
|
||||
.unwrap();
|
||||
try_err!(file.flush(), p);
|
||||
|
||||
Ok(())
|
||||
let mut p = out_dir;
|
||||
p.push(output.index.get(&output.root).unwrap().name.clone().unwrap());
|
||||
p.set_extension("json");
|
||||
self.write(
|
||||
output,
|
||||
BufWriter::new(try_err!(File::create(&p), p)),
|
||||
&p.display().to_string(),
|
||||
)
|
||||
} else {
|
||||
self.write(output, BufWriter::new(stdout()), "<stdout>")
|
||||
}
|
||||
}
|
||||
|
||||
fn cache(&self) -> &Cache {
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 57ae1a3474057fead2c438928ed368b3740bf0ec
|
||||
Subproject commit ccf4c38bdd73f1a37ec266c73bdaef80e39f8cf6
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use rustc_hash::FxHashMap;
|
||||
pub use rustc_hash::FxHashMap;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// The version of JSON output that this crate represents.
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
Subproject commit 0d8d22f83b066503f6b2b755925197e959e58b4f
|
||||
Subproject commit 2f738d617c6ead388f899802dd1a7fd66858a691
|
||||
|
|
@ -470,7 +470,7 @@ fn setup_mod_file(path: &Path, lint: &LintData<'_>) -> io::Result<&'static str>
|
|||
});
|
||||
|
||||
// Find both the last lint declaration (declare_clippy_lint!) and the lint pass impl
|
||||
while let Some(LintDeclSearchResult { content, .. }) = iter.find(|result| result.token_kind == TokenKind::Ident) {
|
||||
while let Some(LintDeclSearchResult { content, .. }) = iter.find(|result| result.token == TokenKind::Ident) {
|
||||
let mut iter = iter
|
||||
.by_ref()
|
||||
.filter(|t| !matches!(t.token_kind, TokenKind::Whitespace | TokenKind::LineComment { .. }));
|
||||
|
|
@ -480,7 +480,7 @@ fn setup_mod_file(path: &Path, lint: &LintData<'_>) -> io::Result<&'static str>
|
|||
// matches `!{`
|
||||
match_tokens!(iter, Bang OpenBrace);
|
||||
if let Some(LintDeclSearchResult { range, .. }) =
|
||||
iter.find(|result| result.token_kind == TokenKind::CloseBrace)
|
||||
iter.find(|result| result.token == TokenKind::CloseBrace)
|
||||
{
|
||||
last_decl_curly_offset = Some(range.end);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@
|
|||
#![feature(let_chains)]
|
||||
#![feature(trait_upcasting)]
|
||||
#![feature(strict_overflow_ops)]
|
||||
#![feature(is_none_or)]
|
||||
// Configure clippy and other lints
|
||||
#![allow(
|
||||
clippy::collapsible_else_if,
|
||||
|
|
|
|||
|
|
@ -11,3 +11,4 @@ wasmparser = { version = "0.214", default-features = false, features = ["std"] }
|
|||
regex = "1.8" # 1.8 to avoid memchr 2.6.0, as 2.5.0 is pinned in the workspace
|
||||
gimli = "0.31.0"
|
||||
build_helper = { path = "../build_helper" }
|
||||
serde_json = "1.0"
|
||||
|
|
|
|||
|
|
@ -285,12 +285,24 @@ impl LlvmAr {
|
|||
self
|
||||
}
|
||||
|
||||
/// Like `obj_to_ar` except creating a thin archive.
|
||||
pub fn obj_to_thin_ar(&mut self) -> &mut Self {
|
||||
self.cmd.arg("rcus").arg("--thin");
|
||||
self
|
||||
}
|
||||
|
||||
/// Extract archive members back to files.
|
||||
pub fn extract(&mut self) -> &mut Self {
|
||||
self.cmd.arg("x");
|
||||
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 {
|
||||
|
|
|
|||
|
|
@ -71,14 +71,8 @@ impl Rustdoc {
|
|||
self
|
||||
}
|
||||
|
||||
/// Specify path to the output folder.
|
||||
pub fn output<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
|
||||
self.cmd.arg("-o");
|
||||
self.cmd.arg(path.as_ref());
|
||||
self
|
||||
}
|
||||
|
||||
/// Specify output directory.
|
||||
#[doc(alias = "output")]
|
||||
pub fn out_dir<P: AsRef<Path>>(&mut self, path: P) -> &mut Self {
|
||||
self.cmd.arg("--out-dir").arg(path.as_ref());
|
||||
self
|
||||
|
|
|
|||
|
|
@ -38,6 +38,7 @@ pub use bstr;
|
|||
pub use gimli;
|
||||
pub use object;
|
||||
pub use regex;
|
||||
pub use serde_json;
|
||||
pub use wasmparser;
|
||||
|
||||
// Re-exports of external dependencies.
|
||||
|
|
|
|||
|
|
@ -84,3 +84,18 @@ pub fn has_suffix<P: AsRef<Path>>(path: P, suffix: &str) -> bool {
|
|||
pub fn filename_contains<P: AsRef<Path>>(path: P, needle: &str) -> bool {
|
||||
path.as_ref().file_name().is_some_and(|name| name.to_str().unwrap().contains(needle))
|
||||
}
|
||||
|
||||
/// Helper for reading entries in a given directory and its children.
|
||||
pub fn read_dir_entries_recursive<P: AsRef<Path>, F: FnMut(&Path)>(dir: P, mut callback: F) {
|
||||
fn read_dir_entries_recursive_inner<P: AsRef<Path>, F: FnMut(&Path)>(dir: P, callback: &mut F) {
|
||||
for entry in rfs::read_dir(dir) {
|
||||
let path = entry.unwrap().path();
|
||||
callback(&path);
|
||||
if path.is_dir() {
|
||||
read_dir_entries_recursive_inner(path, callback);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
read_dir_entries_recursive_inner(dir, &mut callback);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1462,7 +1462,7 @@ fn generic_args_sans_defaults<'ga>(
|
|||
// otherwise, if the arg is equal to the param default, hide it (unless the
|
||||
// default is an error which can happen for the trait Self type)
|
||||
#[allow(unstable_name_collisions)]
|
||||
default_parameters.get(i).is_none_or(|default_parameter| {
|
||||
IsNoneOr::is_none_or(default_parameters.get(i), |default_parameter| {
|
||||
// !is_err(default_parameter.skip_binders())
|
||||
// &&
|
||||
arg != &default_parameter.clone().substitute(Interner, ¶meters)
|
||||
|
|
|
|||
|
|
@ -15,8 +15,10 @@ extern crate rustc_abi;
|
|||
#[cfg(not(feature = "in-rust-tree"))]
|
||||
extern crate ra_ap_rustc_abi as rustc_abi;
|
||||
|
||||
// Use the crates.io version unconditionally until the API settles enough that we can switch to
|
||||
// using the in-tree one.
|
||||
#[cfg(feature = "in-rust-tree")]
|
||||
extern crate rustc_pattern_analysis;
|
||||
|
||||
#[cfg(not(feature = "in-rust-tree"))]
|
||||
extern crate ra_ap_rustc_pattern_analysis as rustc_pattern_analysis;
|
||||
|
||||
mod builder;
|
||||
|
|
|
|||
|
|
@ -303,6 +303,12 @@ dependencies = [
|
|||
"crypto-common",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "doc-comment"
|
||||
version = "0.3.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10"
|
||||
|
||||
[[package]]
|
||||
name = "elasticlunr-rs"
|
||||
version = "3.0.2"
|
||||
|
|
@ -465,6 +471,21 @@ dependencies = [
|
|||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "html_parser"
|
||||
version = "0.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f6f56db07b6612644f6f7719f8ef944f75fff9d6378fdf3d316fd32194184abd"
|
||||
dependencies = [
|
||||
"doc-comment",
|
||||
"pest",
|
||||
"pest_derive",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "humantime"
|
||||
version = "2.1.0"
|
||||
|
|
@ -680,13 +701,13 @@ name = "mdbook-trpl-listing"
|
|||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"clap",
|
||||
"html_parser",
|
||||
"mdbook",
|
||||
"pulldown-cmark",
|
||||
"pulldown-cmark-to-cmark",
|
||||
"serde_json",
|
||||
"thiserror",
|
||||
"toml 0.8.14",
|
||||
"xmlparser",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1767,12 +1788,6 @@ dependencies = [
|
|||
"memchr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "xmlparser"
|
||||
version = "0.13.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "66fee0b777b0f5ac1c69bb06d361268faafa61cd4682ae064a171c16c433e9e4"
|
||||
|
||||
[[package]]
|
||||
name = "yaml-rust"
|
||||
version = "0.4.5"
|
||||
|
|
|
|||
|
|
@ -84,9 +84,7 @@ pub(crate) struct ParsedMacroArgs {
|
|||
fn check_keyword<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option<MacroArg> {
|
||||
for &keyword in RUST_KW.iter() {
|
||||
if parser.token.is_keyword(keyword)
|
||||
&& parser.look_ahead(1, |t| {
|
||||
t.kind == TokenKind::Eof || t.kind == TokenKind::Comma
|
||||
})
|
||||
&& parser.look_ahead(1, |t| *t == TokenKind::Eof || *t == TokenKind::Comma)
|
||||
{
|
||||
parser.bump();
|
||||
return Some(MacroArg::Keyword(
|
||||
|
|
@ -131,7 +129,7 @@ pub(crate) fn parse_macro_args(
|
|||
Some(arg) => {
|
||||
args.push(arg);
|
||||
parser.bump();
|
||||
if parser.token.kind == TokenKind::Eof && args.len() == 2 {
|
||||
if parser.token == TokenKind::Eof && args.len() == 2 {
|
||||
vec_with_semi = true;
|
||||
break;
|
||||
}
|
||||
|
|
@ -150,7 +148,7 @@ pub(crate) fn parse_macro_args(
|
|||
|
||||
parser.bump();
|
||||
|
||||
if parser.token.kind == TokenKind::Eof {
|
||||
if parser.token == TokenKind::Eof {
|
||||
trailing_comma = true;
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,21 +1,13 @@
|
|||
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
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue