Skip to content

Commit c4c6eaa

Browse files
committed
[hermes] Stop copying shadow crate; run in-place
gherrit-pr-id: G5bgufougyvpozncgq4yokgx3sie6wfy7
1 parent 565936b commit c4c6eaa

File tree

3 files changed

+10
-122
lines changed

3 files changed

+10
-122
lines changed

tools/hermes/src/charon.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ pub fn run_charon(args: &Args, roots: &Roots, packages: &[HermesArtifact]) -> Re
4646
// Ensure cargo emits json msgs which charon-driver natively generates
4747
cmd.arg("--message-format=json");
4848

49-
cmd.arg("--manifest-path").arg(&artifact.shadow_manifest_path);
49+
cmd.arg("--manifest-path").arg(&artifact.manifest_path);
5050

5151
match artifact.target_kind {
5252
HermesTargetKind::Lib
@@ -117,7 +117,7 @@ pub fn run_charon(args: &Args, roots: &Roots, packages: &[HermesArtifact]) -> Re
117117
let reader = BufReader::new(stdout);
118118

119119
let mut mapper = crate::diagnostics::DiagnosticMapper::new(
120-
artifact.shadow_manifest_path.parent().unwrap().to_path_buf(),
120+
roots.workspace.clone(),
121121
roots.workspace.clone(),
122122
);
123123

tools/hermes/src/shadow.rs

Lines changed: 7 additions & 90 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ use std::{
77
};
88

99
use anyhow::{Context, Result};
10-
use cargo_metadata::PackageName;
1110
use dashmap::DashSet;
1211
use walkdir::WalkDir;
1312

@@ -19,8 +18,8 @@ use crate::{
1918
pub struct HermesArtifact {
2019
pub name: HermesTargetName,
2120
pub target_kind: HermesTargetKind,
22-
/// The path to the shadow crate's `Cargo.toml`.
23-
pub shadow_manifest_path: PathBuf,
21+
/// The path to the crate's `Cargo.toml`.
22+
pub manifest_path: PathBuf,
2423
pub start_from: Vec<String>,
2524
}
2625

@@ -37,10 +36,9 @@ impl HermesArtifact {
3736
}
3837

3938
// Double-hash to make sure we can distinguish between e.g.
40-
// (shadow_manifest_path, target_name) = ("abc", "def") and ("ab",
41-
// "cdef"), which would hash identically if we just hashed their
42-
// concatenation.
43-
let h0 = hash(&self.shadow_manifest_path);
39+
// (manifest_path, target_name) = ("abc", "def") and ("ab", "cdef"),
40+
// which would hash identically if we just hashed their concatenation.
41+
let h0 = hash(&self.manifest_path);
4442
let h1 = hash(&self.name.target_name);
4543
let h = hash(&[h0, h1]);
4644
format!("{}-{}-{:08x}.llbc", self.name.package_name, self.name.target_name, h)
@@ -54,29 +52,12 @@ impl HermesArtifact {
5452
/// 2. Creates symlinks for the remaining skeleton.
5553
pub fn build_shadow_crate(roots: &Roots) -> Result<Vec<HermesArtifact>> {
5654
log::trace!("build_shadow_crate({:?})", roots);
57-
let shadow_root = roots.shadow_root();
58-
if shadow_root.exists() {
59-
fs::remove_dir_all(&shadow_root).context("Failed to clear shadow root")?;
60-
}
61-
fs::create_dir_all(&shadow_root).context("Failed to create shadow root")?;
6255

6356
let visited_paths = DashSet::new();
6457
let (err_tx, err_rx) = mpsc::channel();
6558
// Items are `((PackageName, TargetName), ItemPath)`.
6659
let (path_tx, path_rx) = mpsc::channel::<(HermesTargetName, String)>();
6760

68-
let mut shadow_manifest_paths: HashMap<PackageName, PathBuf> = HashMap::new();
69-
for target in &roots.roots {
70-
if !shadow_manifest_paths.contains_key(&target.name.package_name) {
71-
let relative_manifest_path = find_package_root(&target.src_path)?
72-
.strip_prefix(&roots.workspace)
73-
.context("Package root outside workspace")?
74-
.join("Cargo.toml");
75-
let shadow_manifest_path = shadow_root.join(&relative_manifest_path);
76-
shadow_manifest_paths.insert(target.name.package_name.clone(), shadow_manifest_path);
77-
}
78-
}
79-
8061
let monitor_handle = std::thread::spawn(move || {
8162
let mut error_count = 0;
8263
for err in err_rx {
@@ -137,23 +118,17 @@ pub fn build_shadow_crate(roots: &Roots) -> Result<Vec<HermesArtifact>> {
137118
return Err(anyhow::anyhow!("Aborting due to {} previous errors.", count));
138119
}
139120

140-
let skip_paths: HashSet<PathBuf> = visited_paths.into_iter().collect();
141-
create_symlink_skeleton(&roots.workspace, &shadow_root, &roots.cargo_target_dir, &skip_paths)?;
142-
143121
Ok(roots
144122
.roots
145123
.iter()
146124
.filter_map(|target| {
147-
// We know that every root has a shadow manifest path, because we
148-
// inserted one for each package that has a root.
149-
let shadow_manifest_path =
150-
shadow_manifest_paths.get(&target.name.package_name).unwrap();
125+
let manifest_path = find_package_root(&target.src_path).ok()?.join("Cargo.toml");
151126
let start_from = entry_points.remove(&target.name)?;
152127

153128
Some(HermesArtifact {
154129
name: target.name.clone(),
155130
target_kind: target.kind,
156-
shadow_manifest_path: shadow_manifest_path.clone(),
131+
manifest_path,
157132
start_from,
158133
})
159134
})
@@ -324,61 +299,3 @@ fn resolve_module_path(
324299

325300
None
326301
}
327-
328-
fn create_symlink_skeleton(
329-
source_root: &Path,
330-
dest_root: &Path,
331-
target_dir: &Path,
332-
skip_paths: &HashSet<PathBuf>,
333-
) -> Result<()> {
334-
log::trace!("create_symlink_skeleton(source_root: {:?}, dest_root: {:?}, target_dir: {:?}, skip_paths_count: {})", source_root, dest_root, target_dir, skip_paths.len());
335-
let walker = WalkDir::new(source_root)
336-
.follow_links(false) // Security: don't follow symlinks out of the root.
337-
.into_iter();
338-
339-
let filter = |e: &walkdir::DirEntry| {
340-
let p = e.path();
341-
// Normally, we expect the `dest_root` to be inside of `target_dir`,
342-
// so checking both is redundant. However, if we ever add the option
343-
// for the user to manually specify a `dest_root` that is outside of
344-
// `target_dir`, this check will prevent us from infinitely recursing
345-
// into the source root.
346-
p != target_dir && p != dest_root && e.file_name() != ".git"
347-
};
348-
349-
for entry in walker.filter_entry(filter) {
350-
let entry = entry.context("Failed to read directory entry")?;
351-
let src_path = entry.path();
352-
353-
let relative_path =
354-
src_path.strip_prefix(source_root).context("File is not inside source root")?;
355-
let dest_path = dest_root.join(relative_path);
356-
357-
if entry.file_type().is_dir() {
358-
fs::create_dir_all(&dest_path)
359-
.with_context(|| format!("Failed to create shadow directory: {:?}", dest_path))?;
360-
continue;
361-
}
362-
363-
if entry.file_type().is_file() && !skip_paths.contains(src_path) {
364-
make_symlink(src_path, &dest_path)?;
365-
}
366-
}
367-
368-
Ok(())
369-
}
370-
371-
#[cfg(unix)]
372-
fn make_symlink(original: &Path, link: &Path) -> Result<()> {
373-
std::os::unix::fs::symlink(original, link)
374-
.with_context(|| format!("Failed to symlink {:?} -> {:?}", original, link))
375-
}
376-
377-
#[cfg(windows)]
378-
fn make_symlink(original: &Path, link: &Path) -> Result<()> {
379-
// Windows treats file and directory symlinks differently.
380-
// Since we only call this on files (checking is_file above),
381-
// we use symlink_file.
382-
std::os::windows::fs::symlink_file(original, link)
383-
.with_context(|| format!("Failed to symlink {:?} -> {:?}", original, link))
384-
}

tools/hermes/tests/integration.rs

Lines changed: 1 addition & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -95,11 +95,9 @@ exec "{1}" "$@"
9595
let mock_json_file = test_case_root.join("mock_charon_output.json");
9696
if mock_json_file.exists() {
9797
// Instead of writing the mock json to the shadow root (which gets cleared by build_shadow_crate), write it to the test workspace root!
98-
let shadow_root =
99-
sandbox_root.join("target").join("hermes").join("hermes_test_target").join("shadow");
10098
// We still need the path for mapping `[SHADOW_ROOT]` correctly!
10199
// But we construct it manually since it might not be created yet:
102-
let abs_shadow_root = std::env::current_dir().unwrap().join(&shadow_root);
100+
let abs_shadow_root = std::env::current_dir().unwrap().join(&sandbox_root);
103101
let abs_test_case_root =
104102
test_case_root.canonicalize().unwrap_or_else(|_| test_case_root.to_path_buf());
105103

@@ -187,13 +185,6 @@ exec "{1}" "$@"
187185
}
188186
}
189187

190-
// Tests can specify the expected shadow crate content.
191-
let actual_shadow = sandbox_root.join("target/hermes/hermes_test_target/shadow");
192-
let expected_shadow = test_case_root.join("expected");
193-
if expected_shadow.exists() {
194-
assert_directories_match(&expected_shadow, &actual_shadow)?;
195-
}
196-
197188
// Load Config
198189
let mut config = TestConfig { artifact: vec![], command: vec![] };
199190
let config_file = test_case_root.join("expected_config.toml");
@@ -324,26 +315,6 @@ fn assert_artifacts_match(
324315
Ok(())
325316
}
326317

327-
fn assert_directories_match(expected: &Path, actual: &Path) -> std::io::Result<()> {
328-
for entry in WalkDir::new(expected) {
329-
let entry = entry?;
330-
if !entry.file_type().is_file() {
331-
continue;
332-
}
333-
let rel = entry.path().strip_prefix(expected).unwrap();
334-
let act = actual.join(rel);
335-
if !act.exists() {
336-
panic!("Missing file {:?}", rel);
337-
}
338-
let e_txt = fs::read_to_string(entry.path())?.replace("\r\n", "\n");
339-
let a_txt = fs::read_to_string(&act)?.replace("\r\n", "\n");
340-
if e_txt != a_txt {
341-
panic!("Mismatch in {:?}", rel);
342-
}
343-
}
344-
Ok(())
345-
}
346-
347318
fn copy_dir_contents(src: &Path, dst: &Path) -> std::io::Result<()> {
348319
fs::create_dir_all(dst)?;
349320
for entry in fs::read_dir(src)? {

0 commit comments

Comments
 (0)