forked from NordSecurity/libtelio
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbuild.rs
152 lines (137 loc) · 5.08 KB
/
build.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
use anyhow::{anyhow, Context, Result};
use std::{
collections::HashSet,
env,
fs::File,
io::{self, BufRead, BufReader},
iter::FromIterator,
path::Path,
};
fn build() -> Result<cc::Build> {
let target_os = env::var("CARGO_CFG_TARGET_OS")?;
let mut build = cc::Build::new();
if target_os == "windows" {
// -lssp is required when source fortification is enabled for Windows. Since -lssp is a
// dynamic library, its very undesirable and right now I'm not in the mood to try and
// find a proper solution. So just skip source fortification for Windows for now.
// https://github.com/msys2/MINGW-packages/issues/5868
} else {
build.flag("-D_FORTIFY_SOURCE=2");
}
Ok(build)
}
fn lines_from_file(filename: &str) -> io::Result<Vec<String>> {
BufReader::new(File::open(filename)?).lines().collect()
}
fn abspath(path: &str) -> Option<String> {
let can_path = std::fs::canonicalize(path).ok()?;
can_path.into_os_string().into_string().ok()
}
// Compile bindings file and enforce bindings export
fn compile_and_enforce_bindings_export(target_os: &str, lang_wrapper: &str) -> Result<()> {
let path = format!(
"ffi/bindings/{target_os}/wrap/{lang_wrapper}.c",
target_os = target_os,
lang_wrapper = lang_wrapper
);
println!("cargo:rerun-if-changed={}", &path);
build()?.file(&path).compile(lang_wrapper);
// For Microsoft link.exe, each exported function must be specified via /export: option.
// For GNU LD, a structured list of exported functions must be passed in a file via --dynamic-list= option.
if cfg!(target_env = "msvc") {
let exports_list_msvc = format!(
"ffi/bindings/{target_os}/wrap/{lang_wrapper}.msvc_exports.lst",
target_os = target_os,
lang_wrapper = lang_wrapper
);
if Path::new(&exports_list_msvc).exists() {
let exported_symbols = lines_from_file(&exports_list_msvc)
.with_context(|| format!("Could not find {}", exports_list_msvc))?;
for export_sym in exported_symbols {
println!("cargo:rustc-link-arg=/export:{}", export_sym);
}
}
} else {
let exports_list_gnuld = format!(
"ffi/bindings/{target_os}/wrap/{lang_wrapper}.gnuld_exports.lst",
target_os = target_os,
lang_wrapper = lang_wrapper
);
// LD requires an absolute path here. Also, LD does not accept empty structures!
// If no additional exports are required, such as with Linux and Golang, then don't pass a --dynamic-list!
if Path::new(&exports_list_gnuld).exists() {
println!(
"cargo:rustc-link-arg=-Wl,--dynamic-list={}",
abspath(&exports_list_gnuld).ok_or_else(|| anyhow!(
"failed to get absolute path for '{}'",
exports_list_gnuld
))?
);
}
}
if target_os == "android" {
println!(
"cargo:rustc-link-arg=-Wl,--whole-archive -l{}",
lang_wrapper
);
}
Ok(())
}
fn main() -> Result<()> {
let target_os = env::var("CARGO_CFG_TARGET_OS")?;
let langs: HashSet<&str> = HashSet::from_iter(["GO", "JAVA", "CS"].iter().copied());
let ffis = env::var("FFI").unwrap_or_default();
let mut ffi: HashSet<&str> = ffis.split(',').filter(|c| langs.contains(c)).collect();
if ffi.is_empty() {
match &*target_os {
"linux" => {
ffi.insert("GO");
}
"android" => {
ffi.insert("JAVA");
}
"windows" => {
ffi.insert("CS");
}
_ => (),
};
}
#[cfg(not(tarpaulin))] // GO FFI fails to compile for tarpaulin (its not needed)
if ffi.contains(&"GO") {
compile_and_enforce_bindings_export(&target_os, "go_wrap")?;
}
if ffi.contains(&"JAVA") {
compile_and_enforce_bindings_export(&target_os, "java_wrap")?;
}
if ffi.contains(&"CS") {
compile_and_enforce_bindings_export(&target_os, "csharp_wrap")?;
}
{
let path = "suppress_source_fortification_check.c";
println!("cargo:rerun-if-changed={}", &path);
// The culprit for breaking the MSVC build is "-Werror", because cl.exe requires a numeric parameter.
if cfg!(target_env = "msvc") {
build()?
.file(path)
.compile("suppressSourceFortificationCheck");
} else {
build()?
.file(path)
.flag("-Werror")
.flag("-O3")
.compile("suppressSourceFortificationCheck");
}
}
if target_os == "android" {
let pkg_name = env!("CARGO_PKG_NAME");
let soname = format!("lib{}.so", pkg_name);
println!("cargo:rustc-cdylib-link-arg=-Wl,-soname,{}", soname);
}
#[cfg(windows)]
if target_os == "windows" {
winres::WindowsResource::new()
.set("LegalCopyright", "Nord Security")
.compile()?;
}
Ok(())
}