Skip to content

Commit a247218

Browse files
committed
Set +whole-archive on C/C++ libraries
This fixes the build for Rust 1.61+ on some machines. I can reliably reproduce this locally, but CI does not exhibit this issue (I'm not sure why). The Rust compatibility notes document this change: https://github.com/rust-lang/rust/blob/1.61.0/RELEASES.md#compatibility-notes and eventually this will be supported by cc: rust-lang/cc-rs#671 Fixes #339
1 parent d3963ca commit a247218

File tree

3 files changed

+58
-0
lines changed

3 files changed

+58
-0
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
11
## 0.34 (unreleased)
22

3+
### Build
4+
5+
Fixed build on Rust 1.61+.
6+
37
### Display
48

59
Fixed an issue where side-by-side display would sometimes print the

build.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,49 @@ struct TreeSitterParser {
77
extra_files: Vec<&'static str>,
88
}
99

10+
/// Emit linking flags for this library, but specifcy `+whole-archive`.
11+
///
12+
/// This should be possible in the cc crate directly after
13+
/// https://github.com/rust-lang/cc-rs/pull/671
14+
fn emit_whole_archive_link_flags(lib_name: &str, is_cpp: bool) {
15+
println!("cargo:rustc-link-lib=static:+whole-archive={}", lib_name);
16+
println!(
17+
"cargo:rustc-link-search=native={}",
18+
std::env::var("OUT_DIR").expect("did not set OUT_DIR")
19+
);
20+
21+
if is_cpp {
22+
let cpp_stdlib = if let Ok(stdlib) = std::env::var("CXXSTDLIB") {
23+
if stdlib.is_empty() {
24+
None
25+
} else {
26+
Some(stdlib)
27+
}
28+
} else {
29+
let target = std::env::var("TARGET").expect("TARGET environment should be set");
30+
31+
// Equivalent to https://github.com/rust-lang/cc-rs/blob/53fb72c87e5769a299f1886ead831901b9c775d6/src/lib.rs#L2528
32+
if target.contains("msvc") {
33+
None
34+
} else if target.contains("apple") {
35+
Some("c++".to_string())
36+
} else if target.contains("freebsd") {
37+
Some("c++".to_string())
38+
} else if target.contains("openbsd") {
39+
Some("c++".to_string())
40+
} else if target.contains("android") {
41+
Some("c++_shared".to_string())
42+
} else {
43+
Some("stdc++".to_string())
44+
}
45+
};
46+
47+
if let Some(cpp_stdlib) = cpp_stdlib {
48+
println!("cargo:rustc-link-lib={}", cpp_stdlib);
49+
}
50+
}
51+
}
52+
1053
impl TreeSitterParser {
1154
fn build(&self) {
1255
let dir = PathBuf::from(&self.src_dir);
@@ -49,6 +92,10 @@ impl TreeSitterParser {
4992
for file in cpp_files {
5093
cpp_build.file(dir.join(file));
5194
}
95+
96+
cpp_build.cargo_metadata(false);
97+
emit_whole_archive_link_flags(&format!("{}-cpp", self.name), true);
98+
5299
cpp_build.compile(&format!("{}-cpp", self.name));
53100
}
54101

@@ -60,6 +107,10 @@ impl TreeSitterParser {
60107
for file in c_files {
61108
build.file(dir.join(file));
62109
}
110+
111+
build.cargo_metadata(false);
112+
emit_whole_archive_link_flags(self.name, false);
113+
63114
build.compile(self.name);
64115
}
65116
}

src/main.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@
1212
// It's common to have pairs foo_lhs and foo_rhs, leading to double
1313
// the number of arguments and triggering this lint.
1414
#![allow(clippy::too_many_arguments)]
15+
// Has false positives on else if chains that sometimes have the same
16+
// body for readability.
17+
#![allow(clippy::clippy::if_same_then_else)]
1518

1619
mod constants;
1720
mod diff;

0 commit comments

Comments
 (0)