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
//! Locate the SDK dylib, its deps/ dir, and the rustc wrapper.
//!
//! Both [`ext_build`](crate::ext_build) (for invoking cargo) and
//! [`new_project`](crate::new_project) (for writing the scaffolded
//! project's `.cargo/config.toml`) need these paths. The path
//! computation lives here so the two sites can't drift. Callers
//! perform their own existence checks and raise whatever error
//! type makes sense for their surface.
//!
//! Resolution order:
//!
//! 1. `JACKDAW_SDK_DIR` env var, if set.
//! 2. The directory containing the currently-running executable.
//! With `cargo run --features dylib`, that lands in
//! `<workspace>/target/debug/` alongside `libjackdaw_sdk.so`.
//! For installed distributions the layout is expected to match.
//! 3. `.` as a last resort; existence checks at the call site will
//! then almost certainly fail.
use std::path::PathBuf;
/// Everything `ext_build` and `new_project` need to point
/// cargo-spawned rustc at the editor's SDK. Paths are _computed_,
/// not _verified_; call [`Self::dylib_exists`] / [`Self::wrapper_exists`]
/// or an equivalent before relying on them.
pub struct SdkPaths {
/// Absolute path to `libjackdaw_sdk.{so,dylib,dll}`.
pub dylib: PathBuf,
/// Absolute path to the sibling `deps/` directory (what
/// `-L dependency=` should point at).
pub deps: PathBuf,
/// Absolute path to `jackdaw-rustc-wrapper(.exe)`.
pub wrapper: PathBuf,
}
impl SdkPaths {
pub fn compute() -> Self {
let base = resolve_base_dir();
Self {
dylib: base.join(dylib_name()),
deps: base.join("deps"),
wrapper: base.join(wrapper_name()),
}
}
pub fn dylib_exists(&self) -> bool {
self.dylib.is_file()
}
pub fn wrapper_exists(&self) -> bool {
self.wrapper.is_file()
}
}
fn resolve_base_dir() -> PathBuf {
if let Ok(from_env) = std::env::var("JACKDAW_SDK_DIR") {
return PathBuf::from(from_env);
}
std::env::current_exe()
.ok()
.and_then(|p| p.parent().map(ToOwned::to_owned))
.unwrap_or_else(|| PathBuf::from("."))
}
fn dylib_name() -> &'static str {
if cfg!(target_os = "windows") {
"jackdaw_sdk.dll"
} else if cfg!(target_os = "macos") {
"libjackdaw_sdk.dylib"
} else {
"libjackdaw_sdk.so"
}
}
fn wrapper_name() -> &'static str {
if cfg!(target_os = "windows") {
"jackdaw-rustc-wrapper.exe"
} else {
"jackdaw-rustc-wrapper"
}
}