Skip to content

Commit 6d445e1

Browse files
committed
Auto merge of #44260 - alexcrichton:hardlink-no-copy, r=Mark-Simulacrum
rustbuild: Switch back to using hard links 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 #39518 due to a bug that only showed up on Windows, described in #39504. The cause described in #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!
2 parents f982ff0 + 38bedfa commit 6d445e1

File tree

6 files changed

+47
-33
lines changed

6 files changed

+47
-33
lines changed

src/Cargo.lock

+18-21
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/bootstrap/dist.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
2121
use std::env;
2222
use std::fs::{self, File};
23-
use std::io::{Read, Write};
23+
use std::io::{self, Read, Write};
2424
use std::path::{PathBuf, Path};
2525
use std::process::{Command, Stdio};
2626

@@ -900,7 +900,11 @@ impl Step for PlainSourceTarball {
900900
fn install(src: &Path, dstdir: &Path, perms: u32) {
901901
let dst = dstdir.join(src.file_name().unwrap());
902902
t!(fs::create_dir_all(dstdir));
903-
t!(fs::copy(src, &dst));
903+
{
904+
let mut s = t!(fs::File::open(&src));
905+
let mut d = t!(fs::File::create(&dst));
906+
io::copy(&mut s, &mut d).expect("failed to copy");
907+
}
904908
chmod(&dst, perms);
905909
}
906910

src/bootstrap/tool.rs

+15-5
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ struct ToolBuild {
6262
compiler: Compiler,
6363
target: Interned<String>,
6464
tool: &'static str,
65+
path: &'static str,
6566
mode: Mode,
6667
}
6768

@@ -81,6 +82,7 @@ impl Step for ToolBuild {
8182
let compiler = self.compiler;
8283
let target = self.target;
8384
let tool = self.tool;
85+
let path = self.path;
8486

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

95-
let mut cargo = prepare_tool_cargo(builder, compiler, target, tool);
97+
let mut cargo = prepare_tool_cargo(builder, compiler, target, path);
9698
build.run(&mut cargo);
9799
build.cargo_out(compiler, Mode::Tool, target).join(exe(tool, &compiler.host))
98100
}
@@ -102,11 +104,11 @@ fn prepare_tool_cargo(
102104
builder: &Builder,
103105
compiler: Compiler,
104106
target: Interned<String>,
105-
tool: &'static str,
107+
path: &'static str,
106108
) -> Command {
107109
let build = builder.build;
108110
let mut cargo = builder.cargo(compiler, Mode::Tool, target, "build");
109-
let dir = build.src.join("src/tools").join(tool);
111+
let dir = build.src.join(path);
110112
cargo.arg("--manifest-path").arg(dir.join("Cargo.toml"));
111113

112114
// We don't want to build tools dynamically as they'll be running across
@@ -184,6 +186,7 @@ macro_rules! tool {
184186
target: self.target,
185187
tool: $tool_name,
186188
mode: $mode,
189+
path: $path,
187190
})
188191
}
189192
}
@@ -201,7 +204,7 @@ tool!(
201204
Compiletest, "src/tools/compiletest", "compiletest", Mode::Libtest;
202205
BuildManifest, "src/tools/build-manifest", "build-manifest", Mode::Libstd;
203206
RemoteTestClient, "src/tools/remote-test-client", "remote-test-client", Mode::Libstd;
204-
RustInstaller, "src/tools/rust-installer", "rust-installer", Mode::Libstd;
207+
RustInstaller, "src/tools/rust-installer", "fabricate", Mode::Libstd;
205208
);
206209

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

279-
let mut cargo = prepare_tool_cargo(builder, build_compiler, target, "rustdoc");
283+
let mut cargo = prepare_tool_cargo(builder,
284+
build_compiler,
285+
target,
286+
"src/tools/rustdoc");
280287
build.run(&mut cargo);
281288
// Cargo adds a number of paths to the dylib search path on windows, which results in
282289
// the wrong rustdoc being executed. To avoid the conflicting rustdocs, we name the "tool"
@@ -337,6 +344,7 @@ impl Step for Cargo {
337344
target: self.target,
338345
tool: "cargo",
339346
mode: Mode::Librustc,
347+
path: "src/tools/cargo",
340348
})
341349
}
342350
}
@@ -375,6 +383,7 @@ impl Step for Clippy {
375383
target: self.target,
376384
tool: "clippy",
377385
mode: Mode::Librustc,
386+
path: "src/tools/clippy",
378387
})
379388
}
380389
}
@@ -417,6 +426,7 @@ impl Step for Rls {
417426
target: self.target,
418427
tool: "rls",
419428
mode: Mode::Librustc,
429+
path: "src/tools/rls",
420430
})
421431
}
422432
}

src/bootstrap/util.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,12 @@ pub fn staticlib(name: &str, target: &str) -> String {
3434
/// Copies a file from `src` to `dst`
3535
pub fn copy(src: &Path, dst: &Path) {
3636
let _ = fs::remove_file(&dst);
37-
let res = fs::copy(src, dst);
38-
if let Err(e) = res {
37+
// Attempt to "easy copy" by creating a hard link (symlinks don't work on
38+
// windows), but if that fails just fall back to a slow `copy` operation.
39+
if let Ok(()) = fs::hard_link(src, dst) {
40+
return
41+
}
42+
if let Err(e) = fs::copy(src, dst) {
3943
panic!("failed to copy `{}` to `{}`: {}", src.display(),
4044
dst.display(), e)
4145
}
@@ -44,7 +48,6 @@ pub fn copy(src: &Path, dst: &Path) {
4448
let atime = FileTime::from_last_access_time(&metadata);
4549
let mtime = FileTime::from_last_modification_time(&metadata);
4650
t!(filetime::set_file_times(dst, atime, mtime));
47-
4851
}
4952

5053
/// Copies the `src` directory recursively to `dst`. Both are assumed to exist

0 commit comments

Comments
 (0)