Skip to content
Merged
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
45 changes: 45 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@ tempfile = "3"
rustc_version = "0.4"
anyhow = "1.0"
walkdir = "2.4"
regex = "1.11.1"
62 changes: 62 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use std::path::{Path, PathBuf};
use std::process::Command;

use anyhow::{bail, Context, Result};
use regex::Regex;
use tempfile::TempDir;
use walkdir::WalkDir;

Expand Down Expand Up @@ -348,6 +349,18 @@ path = {src_dir_test:?}
),
};

let builtins_patch = if let Some(path) = builtins_patch_location(src_dir) {
format!(
r#"
[patch.crates-io.compiler_builtins]
path = {src_dir_workspace_builtins:?}
"#,
src_dir_workspace_builtins = src_dir.join(path),
)
} else {
String::new()
};

// If we include a patch for rustc-std-workspace-std for no_std sysroot builds, we get a
// warning from Cargo that the patch is unused. If this patching ever breaks that lint will
// probably be very helpful, so it would be best to not disable it.
Expand All @@ -359,6 +372,7 @@ path = {src_dir_test:?}
r#"
[patch.crates-io.rustc-std-workspace-core]
path = {src_dir_workspace_core:?}
{builtins_patch}
"#,
src_dir_workspace_core = src_dir.join("rustc-std-workspace-core"),
),
Expand All @@ -370,6 +384,7 @@ path = {src_dir_workspace_core:?}
path = {src_dir_workspace_alloc:?}
[patch.crates-io.rustc-std-workspace-std]
path = {src_dir_workspace_std:?}
{builtins_patch}
"#,
src_dir_workspace_core = src_dir.join("rustc-std-workspace-core"),
src_dir_workspace_alloc = src_dir.join("rustc-std-workspace-alloc"),
Expand Down Expand Up @@ -559,3 +574,50 @@ panic = 'unwind'
Ok(SysrootStatus::SysrootBuilt)
}
}

/// If the workspace Cargo.toml needs a `compiler_builtins` patch, return the path
fn builtins_patch_location(src_dir: &Path) -> Option<String> {
// Assume no patch is needed if the workspace Cargo.toml doesn't exist
let f = fs::read_to_string(src_dir.join("Cargo.toml")).ok()?;

// Crudely extract only the patches and see if one exists for `compiler_builtins`
let patches = f.split_once("[patch.crates-io]")?.1;
Copy link
Owner

Choose a reason for hiding this comment

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

Would it make sense to just copy the entire [patch.crates-io] section if it exists?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That would probably be reasonable - how would you like the logic to work with let patches = ...? We could replace the PATH portion of rustc-std-workspace-CRATE = { path = 'PATH' } with src_dir.join("rustc-std-workspace-CRATE") and then delete unneeded rustc-std-workspace-*.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It might also be possible to copy the entire workspace Cargo.toml file but stripping [workspace] so you get the profile.release config https://github.com/rust-lang/rust/blob/f315e6145802e091ff9fceab6db627a4b4ec2b86/library/Cargo.toml#L16-L45 and anything else that winds up getting added. But this would mean Cargo warnings if e.g. gimli isn't in the crate graph because SysrootConfig::NoStd is used.

Copy link
Owner

Choose a reason for hiding this comment

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

Ah right, we need to overwrite some of the patches...

We could replace the PATH portion of rustc-std-workspace-CRATE = { path = 'PATH' } with src_dir.join("rustc-std-workspace-CRATE") and then delete unneeded rustc-std-workspace-*.

That sounds reasonable.

Probably best to have a toml parser around for getting this data out of the manifest.

It might also be possible to copy the entire workspace Cargo.toml file but stripping [workspace] so you get the profile.release config

I'd rather copy the profile part than copy everything by default.


Overall this expands the scope of the PR quite a bit, so I am also fine with landing the approach you have here -- it's only needed temporarily anyway. The nicer version (that copies the profile etc) can be done later. Let me know which option you want to pursue for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

If you are okay with what is here, I have a mild preference to go with this for now since this covers the current usecase. I'm happy to implement a smarter version with a parser / printer afterward, but that won't be for another couple of days and it would be nice to be able to get the big update list rolling.

Copy link
Owner

Choose a reason for hiding this comment

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

Just copying the patch section also has the problem of copying too match for no-std builds, where we currently have special logic to avoid a cargo warning...

So yeah let's just land this as-is for now.

let re =
Regex::new(r#"(?m)^\s*compiler_builtins\s*=\s*\{.*path\s*=\s*"(?P<path>.*)".*\}"#).unwrap();
let path = re.captures(patches)?.name("path").unwrap().as_str();
Some(path.to_string())
}

#[cfg(test)]
mod tests {
use super::*;

#[test]
fn check_patch_location() {
let has_patch = r#"
[workspace]
# ...
[patch.crates-io]
other = { path = "foo" }
compiler_builtins = {path = "dir1/dir2"}
"#;
let no_patch = r#"
[workspace]
# ...
# Dep rather than a patch
compiler_builtins = { path = "dir1/dir2" }
"#;

let dir = tempfile::tempdir().unwrap();
let f = dir.path().join("Cargo.toml");
fs::write(&f, has_patch).unwrap();

assert_eq!(
builtins_patch_location(dir.path()),
Some("dir1/dir2".to_string())
);

fs::write(&f, no_patch).unwrap();
assert_eq!(builtins_patch_location(dir.path()), None);
}
}