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
//! Build script for rustfs-mimalloc-sys.
//!
//! Compiles mimalloc V3 as a static library using the `cc` crate.
//! Handles platform-specific flags, feature gates, and linker requirements.
use std::env;
fn main() {
let target = env::var("TARGET").unwrap_or_default();
let is_debug = env::var("PROFILE").as_deref() == Ok("debug");
// Tell Cargo to re-run if features change
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_SECURE");
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_DEBUG");
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_DEBUG_IN_DEBUG");
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_OVERRIDE");
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_LOCAL_DYNAMIC_TLS");
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_WIN_DIRECT_TLS");
println!("cargo:rerun-if-env-changed=CARGO_FEATURE_NO_THP");
let mut build = cc::Build::new();
build.file("c_src/mimalloc/src/static.c");
build.include("c_src/mimalloc/include");
build.include("c_src/mimalloc/src");
// Optimization flags
if !is_debug {
build.opt_level(3);
build.define("NDEBUG", None);
build.define("MI_BUILD_RELEASE", None);
} else {
build.opt_level(0);
build.debug(true);
}
// Debug mode: either explicit feature or auto-enable in debug builds
if env::var_os("CARGO_FEATURE_DEBUG").is_some()
|| (env::var_os("CARGO_FEATURE_DEBUG_IN_DEBUG").is_some() && is_debug)
{
build.define("MI_DEBUG", "2");
} else {
build.define("MI_DEBUG", "0");
}
// Secure mode: encrypt heap allocations
if env::var_os("CARGO_FEATURE_SECURE").is_some() {
build.define("MI_SECURE", "4");
}
// TLS model: default is initial-exec for performance.
// Use `local_dynamic_tls` feature to switch to local-dynamic model,
// which fixes compatibility with projects like polars that have TLS issues.
// See: https://github.com/purpleprotocol/mimalloc_rust/issues/138
if env::var_os("CARGO_FEATURE_LOCAL_DYNAMIC_TLS").is_some() {
build.flag_if_supported("-ftls-model=local-dynamic");
} else if target.contains("apple") || target.contains("linux") || target.contains("freebsd") {
build.flag_if_supported("-ftls-model=initial-exec");
}
if target.contains("windows") && env::var_os("CARGO_FEATURE_WIN_DIRECT_TLS").is_some() {
build.define("MI_WIN_DIRECT_TLS", "1");
}
// Disable THP on Linux/Android if requested
// See: https://github.com/purpleprotocol/mimalloc_rust/pull/112
if env::var_os("CARGO_FEATURE_NO_THP").is_some() {
build.define("MI_NO_THP", "1");
}
// macOS: enable dyld interposing for proper override support
// See: https://github.com/purpleprotocol/mimalloc_rust/pull/145
if target.contains("apple") && env::var_os("CARGO_FEATURE_OVERRIDE").is_some() {
build.define("MI_OSX_ZONE", "1");
build.define("MI_OSX_INTERPOSE", "1");
}
// Platform-specific compiler flags
if target.contains("msvc") || target.contains("windows") {
// MSVC: use correct runtime library based on debug/release
// See: https://github.com/purpleprotocol/mimalloc_rust/pull/167
if is_debug {
build.flag("/MDd");
} else {
build.flag("/MD");
}
// Suppress common MSVC warnings
build.flag("/wd4100"); // unreferenced formal parameter
build.flag("/wd4127"); // conditional expression is constant
build.flag("/wd4201"); // nameless struct/union
} else {
// Unix-like: standard warning suppression
build.flag_if_supported("-Wno-unused-function");
build.flag_if_supported("-Wno-unused-parameter");
// Fix musl + release build failures with __DATE__ / __TIME__ macros
// See: https://github.com/purpleprotocol/mimalloc_rust/pull/139
if target.contains("musl") {
build.flag_if_supported("-Wno-error=date-time");
}
}
// ARM-specific: do NOT force ARMv8.1-A (fixes Raspberry Pi 4 compatibility)
// See: https://github.com/purpleprotocol/mimalloc_rust/issues/165
// We let the compiler use the target's default architecture level.
// If the user wants ARMv8.1-A optimizations, they can set RUSTFLAGS.
build.compile("mimalloc");
// Link required system libraries
link_system_libs(&target);
// Export include directory for downstream crates
let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
println!("cargo:include={manifest_dir}/c_src/mimalloc/include");
// Print version info
println!("cargo:version=30500"); // MI_MALLOC_VERSION from mimalloc.h
}
/// Link required system libraries based on the target platform.
fn link_system_libs(target: &str) {
if target.contains("windows") {
// Windows: required for crypto (BCryptGenRandom), process info (psapi),
// and token manipulation (advapi32 for large pages)
// See: https://github.com/purpleprotocol/mimalloc_rust/issues/135
println!("cargo:rustc-link-lib=advapi32");
println!("cargo:rustc-link-lib=bcrypt");
println!("cargo:rustc-link-lib=psapi");
println!("cargo:rustc-link-lib=shell32");
println!("cargo:rustc-link-lib=user32");
}
// ARMv6: needs libatomic for 64-bit atomic operations
// See: https://github.com/purpleprotocol/mimalloc_rust/pull/115
if target.contains("armv6") || target.contains("arm-unknown") {
println!("cargo:rustc-link-lib=atomic");
}
}