Skip to content

Commit 057eab7

Browse files
committed
Make "Assemble stage1 compiler" orders of magnitude faster
This used to take upwards of 5 seconds for me locally. I found that the culprit was copying the downloaded LLVM shared object: ``` [22:28:03] Install "/home/jnelson/rust-lang/rust/build/x86_64-unknown-linux-gnu/ci-llvm/lib/libLLVM-14-rust-1.62.0-nightly.so" to "/home/jnelson/rust-lang/rust/build/x86_64-unknown-linux-gnu/stage1/lib/rustlib/x86_64-unknown-linux-gnu/lib/libLLVM-14-rust-1.62.0-nightly.so" [22:28:09] c Sysroot { compiler: Compiler { stage: 1, host: x86_64-unknown-linux-gnu(x86_64-unknown-linux-gnu) } } ``` It turned out that `install()` used full copies unconditionally. Change it to use `copy()` internally, which uses hard links instead when available. Note that this has a change in behavior: Installing a file will also change permissions on the source, not just the destination, if hard links are used. To avoid changing the behavior on symlinks for existing code, I introduce a new function `copy_internal` which only dereferences symlinks when told to do so.
1 parent b9eedea commit 057eab7

File tree

2 files changed

+20
-18
lines changed

2 files changed

+20
-18
lines changed

src/bootstrap/dist.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -1873,7 +1873,6 @@ fn add_env(builder: &Builder<'_>, cmd: &mut Command, target: TargetSelection) {
18731873

18741874
/// Maybe add LLVM object files to the given destination lib-dir. Allows either static or dynamic linking.
18751875
///
1876-
18771876
/// Returns whether the files were actually copied.
18781877
fn maybe_install_llvm(builder: &Builder<'_>, target: TargetSelection, dst_libdir: &Path) -> bool {
18791878
if let Some(config) = builder.config.target_config.get(&target) {
@@ -1983,6 +1982,8 @@ impl Step for LlvmTools {
19831982
}
19841983
}
19851984

1985+
builder.ensure(crate::native::Llvm { target });
1986+
19861987
let mut tarball = Tarball::new(builder, "llvm-tools", &target.triple);
19871988
tarball.set_overlay(OverlayKind::LLVM);
19881989
tarball.is_preview(true);

src/bootstrap/lib.rs

+18-17
Original file line numberDiff line numberDiff line change
@@ -1408,6 +1408,10 @@ impl Build {
14081408

14091409
/// Copies a file from `src` to `dst`
14101410
pub fn copy(&self, src: &Path, dst: &Path) {
1411+
self.copy_internal(src, dst, false);
1412+
}
1413+
1414+
fn copy_internal(&self, src: &Path, dst: &Path, dereference_symlinks: bool) {
14111415
if self.config.dry_run {
14121416
return;
14131417
}
@@ -1417,15 +1421,22 @@ impl Build {
14171421
}
14181422
let _ = fs::remove_file(&dst);
14191423
let metadata = t!(src.symlink_metadata());
1424+
let mut src = src.to_path_buf();
14201425
if metadata.file_type().is_symlink() {
1421-
let link = t!(fs::read_link(src));
1422-
t!(symlink_file(link, dst));
1423-
} else if let Ok(()) = fs::hard_link(src, dst) {
1426+
if dereference_symlinks {
1427+
src = t!(fs::canonicalize(src));
1428+
} else {
1429+
let link = t!(fs::read_link(src));
1430+
t!(symlink_file(link, dst));
1431+
return;
1432+
}
1433+
}
1434+
if let Ok(()) = fs::hard_link(&src, dst) {
14241435
// Attempt to "easy copy" by creating a hard link
14251436
// (symlinks don't work on windows), but if that fails
14261437
// just fall back to a slow `copy` operation.
14271438
} else {
1428-
if let Err(e) = fs::copy(src, dst) {
1439+
if let Err(e) = fs::copy(&src, dst) {
14291440
panic!("failed to copy `{}` to `{}`: {}", src.display(), dst.display(), e)
14301441
}
14311442
t!(fs::set_permissions(dst, metadata.permissions()));
@@ -1497,20 +1508,10 @@ impl Build {
14971508
let dst = dstdir.join(src.file_name().unwrap());
14981509
self.verbose_than(1, &format!("Install {:?} to {:?}", src, dst));
14991510
t!(fs::create_dir_all(dstdir));
1500-
drop(fs::remove_file(&dst));
1501-
{
1502-
if !src.exists() {
1503-
panic!("Error: File \"{}\" not found!", src.display());
1504-
}
1505-
let metadata = t!(src.symlink_metadata());
1506-
if let Err(e) = fs::copy(&src, &dst) {
1507-
panic!("failed to copy `{}` to `{}`: {}", src.display(), dst.display(), e)
1508-
}
1509-
t!(fs::set_permissions(&dst, metadata.permissions()));
1510-
let atime = FileTime::from_last_access_time(&metadata);
1511-
let mtime = FileTime::from_last_modification_time(&metadata);
1512-
t!(filetime::set_file_times(&dst, atime, mtime));
1511+
if !src.exists() {
1512+
panic!("Error: File \"{}\" not found!", src.display());
15131513
}
1514+
self.copy_internal(src, &dst, true);
15141515
chmod(&dst, perms);
15151516
}
15161517

0 commit comments

Comments
 (0)