Skip to content

Commit c09d654

Browse files
improve Python environment activation (#118)
1 parent 3b7ffe0 commit c09d654

File tree

10 files changed

+668
-289
lines changed

10 files changed

+668
-289
lines changed

CHANGELOG.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ and this project attempts to adhere to [Semantic Versioning](https://semver.org/
2727
### Changed
2828

2929
- **Internal**: Moved task queueing functionality to `djls-server` crate, renamed from `Worker` to `Queue`, and simplified API.
30-
- Improved Python environment detection.
30+
- **Internal**: Improved Python environment handling, including refactored activation logic.
3131

3232
## [5.2.0a0]
3333

Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@ anyhow = "1.0"
1313
async-trait = "0.1"
1414
pyo3 = "0.24"
1515
pyo3-async-runtimes = "0.24"
16+
pyo3-build-config = "0.24"
1617
serde = { version = "1.0", features = ["derive"] }
1718
serde_json = "1.0"
19+
tempfile = "3.19"
1820
thiserror = "2.0"
1921
tokio = { version = "1.42", features = ["full"] }
2022
tower-lsp-server = { version = "0.21", features = ["proposed"] }

crates/djls-project/Cargo.toml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,13 @@ version = "0.1.0"
44
edition = "2021"
55

66
[dependencies]
7-
pyo3 = { workspace = true }
7+
pyo3 = { workspace = true, features = ["auto-initialize"] }
88
tower-lsp-server = { workspace = true, features = ["proposed"] }
99

1010
which = "7.0.1"
1111

12+
[build-dependencies]
13+
pyo3-build-config = { workspace = true, features = ["resolve-config"] }
14+
1215
[dev-dependencies]
13-
tempfile = "3.19"
16+
tempfile = { workspace = true }

crates/djls-project/build.rs

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
/// Build script to configure linking against the Python library.
2+
///
3+
/// This script is necessary when the crate's code, particularly tests
4+
/// that interact with the Python interpreter via `pyo3` (e.g., using
5+
/// `Python::with_gil`, importing modules, calling Python functions),
6+
/// needs symbols from the Python C API at link time.
7+
///
8+
/// It uses `pyo3-build-config` to detect the Python installation and
9+
/// prints the required `cargo:rustc-link-search` and `cargo:rustc-link-lib`
10+
/// directives to Cargo, enabling the linker to find and link against the
11+
/// appropriate Python library (e.g., libpythonX.Y.so).
12+
///
13+
/// It also adds an RPATH linker argument on Unix-like systems so the
14+
/// resulting test executable can find the Python library at runtime.
15+
///
16+
/// Note: Each crate whose test target requires Python linking needs its
17+
/// own `build.rs` with this logic.
18+
fn main() {
19+
println!("cargo:rerun-if-changed=build.rs");
20+
21+
// Set up #[cfg] flags first (useful for conditional compilation)
22+
pyo3_build_config::use_pyo3_cfgs();
23+
24+
// Get the Python interpreter configuration directly
25+
let config = pyo3_build_config::get();
26+
27+
// Add the library search path if available
28+
if let Some(lib_dir) = &config.lib_dir {
29+
println!("cargo:rustc-link-search=native={}", lib_dir);
30+
31+
// Add RPATH linker argument for Unix-like systems (Linux, macOS)
32+
// This helps the test executable find the Python library at runtime.
33+
#[cfg(not(windows))]
34+
println!("cargo:rustc-link-arg=-Wl,-rpath,{}", lib_dir);
35+
} else {
36+
println!("cargo:warning=Python library directory not found in config.");
37+
}
38+
39+
// Add the library link directive if available
40+
if let Some(lib_name) = &config.lib_name {
41+
println!("cargo:rustc-link-lib=dylib={}", lib_name);
42+
} else {
43+
println!("cargo:warning=Python library name not found in config.");
44+
}
45+
}

0 commit comments

Comments
 (0)