Skip to content
This repository has been archived by the owner on Jun 10, 2024. It is now read-only.

Commit

Permalink
chore: update libunwind; link appropriate libs in linker
Browse files Browse the repository at this point in the history
  • Loading branch information
bitwalker committed Feb 27, 2023
1 parent 6d51d5c commit 8ffa27b
Show file tree
Hide file tree
Showing 39 changed files with 5,163 additions and 1,965 deletions.
1 change: 0 additions & 1 deletion Cargo.lock

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

28 changes: 26 additions & 2 deletions compiler/linker/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -208,20 +208,31 @@ impl ProjectInfo {
platform_libs.extend_from_slice(&[
("execinfo", NativeLibraryKind::Unspecified),
("pthread", NativeLibraryKind::Unspecified),
("gcc_s", NativeLibraryKind::Unspecified),
]);
} else if target_os == "netbsd" {
platform_libs.extend_from_slice(&[
("pthread", NativeLibraryKind::Unspecified),
("rt", NativeLibraryKind::Unspecified),
("gcc_s", NativeLibraryKind::Unspecified),
]);
} else if target_os == "dragonfly" {
platform_libs.extend_from_slice(&[
("pthread", NativeLibraryKind::Unspecified),
("gcc_pic", NativeLibraryKind::Unspecified),
]);
} else if target_os == "openbsd" {
platform_libs.extend_from_slice(&[
("pthread", NativeLibraryKind::Unspecified),
("c++abi", NativeLibraryKind::Unspecified),
]);
} else if target_os == "dragonfly" || target_os == "openbsd" {
platform_libs.extend_from_slice(&[("pthread", NativeLibraryKind::Unspecified)]);
} else if target_os == "solaris" {
platform_libs.extend_from_slice(&[
("socket", NativeLibraryKind::Unspecified),
("posix4", NativeLibraryKind::Unspecified),
("pthread", NativeLibraryKind::Unspecified),
("resolv", NativeLibraryKind::Unspecified),
("gcc_s", NativeLibraryKind::Unspecified),
]);
} else if target_os == "illumos" {
platform_libs.extend_from_slice(&[
Expand All @@ -232,6 +243,7 @@ impl ProjectInfo {
("nsl", NativeLibraryKind::Unspecified),
// Use libumem for the (malloc-compatible) allocator
("umem", NativeLibraryKind::Unspecified),
("gcc_s", NativeLibraryKind::Unspecified),
]);
} else if target_os == "macos" {
platform_libs.extend_from_slice(&[
Expand All @@ -258,12 +270,24 @@ impl ProjectInfo {
]);
} else if target_os == "linux" && target_env == "uclibc" {
platform_libs.extend_from_slice(&[("dl", NativeLibraryKind::Unspecified)]);
if !options.crt_static(Some(options.project_type)) {
platform_libs.extend_from_slice(&[("gcc_s", NativeLibraryKind::Unspecified)]);
}
} else if target_os == "linux" && target_env == "gnu" {
platform_libs.extend_from_slice(&[
("m", NativeLibraryKind::Unspecified),
("dl", NativeLibraryKind::Unspecified),
("pthread", NativeLibraryKind::Unspecified),
]);
if !options.crt_static(Some(options.project_type)) {
platform_libs.extend_from_slice(&[("gcc_s", NativeLibraryKind::Unspecified)]);
}
} else if target_os == "linux" && target_env == "musl" {
if !options.crt_static(Some(options.project_type)) {
platform_libs.extend_from_slice(&[("gcc_s", NativeLibraryKind::Unspecified)]);
} else {
platform_libs.extend_from_slice(&[("unwind", NativeLibraryKind::Unspecified)]);
}
}

for (name, kind) in platform_libs.drain(..) {
Expand Down
6 changes: 6 additions & 0 deletions compiler/unwind/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,13 @@ bench = false
doc = false

[features]
# Only applies for Linux and Fuchsia targets
# Static link to the in-tree build of LLVM libunwind
llvm-libunwind = []
# Only applies for Linux and Fuchsia targets
# If crt-static is enabled, static link to `libunwind.a` provided by system
# If crt-static is disabled, dynamic link to `libunwind.a` provided by system
system-llvm-libunwind = []

[dependencies]
cfg-if.workspace = true
Expand Down
228 changes: 107 additions & 121 deletions compiler/unwind/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,158 +4,144 @@ fn main() {
println!("cargo:rerun-if-changed=build.rs");
let target = env::var("TARGET").expect("TARGET was not set");

if cfg!(feature = "llvm-libunwind")
&& ((target.contains("linux") && !target.contains("musl")) || target.contains("fuchsia"))
{
// Build the unwinding from libunwind C/C++ source code.
llvm_libunwind::compile();
} else if target.contains("x86_64-fortanix-unknown-sgx") {
llvm_libunwind::compile();
} else if target.contains("linux") {
if target.contains("musl") {
// linking for musl is handled in lib.rs
llvm_libunwind::compile();
} else if !target.contains("android") {
println!("cargo:rustc-link-lib=gcc_s");
}
} else if target.contains("freebsd") {
println!("cargo:rustc-link-lib=gcc_s");
} else if target.contains("rumprun") {
println!("cargo:rustc-link-lib=unwind");
} else if target.contains("netbsd") {
println!("cargo:rustc-link-lib=gcc_s");
} else if target.contains("openbsd") {
if target.contains("sparc64") {
println!("cargo:rustc-link-lib=gcc");
} else {
println!("cargo:rustc-link-lib=c++abi");
llvm_libunwind::compile();

if target.contains("android") {
let build = cc::Build::new();

// Since ndk r23 beta 3 `libgcc` was replaced with `libunwind` thus
// check if we have `libunwind` available and if so use it. Otherwise
// fall back to `libgcc` to support older ndk versions.
let has_unwind = build
.is_flag_supported("-lunwind")
.expect("Unable to invoke compiler");

if has_unwind {
println!("cargo:rustc-cfg=feature=\"system-llvm-libunwind\"");
}
} else if target.contains("solaris") {
println!("cargo:rustc-link-lib=gcc_s");
} else if target.contains("illumos") {
println!("cargo:rustc-link-lib=gcc_s");
} else if target.contains("dragonfly") {
println!("cargo:rustc-link-lib=gcc_pic");
} else if target.contains("pc-windows-gnu") {
// This is handled in the target spec with late_link_args_[static|dynamic]
} else if target.contains("uwp-windows-gnu") {
println!("cargo:rustc-link-lib=unwind");
} else if target.contains("fuchsia") {
println!("cargo:rustc-link-lib=unwind");
} else if target.contains("haiku") {
println!("cargo:rustc-link-lib=gcc_s");
} else if target.contains("redox") {
// redox is handled in lib.rs
} else if target.contains("cloudabi") {
println!("cargo:rustc-link-lib=unwind");
}
}

mod llvm_libunwind {
use std::env;
use std::ffi::OsStr;
use std::fs;

/// Compile the libunwind C/C++ source code.
pub fn compile() {
let target = env::var("TARGET").expect("TARGET was not set");
let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap();
let target_vendor = env::var("CARGO_CFG_TARGET_VENDOR").unwrap();
let target_endian_little = env::var("CARGO_CFG_TARGET_ENDIAN").unwrap() != "big";
let cfg = &mut cc::Build::new();

cfg.cpp(true);
cfg.cpp_set_stdlib(None);
cfg.warnings(false);

// libunwind expects a __LITTLE_ENDIAN__ macro to be set for LE archs, cf. #65765
if target_endian_little {
cfg.define("__LITTLE_ENDIAN__", Some("1"));
}
let cwd = env::current_dir().unwrap();
let out_dir = env::var("OUT_DIR").unwrap();

if env::var("LUMEN_LLVM_LTO").unwrap_or("OFF".to_string()) == "ON" {
cfg.flag("-flto=thin");
}
let mut cc_cfg = cc::Build::new();
let mut cpp_cfg = cc::Build::new();

if target_env == "msvc" {
// Don't pull in extra libraries on MSVC
cfg.flag("/Zl");
cfg.flag("/EHsc");
cfg.define("_CRT_SECURE_NO_WARNINGS", None);
cfg.define("_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS", None);
} else if target.contains("x86_64-fortanix-unknown-sgx") {
cfg.cpp(false);
cpp_cfg.cpp(true);
cpp_cfg.cpp_set_stdlib(None);
cpp_cfg.flag("-nostdinc++");
cpp_cfg.flag("-fno-exceptions");
cpp_cfg.flag("-fno-rtti");
cpp_cfg.flag_if_supported("-fvisibility-global-new-delete-hidden");

cfg.static_flag(true);
for cfg in [&mut cc_cfg, &mut cpp_cfg].iter_mut() {
cfg.warnings(false);
cfg.debug(false);
cfg.opt_level(3);

cfg.flag("-nostdinc++");
cfg.flag("-fno-exceptions");
cfg.flag("-fno-rtti");
cfg.flag("-fstrict-aliasing");
cfg.flag("-funwind-tables");
cfg.flag("-fvisibility=hidden");
cfg.flag("-fno-stack-protector");
cfg.flag("-ffreestanding");
cfg.flag("-fexceptions");
cfg.flag_if_supported("-fvisibility-hidden");
cfg.define("_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS", None);
cfg.include(cwd.join("c_src/include"));
cfg.cargo_metadata(false);

// easiest way to undefine since no API available in cc::Build to undefine
cfg.flag("-U_FORTIFY_SOURCE");
cfg.define("_FORTIFY_SOURCE", "0");
if target.contains("x86_64-fortanix-unknown-sgx") {
cfg.static_flag(true);
cfg.flag("-fno-stack-protector");
cfg.flag("-ffreestanding");
cfg.flag("-fexceptions");

// easiest way to undefine since no API available in cc::Build to undefine
cfg.flag("-U_FORTIFY_SOURCE");
cfg.define("_FORTIFY_SOURCE", "0");
cfg.define("RUST_SGX", "1");
cfg.define("__NO_STRING_INLINES", None);
cfg.define("__NO_MATH_INLINES", None);
cfg.define("_LIBUNWIND_IS_BAREMETAL", None);
cfg.define("__LIBUNWIND_IS_NATIVE_ONLY", None);
cfg.define("NDEBUG", None);
}
if target.contains("windows") {
cfg.define("_LIBUNWIND_HIDE_SYMBOLS", "1");
cfg.define("_LIBUNWIND_IS_NATIVE_ONLY", "1");
}
}

cfg.flag_if_supported("-fvisibility-global-new-delete-hidden");
// Don't set this for clang
// By default, Clang builds C code in GNU C17 mode.
// By default, Clang builds C++ code according to the C++98 standard,
// with many C++11 features accepted as extensions.
if cc_cfg.get_compiler().is_like_gnu() {
cc_cfg.flag("-std=c99");
}
if cpp_cfg.get_compiler().is_like_gnu() {
cpp_cfg.flag("-std=c++11");
}

cfg.define("_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS", None);
cfg.define("RUST_SGX", "1");
cfg.define("__NO_STRING_INLINES", None);
cfg.define("__NO_MATH_INLINES", None);
cfg.define("_LIBUNWIND_IS_BAREMETAL", None);
cfg.define("__LIBUNWIND_IS_NATIVE_ONLY", None);
cfg.define("NDEBUG", None);
} else {
cfg.flag("-std=c99");
cfg.flag("-std=c++11");
cfg.flag("-nostdinc++");
cfg.flag("-fno-exceptions");
cfg.flag("-fno-rtti");
cfg.flag("-fstrict-aliasing");
cfg.flag("-funwind-tables");
cfg.flag("-fvisibility=hidden");
cfg.flag_if_supported("-fvisibility-global-new-delete-hidden");
cfg.define("_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS", None);
if target.contains("x86_64-fortanix-unknown-sgx") || target.contains("musl") {
// use the same GCC C compiler command to compile C++ code so we do not need to setup the
// C++ compiler env variables on the builders.
// Don't set this for clang++, as clang++ is able to compile this without libc++.
if cpp_cfg.get_compiler().is_like_gnu() {
cpp_cfg.cpp(false);
cpp_cfg.compiler(cc_cfg.get_compiler().path());
}
}

let mut unwind_sources = vec![
"Unwind-EHABI.cpp",
"Unwind-seh.cpp",
let c_sources = vec![
"Unwind-sjlj.c",
"UnwindLevel1-gcc-ext.c",
"UnwindLevel1.c",
"UnwindRegistersRestore.S",
"UnwindRegistersSave.S",
"libunwind.cpp",
];

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

let cwd = env::current_dir().unwrap();
cfg.include(cwd.join("c_src/include"));
for src in unwind_sources {
cfg.file(cwd.join("c_src").join(src));
for src in c_sources.iter() {
cc_cfg.file(cwd.join("c_src").join(src).canonicalize().unwrap());
}
for src in cpp_sources.iter() {
cpp_cfg.file(cwd.join("c_src").join(src).canonicalize().unwrap());
}

if target_env == "musl" {
// use the same C compiler command to compile C++ code so we do not need to setup the
// C++ compiler env variables on the builders
cfg.cpp(false);
// linking for musl is handled in lib.rs
cfg.cargo_metadata(false);
println!(
"cargo:rustc-link-search=native={}",
env::var("OUT_DIR").unwrap()
);
cpp_cfg.compile("unwind-cpp");

// FIXME: https://github.com/alexcrichton/cc-rs/issues/545#issuecomment-679242845
let mut count = 0;
for entry in fs::read_dir(&out_dir).unwrap() {
let file = entry.unwrap().path().canonicalize().unwrap();
if file.is_file() && file.extension() == Some(OsStr::new("o")) {
// file name starts with "<unique-prefix>-Unwind-EHABI", "<unique-prefix>-Unwind-seh" or "<unique-prefix>-libunwind"
let (_prefix, file_name) = file
.file_name()
.unwrap()
.to_str()
.expect("UTF-8 file name")
.split_once('-')
.unwrap();
if cpp_sources
.iter()
.any(|f| file_name.starts_with(&f[..f.len() - 4]))
{
cc_cfg.object(&file);
count += 1;
}
}
}
assert_eq!(cpp_len, count, "Can't get object files from {:?}", &out_dir);

cc_cfg.compile("unwind");

cfg.compile("unwind");
println!("cargo:rustc-link-search=native={}", out_dir);
}
}
Loading

0 comments on commit 8ffa27b

Please sign in to comment.