Skip to content

Commit e517bf8

Browse files
committed
rust_src: Resolve output path for foreign targets and unresolved symbols on macOS
1 parent 903a5d6 commit e517bf8

1 file changed

Lines changed: 38 additions & 9 deletions

File tree

src/rust_src/build.rs

Lines changed: 38 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,18 @@ use std::path::PathBuf;
33

44
fn main() {
55
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
6-
let target_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap())
7-
.join("target")
8-
.join(env::var("PROFILE").unwrap_or("release".into()));
6+
let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
7+
let profile = env::var("PROFILE").unwrap_or("release".into());
8+
let target = env::var("TARGET").unwrap_or_default();
9+
10+
// Cargo puts output in target/<profile>/ OR target/<triple>/<profile>/
11+
// when --target is used. Output loader to both locations to be safe.
12+
let base_dir = manifest_dir.join("target").join(&profile);
13+
let triple_dir = if !target.is_empty() {
14+
Some(manifest_dir.join("target").join(&target).join(&profile))
15+
} else {
16+
None
17+
};
918

1019
// Compile the loader .so
1120
// This tiny C library:
@@ -17,23 +26,26 @@ fn main() {
1726
std::fs::write(&loader_c, LOADER_SOURCE).unwrap();
1827

1928
// Platform-specific loader compilation
20-
let target = env::var("TARGET").unwrap_or_default();
2129
let is_windows = target.contains("windows");
2230
let is_macos = target.contains("apple") || target.contains("darwin");
2331

32+
std::fs::create_dir_all(&base_dir).ok();
33+
if let Some(ref td) = triple_dir {
34+
std::fs::create_dir_all(td).ok();
35+
}
36+
2437
if is_windows {
2538
// On Windows, the loader is compiled by the C compiler from the host
2639
// For cross-compilation from Linux CI, we skip loader compilation
2740
// and rely on the Rust cdylib being named ring_python_impl.dll
2841
// The loader .dll is built separately or by MSVC on Windows CI
29-
let loader_dll = target_dir.join("ring_python.dll");
42+
let loader_dll = base_dir.join("ring_python.dll");
3043
let status = std::process::Command::new("cl.exe")
3144
.args([
32-
"/LD", "/O2", "/Fe:", loader_dll.to_str().unwrap(),
45+
"/LD", "/O2", &format!("/Fe:{}", loader_dll.to_str().unwrap()),
3346
loader_c.to_str().unwrap(),
3447
])
3548
.status();
36-
// If cl.exe is not available (Linux CI), try gcc for Windows target
3749
if status.is_err() || !status.unwrap().success() {
3850
let status = std::process::Command::new("gcc")
3951
.args([
@@ -45,8 +57,11 @@ fn main() {
4557
.expect("Failed to compile loader");
4658
assert!(status.success(), "Failed to compile loader .dll");
4759
}
60+
if let Some(ref td) = triple_dir {
61+
std::fs::copy(&loader_dll, td.join("ring_python.dll")).ok();
62+
}
4863
} else if is_macos {
49-
let loader_dylib = target_dir.join("libring_python.dylib");
64+
let loader_dylib = base_dir.join("libring_python.dylib");
5065
let status = std::process::Command::new("gcc")
5166
.args([
5267
"-shared", "-fPIC", "-O2",
@@ -58,9 +73,13 @@ fn main() {
5873
.status()
5974
.expect("Failed to compile loader");
6075
assert!(status.success(), "Failed to compile loader .dylib");
76+
if let Some(ref td) = triple_dir {
77+
std::fs::copy(&loader_dylib, td.join("libring_python.dylib")).ok();
78+
}
6179
} else {
6280
// Linux, FreeBSD, etc.
63-
let loader_so = target_dir.join("libring_python.so");
81+
let loader_so = base_dir.join("libring_python.so");
82+
std::fs::create_dir_all(&base_dir).ok();
6483
let status = std::process::Command::new("gcc")
6584
.args([
6685
"-shared", "-fPIC", "-O2",
@@ -72,9 +91,19 @@ fn main() {
7291
.status()
7392
.expect("Failed to compile loader");
7493
assert!(status.success(), "Failed to compile loader .so");
94+
if let Some(ref td) = triple_dir {
95+
std::fs::create_dir_all(td).ok();
96+
std::fs::copy(&loader_so, td.join("libring_python.so")).ok();
97+
}
7598
}
7699

77100
println!("cargo:rerun-if-changed=build.rs");
101+
102+
// On macOS, allow undefined symbols (resolved at runtime by the loader)
103+
if is_macos {
104+
println!("cargo:rustc-cdylib-link-arg=-undefined");
105+
println!("cargo:rustc-cdylib-link-arg=dynamic_lookup");
106+
}
78107
}
79108

80109
const LOADER_SOURCE: &str = r#"

0 commit comments

Comments
 (0)