pyo3-build-config: conditionalize symbols on resolve-config feature
PR #1856 was buggy in that the `pyo3-build-config` crate didn't actually work in library mode because `include_str!()` was attempting to resolve missing files as part of populating some `const` values. We could change the logic of these constants to make them lazy if we wanted to support possibly getting access to the value. But the simple solution is to conditionalize their presence on the crate feature. Test coverage for building and testing the crate in insolation with the feature disabled has been added. Various code has been conditionalized to avoid compiler warnings. Also, it appears `cargo build|test -p pyo3-build-config --no-default-features` still passes default features. This seems wrong to me. But it is how my system behaves. Maybe it is an sccache bug? I coded the new tests to `cd pyo3-build-config` first to work around.
This commit is contained in:
parent
afd4d46bdb
commit
3957afc9c5
|
@ -176,11 +176,23 @@ jobs:
|
||||||
- name: Build (no features)
|
- name: Build (no features)
|
||||||
run: cargo build --lib --tests --no-default-features
|
run: cargo build --lib --tests --no-default-features
|
||||||
|
|
||||||
|
# --no-default-features when used with `cargo build/test -p` doesn't seem to work!
|
||||||
|
- name: Build pyo3-build-config (no features)
|
||||||
|
run: |
|
||||||
|
cd pyo3-build-config
|
||||||
|
cargo build --no-default-features
|
||||||
|
|
||||||
# Run tests (except on PyPy, because no embedding API).
|
# Run tests (except on PyPy, because no embedding API).
|
||||||
- if: ${{ !startsWith(matrix.python-version, 'pypy') }}
|
- if: ${{ !startsWith(matrix.python-version, 'pypy') }}
|
||||||
name: Test (no features)
|
name: Test (no features)
|
||||||
run: cargo test --no-default-features
|
run: cargo test --no-default-features
|
||||||
|
|
||||||
|
# --no-default-features when used with `cargo build/test -p` doesn't seem to work!
|
||||||
|
- name: Test pyo3-build-config (no features)
|
||||||
|
run: |
|
||||||
|
cd pyo3-build-config
|
||||||
|
cargo test --no-default-features
|
||||||
|
|
||||||
- name: Build (all additive features)
|
- name: Build (all additive features)
|
||||||
run: cargo build --lib --tests --no-default-features --features "${{ steps.settings.outputs.all_additive_features }}"
|
run: cargo build --lib --tests --no-default-features --features "${{ steps.settings.outputs.all_additive_features }}"
|
||||||
|
|
||||||
|
|
|
@ -479,6 +479,7 @@ struct CrossCompileConfig {
|
||||||
arch: String,
|
arch: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(unused)]
|
||||||
pub fn any_cross_compiling_env_vars_set() -> bool {
|
pub fn any_cross_compiling_env_vars_set() -> bool {
|
||||||
env::var_os("PYO3_CROSS").is_some()
|
env::var_os("PYO3_CROSS").is_some()
|
||||||
|| env::var_os("PYO3_CROSS_LIB_DIR").is_some()
|
|| env::var_os("PYO3_CROSS_LIB_DIR").is_some()
|
||||||
|
@ -1466,7 +1467,11 @@ mod tests {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
#[cfg(all(target_os = "linux", target_arch = "x86_64"))]
|
#[cfg(all(
|
||||||
|
target_os = "linux",
|
||||||
|
target_arch = "x86_64",
|
||||||
|
feature = "resolve-config"
|
||||||
|
))]
|
||||||
fn parse_sysconfigdata() {
|
fn parse_sysconfigdata() {
|
||||||
// A best effort attempt to get test coverage for the sysconfigdata parsing.
|
// A best effort attempt to get test coverage for the sysconfigdata parsing.
|
||||||
// Might not complete successfully depending on host installation; that's ok as long as
|
// Might not complete successfully depending on host installation; that's ok as long as
|
||||||
|
|
|
@ -9,8 +9,10 @@
|
||||||
mod errors;
|
mod errors;
|
||||||
mod impl_;
|
mod impl_;
|
||||||
|
|
||||||
|
#[cfg(feature = "resolve-config")]
|
||||||
use std::io::Cursor;
|
use std::io::Cursor;
|
||||||
|
|
||||||
|
#[cfg(feature = "resolve-config")]
|
||||||
use once_cell::sync::OnceCell;
|
use once_cell::sync::OnceCell;
|
||||||
|
|
||||||
pub use impl_::{BuildFlag, BuildFlags, InterpreterConfig, PythonImplementation, PythonVersion};
|
pub use impl_::{BuildFlag, BuildFlags, InterpreterConfig, PythonImplementation, PythonVersion};
|
||||||
|
@ -28,6 +30,7 @@ pub use impl_::{BuildFlag, BuildFlags, InterpreterConfig, PythonImplementation,
|
||||||
/// | `#[cfg(PyPy)]` | This marks code which is run when compiling for PyPy. |
|
/// | `#[cfg(PyPy)]` | This marks code which is run when compiling for PyPy. |
|
||||||
///
|
///
|
||||||
/// For examples of how to use these attributes, [see PyO3's guide](https://pyo3.rs/latest/building_and_distribution/multiple_python_versions.html).
|
/// For examples of how to use these attributes, [see PyO3's guide](https://pyo3.rs/latest/building_and_distribution/multiple_python_versions.html).
|
||||||
|
#[cfg(feature = "resolve-config")]
|
||||||
pub fn use_pyo3_cfgs() {
|
pub fn use_pyo3_cfgs() {
|
||||||
get().emit_pyo3_cfgs();
|
get().emit_pyo3_cfgs();
|
||||||
}
|
}
|
||||||
|
@ -56,6 +59,7 @@ fn _add_extension_module_link_args(target_os: &str, mut writer: impl std::io::Wr
|
||||||
///
|
///
|
||||||
/// Because this will never change in a given compilation run, this is cached in a `once_cell`.
|
/// Because this will never change in a given compilation run, this is cached in a `once_cell`.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
#[cfg(feature = "resolve-config")]
|
||||||
pub fn get() -> &'static InterpreterConfig {
|
pub fn get() -> &'static InterpreterConfig {
|
||||||
static CONFIG: OnceCell<InterpreterConfig> = OnceCell::new();
|
static CONFIG: OnceCell<InterpreterConfig> = OnceCell::new();
|
||||||
CONFIG.get_or_init(|| {
|
CONFIG.get_or_init(|| {
|
||||||
|
@ -74,23 +78,28 @@ pub fn get() -> &'static InterpreterConfig {
|
||||||
|
|
||||||
/// Path where PyO3's build.rs will write configuration by default.
|
/// Path where PyO3's build.rs will write configuration by default.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
#[cfg(feature = "resolve-config")]
|
||||||
const DEFAULT_CROSS_COMPILE_CONFIG_PATH: &str =
|
const DEFAULT_CROSS_COMPILE_CONFIG_PATH: &str =
|
||||||
concat!(env!("OUT_DIR"), "/pyo3-cross-compile-config.txt");
|
concat!(env!("OUT_DIR"), "/pyo3-cross-compile-config.txt");
|
||||||
|
|
||||||
/// Build configuration provided by `PYO3_CONFIG_FILE`. May be empty if env var not set.
|
/// Build configuration provided by `PYO3_CONFIG_FILE`. May be empty if env var not set.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
#[cfg(feature = "resolve-config")]
|
||||||
const CONFIG_FILE: &str = include_str!(concat!(env!("OUT_DIR"), "/pyo3-build-config-file.txt"));
|
const CONFIG_FILE: &str = include_str!(concat!(env!("OUT_DIR"), "/pyo3-build-config-file.txt"));
|
||||||
|
|
||||||
/// Build configuration set if abi3 features enabled and `PYO3_NO_PYTHON` env var present. Empty if
|
/// Build configuration set if abi3 features enabled and `PYO3_NO_PYTHON` env var present. Empty if
|
||||||
/// not both present.
|
/// not both present.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
#[cfg(feature = "resolve-config")]
|
||||||
const ABI3_CONFIG: &str = include_str!(concat!(env!("OUT_DIR"), "/pyo3-build-config-abi3.txt"));
|
const ABI3_CONFIG: &str = include_str!(concat!(env!("OUT_DIR"), "/pyo3-build-config-abi3.txt"));
|
||||||
|
|
||||||
/// Build configuration discovered by `pyo3-build-config` build script. Not aware of
|
/// Build configuration discovered by `pyo3-build-config` build script. Not aware of
|
||||||
/// cross-compilation settings.
|
/// cross-compilation settings.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
|
#[cfg(feature = "resolve-config")]
|
||||||
const HOST_CONFIG: &str = include_str!(concat!(env!("OUT_DIR"), "/pyo3-build-config.txt"));
|
const HOST_CONFIG: &str = include_str!(concat!(env!("OUT_DIR"), "/pyo3-build-config.txt"));
|
||||||
|
|
||||||
|
#[cfg(feature = "resolve-config")]
|
||||||
fn abi3_config() -> InterpreterConfig {
|
fn abi3_config() -> InterpreterConfig {
|
||||||
let mut interpreter_config = InterpreterConfig::from_reader(Cursor::new(ABI3_CONFIG))
|
let mut interpreter_config = InterpreterConfig::from_reader(Cursor::new(ABI3_CONFIG))
|
||||||
.expect("failed to parse hardcoded PyO3 abi3 config");
|
.expect("failed to parse hardcoded PyO3 abi3 config");
|
||||||
|
@ -109,9 +118,12 @@ fn abi3_config() -> InterpreterConfig {
|
||||||
/// Please don't use these - they could change at any time.
|
/// Please don't use these - they could change at any time.
|
||||||
#[doc(hidden)]
|
#[doc(hidden)]
|
||||||
pub mod pyo3_build_script_impl {
|
pub mod pyo3_build_script_impl {
|
||||||
|
#[cfg(feature = "resolve-config")]
|
||||||
use crate::errors::{Context, Result};
|
use crate::errors::{Context, Result};
|
||||||
|
#[cfg(feature = "resolve-config")]
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
|
#[cfg(feature = "resolve-config")]
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub mod errors {
|
pub mod errors {
|
||||||
|
@ -126,6 +138,7 @@ pub mod pyo3_build_script_impl {
|
||||||
/// Differs from .get() above only in the cross-compile case, where PyO3's build script is
|
/// Differs from .get() above only in the cross-compile case, where PyO3's build script is
|
||||||
/// required to generate a new config (as it's the first build script which has access to the
|
/// required to generate a new config (as it's the first build script which has access to the
|
||||||
/// correct value for CARGO_CFG_TARGET_OS).
|
/// correct value for CARGO_CFG_TARGET_OS).
|
||||||
|
#[cfg(feature = "resolve-config")]
|
||||||
pub fn resolve_interpreter_config() -> Result<InterpreterConfig> {
|
pub fn resolve_interpreter_config() -> Result<InterpreterConfig> {
|
||||||
if !CONFIG_FILE.is_empty() {
|
if !CONFIG_FILE.is_empty() {
|
||||||
InterpreterConfig::from_reader(Cursor::new(CONFIG_FILE))
|
InterpreterConfig::from_reader(Cursor::new(CONFIG_FILE))
|
||||||
|
|
Loading…
Reference in New Issue