Skip to content

Commit e4ff872

Browse files
authored
progressive linking (#564)
* Implement progressive linking * Address feedback
1 parent 0613e2a commit e4ff872

File tree

1 file changed

+36
-57
lines changed

1 file changed

+36
-57
lines changed

src/lib.rs

Lines changed: 36 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1774,66 +1774,25 @@ impl Build {
17741774
}
17751775

17761776
fn assemble(&self, lib_name: &str, dst: &Path, objs: &[Object]) -> Result<(), Error> {
1777-
// Delete the destination if it exists as the `ar` tool at least on Unix
1778-
// appends to it, which we don't want.
1777+
// Delete the destination if it exists as we want to
1778+
// create on the first iteration instead of appending.
17791779
let _ = fs::remove_file(&dst);
1780-
1781-
let objects: Vec<_> = objs.iter().map(|obj| obj.dst.clone()).collect();
17821780
let target = self.get_target()?;
1783-
if target.contains("msvc") {
1784-
let (mut cmd, program) = self.get_ar()?;
1785-
let mut out = OsString::from("-out:");
1786-
out.push(dst);
1787-
cmd.arg(out).arg("-nologo");
1788-
for flag in self.ar_flags.iter() {
1789-
cmd.arg(flag);
1790-
}
1791-
1792-
// Similar to https://github.com/rust-lang/rust/pull/47507
1793-
// and https://github.com/rust-lang/rust/pull/48548
1794-
let estimated_command_line_len = objects
1795-
.iter()
1796-
.chain(&self.objects)
1797-
.map(|a| a.as_os_str().len())
1798-
.sum::<usize>();
1799-
if estimated_command_line_len > 1024 * 6 {
1800-
let mut args = String::from("\u{FEFF}"); // BOM
1801-
for arg in objects.iter().chain(&self.objects) {
1802-
args.push('"');
1803-
for c in arg.to_str().unwrap().chars() {
1804-
if c == '"' {
1805-
args.push('\\')
1806-
}
1807-
args.push(c)
1808-
}
1809-
args.push('"');
1810-
args.push('\n');
1811-
}
1812-
1813-
let mut utf16le = Vec::new();
1814-
for code_unit in args.encode_utf16() {
1815-
utf16le.push(code_unit as u8);
1816-
utf16le.push((code_unit >> 8) as u8);
1817-
}
1818-
1819-
let mut args_file = OsString::from(dst);
1820-
args_file.push(".args");
1821-
fs::File::create(&args_file)
1822-
.unwrap()
1823-
.write_all(&utf16le)
1824-
.unwrap();
1781+
let objs: Vec<_> = objs
1782+
.iter()
1783+
.map(|o| o.dst.clone())
1784+
.chain(self.objects.clone())
1785+
.collect();
18251786

1826-
let mut args_file_arg = OsString::from("@");
1827-
args_file_arg.push(args_file);
1828-
cmd.arg(args_file_arg);
1829-
} else {
1830-
cmd.args(&objects).args(&self.objects);
1831-
}
1832-
run(&mut cmd, &program)?;
1787+
for chunk in objs.chunks(100) {
1788+
self.assemble_progressive(dst, chunk)?;
1789+
}
18331790

1791+
if target.contains("msvc") {
18341792
// The Rust compiler will look for libfoo.a and foo.lib, but the
18351793
// MSVC linker will also be passed foo.lib, so be sure that both
18361794
// exist for now.
1795+
18371796
let lib_dst = dst.with_file_name(format!("{}.lib", lib_name));
18381797
let _ = fs::remove_file(&lib_dst);
18391798
match fs::hard_link(&dst, &lib_dst).or_else(|_| {
@@ -1848,6 +1807,29 @@ impl Build {
18481807
));
18491808
}
18501809
};
1810+
}
1811+
1812+
Ok(())
1813+
}
1814+
1815+
fn assemble_progressive(&self, dst: &Path, objs: &[PathBuf]) -> Result<(), Error> {
1816+
let target = self.get_target()?;
1817+
1818+
if target.contains("msvc") {
1819+
let (mut cmd, program) = self.get_ar()?;
1820+
let mut out = OsString::from("-out:");
1821+
out.push(dst);
1822+
cmd.arg(out).arg("-nologo");
1823+
for flag in self.ar_flags.iter() {
1824+
cmd.arg(flag);
1825+
}
1826+
// If the library file already exists, add the libary name
1827+
// as an argument to let lib.exe know we are appending the objs.
1828+
if dst.exists() {
1829+
cmd.arg(dst);
1830+
}
1831+
cmd.args(objs);
1832+
run(&mut cmd, &program)?;
18511833
} else {
18521834
let (mut ar, cmd) = self.get_ar()?;
18531835

@@ -1877,10 +1859,7 @@ impl Build {
18771859
for flag in self.ar_flags.iter() {
18781860
ar.arg(flag);
18791861
}
1880-
run(
1881-
ar.arg("crs").arg(dst).args(&objects).args(&self.objects),
1882-
&cmd,
1883-
)?;
1862+
run(ar.arg("crs").arg(dst).args(objs), &cmd)?;
18841863
}
18851864

18861865
Ok(())

0 commit comments

Comments
 (0)