]> git.lizzy.rs Git - rust.git/blob - library/unwind/build.rs
0529d24a27408002b3b36c500c9b87b8cd925d62
[rust.git] / library / unwind / build.rs
1 use std::env;
2
3 fn main() {
4     println!("cargo:rerun-if-changed=build.rs");
5     let target = env::var("TARGET").expect("TARGET was not set");
6
7     if cfg!(target_os = "linux") && cfg!(feature = "system-llvm-libunwind") {
8         // linking for Linux is handled in lib.rs
9         return;
10     }
11
12     if cfg!(feature = "llvm-libunwind")
13         && ((target.contains("linux") && !target.contains("musl")) || target.contains("fuchsia"))
14     {
15         // Build the unwinding from libunwind C/C++ source code.
16         llvm_libunwind::compile();
17     } else if target.contains("x86_64-fortanix-unknown-sgx") {
18         llvm_libunwind::compile();
19     } else if target.contains("linux") {
20         // linking for Linux is handled in lib.rs
21         if target.contains("musl") {
22             llvm_libunwind::compile();
23         } else if target.contains("android") {
24             let build = cc::Build::new();
25
26             // Since ndk r23 beta 3 `libgcc` was replaced with `libunwind` thus
27             // check if we have `libunwind` available and if so use it. Otherwise
28             // fall back to `libgcc` to support older ndk versions.
29             let has_unwind =
30                 build.is_flag_supported("-lunwind").expect("Unable to invoke compiler");
31
32             if has_unwind {
33                 println!("cargo:rustc-link-lib=unwind");
34             } else {
35                 println!("cargo:rustc-link-lib=gcc");
36             }
37         }
38     } else if target.contains("freebsd") {
39         println!("cargo:rustc-link-lib=gcc_s");
40     } else if target.contains("netbsd") {
41         println!("cargo:rustc-link-lib=gcc_s");
42     } else if target.contains("openbsd") {
43         if target.contains("sparc64") {
44             println!("cargo:rustc-link-lib=gcc");
45         } else {
46             println!("cargo:rustc-link-lib=c++abi");
47         }
48     } else if target.contains("solaris") {
49         println!("cargo:rustc-link-lib=gcc_s");
50     } else if target.contains("illumos") {
51         println!("cargo:rustc-link-lib=gcc_s");
52     } else if target.contains("dragonfly") {
53         println!("cargo:rustc-link-lib=gcc_pic");
54     } else if target.contains("pc-windows-gnu") {
55         // This is handled in the target spec with late_link_args_[static|dynamic]
56     } else if target.contains("uwp-windows-gnu") {
57         println!("cargo:rustc-link-lib=unwind");
58     } else if target.contains("fuchsia") {
59         println!("cargo:rustc-link-lib=unwind");
60     } else if target.contains("haiku") {
61         println!("cargo:rustc-link-lib=gcc_s");
62     } else if target.contains("redox") {
63         // redox is handled in lib.rs
64     }
65 }
66
67 mod llvm_libunwind {
68     use std::env;
69     use std::path::Path;
70
71     /// Compile the libunwind C/C++ source code.
72     pub fn compile() {
73         let target = env::var("TARGET").expect("TARGET was not set");
74         let target_env = env::var("CARGO_CFG_TARGET_ENV").unwrap();
75         let mut cc_cfg = cc::Build::new();
76         let mut cpp_cfg = cc::Build::new();
77         let root = Path::new("../../src/llvm-project/libunwind");
78
79         cpp_cfg.cpp(true);
80         cpp_cfg.cpp_set_stdlib(None);
81         cpp_cfg.flag("-nostdinc++");
82         cpp_cfg.flag("-fno-exceptions");
83         cpp_cfg.flag("-fno-rtti");
84         cpp_cfg.flag_if_supported("-fvisibility-global-new-delete-hidden");
85
86         // Don't set this for clang
87         // By default, Clang builds C code in GNU C17 mode.
88         // By default, Clang builds C++ code according to the C++98 standard,
89         // with many C++11 features accepted as extensions.
90         if cpp_cfg.get_compiler().is_like_gnu() {
91             cpp_cfg.flag("-std=c++11");
92             cc_cfg.flag("-std=c99");
93         }
94
95         if target.contains("x86_64-fortanix-unknown-sgx") || target_env == "musl" {
96             // use the same GCC C compiler command to compile C++ code so we do not need to setup the
97             // C++ compiler env variables on the builders.
98             // Don't set this for clang++, as clang++ is able to compile this without libc++.
99             if cpp_cfg.get_compiler().is_like_gnu() {
100                 cpp_cfg.cpp(false);
101             }
102         }
103
104         for cfg in [&mut cc_cfg, &mut cpp_cfg].iter_mut() {
105             cfg.warnings(false);
106             cfg.flag("-fstrict-aliasing");
107             cfg.flag("-funwind-tables");
108             cfg.flag("-fvisibility=hidden");
109             cfg.define("_LIBUNWIND_DISABLE_VISIBILITY_ANNOTATIONS", None);
110             cfg.include(root.join("include"));
111             cfg.cargo_metadata(false);
112
113             if target.contains("x86_64-fortanix-unknown-sgx") {
114                 cfg.static_flag(true);
115                 cfg.opt_level(3);
116                 cfg.flag("-fno-stack-protector");
117                 cfg.flag("-ffreestanding");
118                 cfg.flag("-fexceptions");
119
120                 // easiest way to undefine since no API available in cc::Build to undefine
121                 cfg.flag("-U_FORTIFY_SOURCE");
122                 cfg.define("_FORTIFY_SOURCE", "0");
123                 cfg.define("RUST_SGX", "1");
124                 cfg.define("__NO_STRING_INLINES", None);
125                 cfg.define("__NO_MATH_INLINES", None);
126                 cfg.define("_LIBUNWIND_IS_BAREMETAL", None);
127                 cfg.define("__LIBUNWIND_IS_NATIVE_ONLY", None);
128                 cfg.define("NDEBUG", None);
129             }
130         }
131
132         let mut c_sources = vec![
133             "Unwind-sjlj.c",
134             "UnwindLevel1-gcc-ext.c",
135             "UnwindLevel1.c",
136             "UnwindRegistersRestore.S",
137             "UnwindRegistersSave.S",
138         ];
139
140         let cpp_sources = vec!["Unwind-EHABI.cpp", "Unwind-seh.cpp", "libunwind.cpp"];
141         let cpp_len = cpp_sources.len();
142
143         if target.contains("x86_64-fortanix-unknown-sgx") {
144             c_sources.push("UnwindRustSgx.c");
145         }
146
147         for src in c_sources {
148             cc_cfg.file(root.join("src").join(src).canonicalize().unwrap());
149         }
150
151         for src in cpp_sources {
152             cpp_cfg.file(root.join("src").join(src).canonicalize().unwrap());
153         }
154
155         let out_dir = env::var("OUT_DIR").unwrap();
156         println!("cargo:rustc-link-search=native={}", &out_dir);
157
158         cpp_cfg.compile("unwind-cpp");
159
160         let mut count = 0;
161         for entry in std::fs::read_dir(&out_dir).unwrap() {
162             let obj = entry.unwrap().path().canonicalize().unwrap();
163             if let Some(ext) = obj.extension() {
164                 if ext == "o" {
165                     cc_cfg.object(&obj);
166                     count += 1;
167                 }
168             }
169         }
170         assert_eq!(cpp_len, count, "Can't get object files from {:?}", &out_dir);
171         cc_cfg.compile("unwind");
172     }
173 }