-
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathbuild.rs
More file actions
130 lines (116 loc) · 4.36 KB
/
Copy pathbuild.rs
File metadata and controls
130 lines (116 loc) · 4.36 KB
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
use std::{env, path::PathBuf};
#[cfg(feature = "re2c")]
use std::{
fs::File,
process::{Command, Stdio},
};
use bindgen::builder;
fn main() {
let out_dir = env::var("OUT_DIR").unwrap();
let out_path = PathBuf::from(out_dir.clone());
// Check if we're building for a musl target (Alpine Linux)
let target = env::var("TARGET").unwrap_or_default();
let is_musl = target.contains("musl");
if is_musl {
// Use pregenerated bindings for musl targets to avoid bindgen issues
// with Alpine's statically-linked Rust toolchain
std::fs::copy("pregenerated/bindings.rs", out_path.join("bindings.rs"))
.expect("failed to copy pregenerated bindings.rs");
} else {
// Generate bindings at build time for other targets
let bindings = builder()
.header("ext/timelib/timelib.h")
.allowlist_var("TIMELIB_ZONETYPE_ID")
.allowlist_var("TIMELIB_NO_CLONE")
.allowlist_function("timelib_builtin_db")
.allowlist_function("timelib_error_container_dtor")
.allowlist_function("timelib_fill_holes")
.allowlist_function("timelib_parse_tzfile")
.allowlist_function("timelib_strtotime")
.allowlist_function("timelib_time_ctor")
.allowlist_function("timelib_time_dtor")
.allowlist_function("timelib_tzinfo_dtor")
.allowlist_function("timelib_unixtime2local")
.allowlist_function("timelib_update_ts")
.header("shim/shim.h")
.allowlist_function("timelib_tz_get_wrapper_cached")
.generate()
.expect("failed to run bindgen");
bindings
.write_to_file(out_path.join("bindings.rs"))
.expect("failed to write bindings.rs");
}
// run re2c on 2 files
#[cfg(feature = "re2c")]
re2c("parse_date", &out_path);
#[cfg(feature = "re2c")]
re2c("parse_iso_intervals", &out_path);
let src = [
"ext/timelib/astro.c",
"ext/timelib/dow.c",
"ext/timelib/interval.c",
"ext/timelib/parse_posix.c",
"ext/timelib/parse_tz.c",
"ext/timelib/parse_zoneinfo.c",
"ext/timelib/timelib.c",
"ext/timelib/tm2unixtime.c",
"ext/timelib/unixtime2tm.c",
// files generated from re2c:
#[cfg(feature = "re2c")]
&format!("{}/parse_date.c", out_dir.clone()),
#[cfg(feature = "re2c")]
&format!("{}/parse_iso_intervals.c", out_dir.clone()),
#[cfg(not(feature = "re2c"))]
"pregenerated/parse_date.c",
#[cfg(not(feature = "re2c"))]
"pregenerated/parse_iso_intervals.c",
"shim/shim.c",
];
let mut builder = cc::Build::new();
let mut build = builder
.files(src.iter())
.include("ext/timelib")
.include("ext/hashmap.h")
// taken from Makefile
.flag("-Wall")
.define("HAVE_STDINT_H", None)
.define("HAVE_GETTIMEOFDAY", None);
if env::var_os("CARGO_CFG_WINDOWS").is_some() {
build = build.define("HAVE_IO_H", None);
} else {
// extra parameters to use in non-Windows
println!("cargo:rustc-link-lib=m");
// Use -g instead of -ggdb3 for musl targets (Alpine Linux)
// as musl's gcc doesn't support -ggdb3
let debug_flag = if is_musl { "-g" } else { "-ggdb3" };
build = build
.flag("-O0")
.flag(debug_flag)
.flag("-fdiagnostics-show-option")
.flag("-fno-exceptions")
.flag("-fno-omit-frame-pointer")
.flag("-fno-optimize-sibling-calls")
//.flag("-fsanitize=address")
//.flag("-fsanitize=undefined")
.flag("-fstack-protector")
.flag("-pedantic")
.define("HAVE_DIRENT_H", None)
.define("HAVE_UNISTD_H", None);
}
build.compile("timelib");
}
#[cfg(feature = "re2c")]
fn re2c(file: &str, out_path: &PathBuf) {
let target_file = File::create(out_path.join(format!("{file}.c"))).unwrap();
let stdio = Stdio::from(target_file);
let mut cmd = Command::new("re2c")
.current_dir("ext/timelib")
.arg("-d")
.arg("-b")
.arg(format!("{file}.re"))
.stdout(stdio)
.spawn()
.expect("re2c command failed to start");
cmd.wait()
.expect(format!("failed to generate {file}.c").as_str());
}