Skip to content

Commit 6dcd039

Browse files
davidhewittTpt
andauthored
ci: install debug interpreter with uv (#5447)
* ci: install debug interpreter with uv * try use rpath to link to exact interpreter * don't emit rpath on wasm targets * fixup clippy * update now ui-test has landed * fix clippy * Update pyo3-build-config/src/lib.rs Co-authored-by: Thomas Tanon <thomas@pellissier-tanon.fr> * newsfragment --------- Co-authored-by: Thomas Tanon <thomas@pellissier-tanon.fr>
1 parent 624adc9 commit 6dcd039

5 files changed

Lines changed: 64 additions & 87 deletions

File tree

.github/workflows/ci.yml

Lines changed: 5 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -597,37 +597,11 @@ jobs:
597597
- uses: dtolnay/rust-toolchain@stable
598598
with:
599599
components: rust-src
600-
- name: Install python3 standalone debug build with nox
601-
run: |
602-
PBS_RELEASE="20241219"
603-
PBS_PYTHON_VERSION="3.13.1"
604-
PBS_ARCHIVE="cpython-${PBS_PYTHON_VERSION}+${PBS_RELEASE}-x86_64-unknown-linux-gnu-debug-full.tar.zst"
605-
wget "https://github.com/indygreg/python-build-standalone/releases/download/${PBS_RELEASE}/${PBS_ARCHIVE}"
606-
tar -I zstd -xf "${PBS_ARCHIVE}"
607-
ls -l $(pwd)/python/install/bin
608-
ls -l $(pwd)/python/install/lib
609-
echo PATH=$(pwd)/python/install/bin:$PATH >> $GITHUB_ENV
610-
echo LD_LIBRARY_PATH=$(pwd)/python/install/lib:$LD_LIBRARY_PATH >> $GITHUB_ENV
611-
echo PYTHONHOME=$(pwd)/python/install >> $GITHUB_ENV
612-
echo PYO3_PYTHON=$(pwd)/python/install/bin/python3 >> $GITHUB_ENV
613-
- run: python3 -m sysconfig
614-
- run: python3 -m pip install --upgrade pip && pip install nox[uv]
615-
- run: |
616-
PYO3_CONFIG_FILE=$(mktemp)
617-
cat > $PYO3_CONFIG_FILE << EOF
618-
implementation=CPython
619-
version=3.13
620-
shared=true
621-
abi3=false
622-
lib_name=python3.13d
623-
lib_dir=${{ github.workspace }}/python/install/lib
624-
executable=${{ github.workspace }}/python/install/bin/python3
625-
pointer_width=64
626-
build_flags=Py_DEBUG,Py_REF_DEBUG
627-
suppress_build_script_link_lines=false
628-
EOF
629-
echo PYO3_CONFIG_FILE=$PYO3_CONFIG_FILE >> $GITHUB_ENV
630-
- run: python3 -m nox -s test
600+
- uses: astral-sh/setup-uv@v6
601+
with:
602+
python-version: "3.13+debug"
603+
- run: uvx python -m sysconfig
604+
- run: uvx nox -s test
631605

632606
test-version-limits:
633607
needs: [fmt, resolve]

build.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
use std::env;
22

3-
use pyo3_build_config::pyo3_build_script_impl::{cargo_env_var, errors::Result};
4-
use pyo3_build_config::{
5-
add_python_framework_link_args, bail, print_feature_cfgs, InterpreterConfig,
3+
use pyo3_build_config::pyo3_build_script_impl::{
4+
cargo_env_var, errors::Result, print_feature_cfgs,
65
};
6+
use pyo3_build_config::{add_libpython_rpath_link_args, bail, InterpreterConfig};
77

88
fn ensure_auto_initialize_ok(interpreter_config: &InterpreterConfig) -> Result<()> {
99
if cargo_env_var("CARGO_FEATURE_AUTO_INITIALIZE").is_some() && !interpreter_config.shared() {
@@ -47,8 +47,8 @@ fn configure_pyo3() -> Result<()> {
4747
// which allows consumers of `pyo3-build-config` APIs to depend on pyo3 instead of pyo3-ffi.
4848
interpreter_config.to_cargo_dep_env()?;
4949

50-
// Make `cargo test` etc work on macOS with Xcode bundled Python
51-
add_python_framework_link_args();
50+
// Make `cargo test` etc work with non-system Python installations
51+
add_libpython_rpath_link_args();
5252

5353
Ok(())
5454
}

newsfragments/5447.fixed.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix `add_libpython_rpath_link_args` emitting rpath link args on wasm targets which don't support rpath.

pyo3-build-config/src/lib.rs

Lines changed: 43 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ pub use impl_::{
1818
PythonVersion, Triple,
1919
};
2020

21-
use target_lexicon::OperatingSystem;
21+
use target_lexicon::{Architecture, OperatingSystem};
2222

2323
/// Adds all the [`#[cfg]` flags](index.html) to the current compilation.
2424
///
@@ -95,23 +95,7 @@ fn _add_extension_module_link_args(
9595
/// for more details.
9696
pub fn add_libpython_rpath_link_args() {
9797
let target = impl_::target_triple_from_env();
98-
_add_libpython_rpath_link_args(
99-
get(),
100-
impl_::is_linking_libpython_for_target(&target),
101-
std::io::stdout(),
102-
)
103-
}
104-
105-
fn _add_libpython_rpath_link_args(
106-
interpreter_config: &InterpreterConfig,
107-
is_linking_libpython: bool,
108-
mut writer: impl std::io::Write,
109-
) {
110-
if is_linking_libpython {
111-
if let Some(lib_dir) = interpreter_config.lib_dir() {
112-
writeln!(writer, "cargo:rustc-link-arg=-Wl,-rpath,{lib_dir}").unwrap();
113-
}
114-
}
98+
pyo3_build_script_impl::print_libpython_rpath_link_args(&target, get());
11599
}
116100

117101
/// Adds linker arguments suitable for linking against the Python framework on macOS.
@@ -162,32 +146,6 @@ fn get_inner() -> InterpreterConfig {
162146
interpreter_config.expect("failed to parse PyO3 config")
163147
}
164148

165-
/// Helper to print a feature cfg with a minimum rust version required.
166-
fn print_feature_cfg(minor_version_required: u32, cfg: &str) {
167-
let minor_version = rustc_minor_version().unwrap_or(0);
168-
169-
if minor_version >= minor_version_required {
170-
println!("cargo:rustc-cfg={cfg}");
171-
}
172-
173-
// rustc 1.80.0 stabilized `rustc-check-cfg` feature, don't emit before
174-
if minor_version >= 80 {
175-
println!("cargo:rustc-check-cfg=cfg({cfg})");
176-
}
177-
}
178-
179-
/// Use certain features if we detect the compiler being used supports them.
180-
///
181-
/// Features may be removed or added as MSRV gets bumped or new features become available,
182-
/// so this function is unstable.
183-
#[doc(hidden)]
184-
pub fn print_feature_cfgs() {
185-
print_feature_cfg(84, "const_is_null");
186-
print_feature_cfg(85, "fn_ptr_eq");
187-
print_feature_cfg(86, "from_bytes_with_nul_error");
188-
print_feature_cfg(95, "cfg_select");
189-
}
190-
191149
/// Registers `pyo3`s config names as reachable cfg expressions
192150
///
193151
/// - <https://github.com/rust-lang/cargo/pull/13571>
@@ -328,6 +286,47 @@ pub mod pyo3_build_script_impl {
328286
self.message
329287
}
330288
}
289+
290+
/// Detects features which `pyo3` and `pyo3-ffi` depend upon internally, and prints the appropriate
291+
/// `cargo:rustc-cfg` and `cargo:rustc-check-cfg` directives to enable them.
292+
pub fn print_feature_cfgs() {
293+
print_feature_cfg(84, "const_is_null");
294+
print_feature_cfg(85, "fn_ptr_eq");
295+
print_feature_cfg(86, "from_bytes_with_nul_error");
296+
print_feature_cfg(95, "cfg_select");
297+
}
298+
299+
/// Helper to print a feature cfg with a minimum rust version required.
300+
fn print_feature_cfg(minor_version_required: u32, cfg: &str) {
301+
println!("cargo:rustc-check-cfg=cfg({cfg})");
302+
303+
let minor_version = rustc_minor_version().unwrap_or(0);
304+
if minor_version >= minor_version_required {
305+
println!("cargo:rustc-cfg={cfg}");
306+
}
307+
}
308+
309+
/// Emit libpython rpath link args if appropriate for the target and interpreter config.
310+
///
311+
/// This form exists for pyo3-ffi where `get()` cannot be called.
312+
pub fn print_libpython_rpath_link_args(
313+
target: &Triple,
314+
interpreter_config: &InterpreterConfig,
315+
) {
316+
let is_linking_libpython = is_linking_libpython_for_target(target);
317+
let is_wasm = matches!(
318+
target.architecture,
319+
Architecture::Wasm32 | Architecture::Wasm64
320+
);
321+
let is_emscripten = target.operating_system == target_lexicon::OperatingSystem::Emscripten;
322+
// webassembly targets generally don't support rpath, emscripten is the only exception currently aware of:
323+
// https://github.com/emscripten-core/emscripten/issues/22126
324+
if is_linking_libpython && (!is_wasm || is_emscripten) {
325+
if let Some(lib_dir) = interpreter_config.lib_dir() {
326+
println!("cargo:rustc-link-arg=-Wl,-rpath,{lib_dir}");
327+
}
328+
}
329+
}
331330
}
332331

333332
fn rustc_minor_version() -> Option<u32> {

pyo3-ffi/build.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
use pyo3_build_config::{
2-
bail, ensure, print_feature_cfgs,
2+
bail, ensure,
33
pyo3_build_script_impl::{
44
cargo_env_var, env_var, errors::Result, is_linking_libpython_for_target,
5-
resolve_build_config, target_triple_from_env, BuildConfig, BuildConfigSource,
6-
MaximumVersionExceeded,
5+
print_feature_cfgs, print_libpython_rpath_link_args, resolve_build_config,
6+
target_triple_from_env, BuildConfig, BuildConfigSource, MaximumVersionExceeded,
77
},
88
warn, InterpreterConfig, PythonImplementation, PythonVersion,
99
};
@@ -214,12 +214,12 @@ fn emit_link_config(build_config: &BuildConfig) -> Result<()> {
214214

215215
/// Prepares the PyO3 crate for compilation.
216216
///
217-
/// This loads the config from pyo3-build-config and then makes some additional checks to improve UX
218-
/// for users.
217+
/// This uses pyo3-build-config implementation to detect the target Python interpreter and validate
218+
/// it's suitable for building with.
219219
///
220220
/// Emits the cargo configuration based on this config as well as a few checks of the Rust compiler
221221
/// version to enable features which aren't supported on MSRV.
222-
fn configure_pyo3() -> Result<()> {
222+
fn configure_pyo3_ffi() -> Result<()> {
223223
let target = target_triple_from_env();
224224
let build_config = resolve_build_config(&target)?;
225225
let interpreter_config = &build_config.interpreter_config;
@@ -251,6 +251,9 @@ fn configure_pyo3() -> Result<()> {
251251

252252
print_feature_cfgs();
253253

254+
// Make `cargo test` etc work with non-system Python installations
255+
print_libpython_rpath_link_args(&target, interpreter_config);
256+
254257
Ok(())
255258
}
256259

@@ -265,7 +268,7 @@ fn print_config_and_exit(config: &InterpreterConfig) {
265268

266269
fn main() {
267270
pyo3_build_config::print_expected_cfgs();
268-
if let Err(e) = configure_pyo3() {
271+
if let Err(e) = configure_pyo3_ffi() {
269272
eprintln!("error: {}", e.report());
270273
std::process::exit(1)
271274
}

0 commit comments

Comments
 (0)