Skip to content

Commit 9814e83

Browse files
committed
Auto merge of #84124 - 12101111:libunwind, r=petrochenkov
libunwind fix and cleanup Fix: 1. "system-llvm-libunwind" now only skip build-script for linux target 2. workaround from #65972 is not needed, upstream fix it in llvm/llvm-project@68c5070 ( LLVM 11 ) 3. remove code for MSCV and Apple in `compile()`, as they are not used 4. fix #69222 , compile c files and cpp files in different config 5. fix conditional compilation for musl target. 6. fix that x86_64-fortanix-unknown-sgx don't link libunwind built in build-script into rlib
2 parents c4ec606 + 52a3365 commit 9814e83

File tree

4 files changed

+106
-76
lines changed

4 files changed

+106
-76
lines changed

config.toml.example

+8
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,14 @@ changelog-seen = 2
563563

564564
# Use LLVM libunwind as the implementation for Rust's unwinder.
565565
# Accepted values are 'in-tree' (formerly true), 'system' or 'no' (formerly false).
566+
# This option only applies for Linux and Fuchsia targets.
567+
# On Linux target, if crt-static is not enabled, 'no' means dynamic link to
568+
# `libgcc_s.so`, 'in-tree' means static link to the in-tree build of llvm libunwind
569+
# and 'system' means dynamic link to `libunwind.so`. If crt-static is enabled,
570+
# the behavior is depend on the libc. On musl target, 'no' and 'in-tree' both
571+
# means static link to the in-tree build of llvm libunwind, and 'system' means
572+
# static link to `libunwind.a` provided by system. Due to the limitation of glibc,
573+
# it must link to `libgcc_eh.a` to get a working output, and this option have no effect.
566574
#llvm-libunwind = 'no'
567575

568576
# Enable Windows Control Flow Guard checks in the standard library.

library/unwind/Cargo.toml

+7
Original file line numberDiff line numberDiff line change
@@ -24,5 +24,12 @@ cfg-if = "0.1.8"
2424
cc = "1.0.68"
2525

2626
[features]
27+
28+
# Only applies for Linux and Fuchsia targets
29+
# Static link to the in-tree build of llvm libunwind
2730
llvm-libunwind = []
31+
32+
# Only applies for Linux and Fuchsia targets
33+
# If crt-static is enabled, static link to `libunwind.a` provided by system
34+
# If crt-static is disabled, dynamic link to `libunwind.so` provided by system
2835
system-llvm-libunwind = []

library/unwind/build.rs

+74-72
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@ fn main() {
44
println!("cargo:rerun-if-changed=build.rs");
55
let target = env::var("TARGET").expect("TARGET was not set");
66

7-
if cfg!(feature = "system-llvm-libunwind") {
7+
if cfg!(target_os = "linux") && cfg!(feature = "system-llvm-libunwind") {
8+
// linking for Linux is handled in lib.rs
89
return;
910
}
1011

@@ -57,101 +58,102 @@ mod llvm_libunwind {
5758
pub fn compile() {
5859
let target = env::var("TARGET").expect("TARGET was not set");
5960
let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap();
60-
let target_vendor = env::var("CARGO_CFG_TARGET_VENDOR").unwrap();
61-
let target_endian_little = env::var("CARGO_CFG_TARGET_ENDIAN").unwrap() != "big";
62-
let cfg = &mut cc::Build::new();
63-
64-
cfg.cpp(true);
65-
cfg.cpp_set_stdlib(None);
66-
cfg.warnings(false);
61+
let mut cc_cfg = cc::Build::new();
62+
let mut cpp_cfg = cc::Build::new();
63+
let root = Path::new("../../src/llvm-project/libunwind");
6764

68-
// libunwind expects a __LITTLE_ENDIAN__ macro to be set for LE archs, cf. #65765
69-
if target_endian_little {
70-
cfg.define("__LITTLE_ENDIAN__", Some("1"));
65+
cpp_cfg.cpp(true);
66+
cpp_cfg.cpp_set_stdlib(None);
67+
cpp_cfg.flag("-nostdinc++");
68+
cpp_cfg.flag("-fno-exceptions");
69+
cpp_cfg.flag("-fno-rtti");
70+
cpp_cfg.flag_if_supported("-fvisibility-global-new-delete-hidden");
71+
72+
// Don't set this for clang
73+
// By default, Clang builds C code in GNU C17 mode.
74+
// By default, Clang builds C++ code according to the C++98 standard,
75+
// with many C++11 features accepted as extensions.
76+
if cpp_cfg.get_compiler().is_like_gnu() {
77+
cpp_cfg.flag("-std=c++11");
78+
cc_cfg.flag("-std=c99");
7179
}
7280

73-
if target_env == "msvc" {
74-
// Don't pull in extra libraries on MSVC
75-
cfg.flag("/Zl");
76-
cfg.flag("/EHsc");
77-
cfg.define("_CRT_SECURE_NO_WARNINGS", None);
78-
cfg.define("_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS", None);
79-
} else if target.contains("x86_64-fortanix-unknown-sgx") {
80-
cfg.cpp(false);
81-
82-
cfg.static_flag(true);
83-
cfg.opt_level(3);
84-
85-
cfg.flag("-nostdinc++");
86-
cfg.flag("-fno-exceptions");
87-
cfg.flag("-fno-rtti");
88-
cfg.flag("-fstrict-aliasing");
89-
cfg.flag("-funwind-tables");
90-
cfg.flag("-fvisibility=hidden");
91-
cfg.flag("-fno-stack-protector");
92-
cfg.flag("-ffreestanding");
93-
cfg.flag("-fexceptions");
94-
95-
// easiest way to undefine since no API available in cc::Build to undefine
96-
cfg.flag("-U_FORTIFY_SOURCE");
97-
cfg.define("_FORTIFY_SOURCE", "0");
98-
99-
cfg.flag_if_supported("-fvisibility-global-new-delete-hidden");
81+
if target.contains("x86_64-fortanix-unknown-sgx") || target_env == "musl" {
82+
// use the same GCC C compiler command to compile C++ code so we do not need to setup the
83+
// C++ compiler env variables on the builders.
84+
// Don't set this for clang++, as clang++ is able to compile this without libc++.
85+
if cpp_cfg.get_compiler().is_like_gnu() {
86+
cpp_cfg.cpp(false);
87+
}
88+
}
10089

101-
cfg.define("_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS", None);
102-
cfg.define("RUST_SGX", "1");
103-
cfg.define("__NO_STRING_INLINES", None);
104-
cfg.define("__NO_MATH_INLINES", None);
105-
cfg.define("_LIBUNWIND_IS_BAREMETAL", None);
106-
cfg.define("__LIBUNWIND_IS_NATIVE_ONLY", None);
107-
cfg.define("NDEBUG", None);
108-
} else {
109-
cfg.flag("-std=c99");
110-
cfg.flag("-std=c++11");
111-
cfg.flag("-nostdinc++");
112-
cfg.flag("-fno-exceptions");
113-
cfg.flag("-fno-rtti");
90+
for cfg in [&mut cc_cfg, &mut cpp_cfg].iter_mut() {
91+
cfg.warnings(false);
11492
cfg.flag("-fstrict-aliasing");
11593
cfg.flag("-funwind-tables");
11694
cfg.flag("-fvisibility=hidden");
117-
cfg.flag_if_supported("-fvisibility-global-new-delete-hidden");
11895
cfg.define("_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS", None);
96+
cfg.include(root.join("include"));
97+
cfg.cargo_metadata(false);
98+
99+
if target.contains("x86_64-fortanix-unknown-sgx") {
100+
cfg.static_flag(true);
101+
cfg.opt_level(3);
102+
cfg.flag("-fno-stack-protector");
103+
cfg.flag("-ffreestanding");
104+
cfg.flag("-fexceptions");
105+
106+
// easiest way to undefine since no API available in cc::Build to undefine
107+
cfg.flag("-U_FORTIFY_SOURCE");
108+
cfg.define("_FORTIFY_SOURCE", "0");
109+
cfg.define("RUST_SGX", "1");
110+
cfg.define("__NO_STRING_INLINES", None);
111+
cfg.define("__NO_MATH_INLINES", None);
112+
cfg.define("_LIBUNWIND_IS_BAREMETAL", None);
113+
cfg.define("__LIBUNWIND_IS_NATIVE_ONLY", None);
114+
cfg.define("NDEBUG", None);
115+
}
119116
}
120117

121-
let mut unwind_sources = vec![
122-
"Unwind-EHABI.cpp",
123-
"Unwind-seh.cpp",
118+
let mut c_sources = vec![
124119
"Unwind-sjlj.c",
125120
"UnwindLevel1-gcc-ext.c",
126121
"UnwindLevel1.c",
127122
"UnwindRegistersRestore.S",
128123
"UnwindRegistersSave.S",
129-
"libunwind.cpp",
130124
];
131125

132-
if target_vendor == "apple" {
133-
unwind_sources.push("Unwind_AppleExtras.cpp");
134-
}
126+
let cpp_sources = vec!["Unwind-EHABI.cpp", "Unwind-seh.cpp", "libunwind.cpp"];
127+
let cpp_len = cpp_sources.len();
135128

136129
if target.contains("x86_64-fortanix-unknown-sgx") {
137-
unwind_sources.push("UnwindRustSgx.c");
130+
c_sources.push("UnwindRustSgx.c");
138131
}
139132

140-
let root = Path::new("../../src/llvm-project/libunwind");
141-
cfg.include(root.join("include"));
142-
for src in unwind_sources {
143-
cfg.file(root.join("src").join(src));
133+
for src in c_sources {
134+
cc_cfg.file(root.join("src").join(src).canonicalize().unwrap());
144135
}
145136

146-
if target_env == "musl" {
147-
// use the same C compiler command to compile C++ code so we do not need to setup the
148-
// C++ compiler env variables on the builders
149-
cfg.cpp(false);
150-
// linking for musl is handled in lib.rs
151-
cfg.cargo_metadata(false);
152-
println!("cargo:rustc-link-search=native={}", env::var("OUT_DIR").unwrap());
137+
for src in cpp_sources {
138+
cpp_cfg.file(root.join("src").join(src).canonicalize().unwrap());
153139
}
154140

155-
cfg.compile("unwind");
141+
let out_dir = env::var("OUT_DIR").unwrap();
142+
println!("cargo:rustc-link-search=native={}", &out_dir);
143+
144+
cpp_cfg.compile("unwind-cpp");
145+
146+
let mut count = 0;
147+
for entry in std::fs::read_dir(&out_dir).unwrap() {
148+
let obj = entry.unwrap().path().canonicalize().unwrap();
149+
if let Some(ext) = obj.extension() {
150+
if ext == "o" {
151+
cc_cfg.object(&obj);
152+
count += 1;
153+
}
154+
}
155+
}
156+
assert_eq!(cpp_len, count, "Can't get object files from {:?}", &out_dir);
157+
cc_cfg.compile("unwind");
156158
}
157159
}

library/unwind/src/lib.rs

+17-4
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,22 @@ cfg_if::cfg_if! {
3737
}
3838

3939
#[cfg(target_env = "musl")]
40-
#[link(name = "unwind", kind = "static", cfg(target_feature = "crt-static"))]
41-
#[link(name = "gcc_s", cfg(not(target_feature = "crt-static")))]
42-
extern "C" {}
40+
cfg_if::cfg_if! {
41+
if #[cfg(all(feature = "llvm-libunwind", feature = "system-llvm-libunwind"))] {
42+
compile_error!("`llvm-libunwind` and `system-llvm-libunwind` cannot be enabled at the same time");
43+
} else if #[cfg(feature = "llvm-libunwind")] {
44+
#[link(name = "unwind", kind = "static")]
45+
extern "C" {}
46+
} else if #[cfg(feature = "system-llvm-libunwind")] {
47+
#[link(name = "unwind", kind = "static-nobundle", cfg(target_feature = "crt-static"))]
48+
#[link(name = "unwind", cfg(not(target_feature = "crt-static")))]
49+
extern "C" {}
50+
} else {
51+
#[link(name = "unwind", kind = "static", cfg(target_feature = "crt-static"))]
52+
#[link(name = "gcc_s", cfg(not(target_feature = "crt-static")))]
53+
extern "C" {}
54+
}
55+
}
4356

4457
// When building with crt-static, we get `gcc_eh` from the `libc` crate, since
4558
// glibc needs it, and needs it listed later on the linker command line. We
@@ -68,5 +81,5 @@ extern "C" {}
6881
extern "C" {}
6982

7083
#[cfg(all(target_vendor = "fortanix", target_env = "sgx"))]
71-
#[link(name = "unwind", kind = "static-nobundle")]
84+
#[link(name = "unwind", kind = "static")]
7285
extern "C" {}

0 commit comments

Comments
 (0)