Skip to content

Commit

Permalink
rustbuild: Switch back to using hard links
Browse files Browse the repository at this point in the history
The `copy` function historically in rustbuild used hard links to speed up the
copy operations that it does. This logic was backed out, however, in rust-lang#39518 due
to a bug that only showed up on Windows, described in rust-lang#39504. The cause
described in rust-lang#39504 happened because Cargo, on a fresh build, would overwrite
the previous artifacts with new hard links that Cargo itself manages.

This behavior in Cargo was fixed in rust-lang/cargo#4390 where it no longer
should overwrite files on fresh builds, opportunistically leaving the filesystem
intact and not touching it.

Hopefully this can help speed up local builds by doing fewer copies all over the
place!
  • Loading branch information
alexcrichton committed Sep 10, 2017
1 parent 18366f4 commit 38bedfa
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 33 deletions.
39 changes: 18 additions & 21 deletions src/Cargo.lock

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

8 changes: 6 additions & 2 deletions src/bootstrap/dist.rs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

use std::env;
use std::fs::{self, File};
use std::io::{Read, Write};
use std::io::{self, Read, Write};
use std::path::{PathBuf, Path};
use std::process::{Command, Stdio};

Expand Down Expand Up @@ -900,7 +900,11 @@ impl Step for PlainSourceTarball {
fn install(src: &Path, dstdir: &Path, perms: u32) {
let dst = dstdir.join(src.file_name().unwrap());
t!(fs::create_dir_all(dstdir));
t!(fs::copy(src, &dst));
{
let mut s = t!(fs::File::open(&src));
let mut d = t!(fs::File::create(&dst));
io::copy(&mut s, &mut d).expect("failed to copy");
}
chmod(&dst, perms);
}

Expand Down
20 changes: 15 additions & 5 deletions src/bootstrap/tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ struct ToolBuild {
compiler: Compiler,
target: Interned<String>,
tool: &'static str,
path: &'static str,
mode: Mode,
}

Expand All @@ -81,6 +82,7 @@ impl Step for ToolBuild {
let compiler = self.compiler;
let target = self.target;
let tool = self.tool;
let path = self.path;

match self.mode {
Mode::Libstd => builder.ensure(compile::Std { compiler, target }),
Expand All @@ -92,7 +94,7 @@ impl Step for ToolBuild {
let _folder = build.fold_output(|| format!("stage{}-{}", compiler.stage, tool));
println!("Building stage{} tool {} ({})", compiler.stage, tool, target);

let mut cargo = prepare_tool_cargo(builder, compiler, target, tool);
let mut cargo = prepare_tool_cargo(builder, compiler, target, path);
build.run(&mut cargo);
build.cargo_out(compiler, Mode::Tool, target).join(exe(tool, &compiler.host))
}
Expand All @@ -102,11 +104,11 @@ fn prepare_tool_cargo(
builder: &Builder,
compiler: Compiler,
target: Interned<String>,
tool: &'static str,
path: &'static str,
) -> Command {
let build = builder.build;
let mut cargo = builder.cargo(compiler, Mode::Tool, target, "build");
let dir = build.src.join("src/tools").join(tool);
let dir = build.src.join(path);
cargo.arg("--manifest-path").arg(dir.join("Cargo.toml"));

// We don't want to build tools dynamically as they'll be running across
Expand Down Expand Up @@ -184,6 +186,7 @@ macro_rules! tool {
target: self.target,
tool: $tool_name,
mode: $mode,
path: $path,
})
}
}
Expand All @@ -201,7 +204,7 @@ tool!(
Compiletest, "src/tools/compiletest", "compiletest", Mode::Libtest;
BuildManifest, "src/tools/build-manifest", "build-manifest", Mode::Libstd;
RemoteTestClient, "src/tools/remote-test-client", "remote-test-client", Mode::Libstd;
RustInstaller, "src/tools/rust-installer", "rust-installer", Mode::Libstd;
RustInstaller, "src/tools/rust-installer", "fabricate", Mode::Libstd;
);

#[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)]
Expand Down Expand Up @@ -230,6 +233,7 @@ impl Step for RemoteTestServer {
target: self.target,
tool: "remote-test-server",
mode: Mode::Libstd,
path: "src/tools/remote-test-server",
})
}
}
Expand Down Expand Up @@ -276,7 +280,10 @@ impl Step for Rustdoc {
let _folder = build.fold_output(|| format!("stage{}-rustdoc", target_compiler.stage));
println!("Building rustdoc for stage{} ({})", target_compiler.stage, target_compiler.host);

let mut cargo = prepare_tool_cargo(builder, build_compiler, target, "rustdoc");
let mut cargo = prepare_tool_cargo(builder,
build_compiler,
target,
"src/tools/rustdoc");
build.run(&mut cargo);
// Cargo adds a number of paths to the dylib search path on windows, which results in
// the wrong rustdoc being executed. To avoid the conflicting rustdocs, we name the "tool"
Expand Down Expand Up @@ -337,6 +344,7 @@ impl Step for Cargo {
target: self.target,
tool: "cargo",
mode: Mode::Librustc,
path: "src/tools/cargo",
})
}
}
Expand Down Expand Up @@ -375,6 +383,7 @@ impl Step for Clippy {
target: self.target,
tool: "clippy",
mode: Mode::Librustc,
path: "src/tools/clippy",
})
}
}
Expand Down Expand Up @@ -417,6 +426,7 @@ impl Step for Rls {
target: self.target,
tool: "rls",
mode: Mode::Librustc,
path: "src/tools/rls",
})
}
}
Expand Down
9 changes: 6 additions & 3 deletions src/bootstrap/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,12 @@ pub fn staticlib(name: &str, target: &str) -> String {
/// Copies a file from `src` to `dst`
pub fn copy(src: &Path, dst: &Path) {
let _ = fs::remove_file(&dst);
let res = fs::copy(src, dst);
if let Err(e) = res {
// 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.
if let Ok(()) = fs::hard_link(src, dst) {
return
}
if let Err(e) = fs::copy(src, dst) {
panic!("failed to copy `{}` to `{}`: {}", src.display(),
dst.display(), e)
}
Expand All @@ -44,7 +48,6 @@ pub fn copy(src: &Path, dst: &Path) {
let atime = FileTime::from_last_access_time(&metadata);
let mtime = FileTime::from_last_modification_time(&metadata);
t!(filetime::set_file_times(dst, atime, mtime));

}

/// Copies the `src` directory recursively to `dst`. Both are assumed to exist
Expand Down
2 changes: 1 addition & 1 deletion src/tools/rust-installer

0 comments on commit 38bedfa

Please sign in to comment.