Add export-config feature to pyo3-build-config.

This commit is contained in:
Ashley Anderson 2022-01-07 20:44:36 -05:00
parent 3eb654c81c
commit 755bf97fdb
2 changed files with 75 additions and 1 deletions

View File

@ -20,6 +20,9 @@ default = []
# script. If this feature isn't enabled, the build script no-ops.
resolve-config = []
# Export the resolved build config into a file for use by e.g. other build scripts.
export-config = ["resolve-config"]
abi3 = []
abi3-py37 = ["abi3-py38"]
abi3-py38 = ["abi3-py39"]

View File

@ -4,7 +4,7 @@ use std::{
env,
ffi::{OsStr, OsString},
fmt::Display,
fs::{self, DirEntry},
fs::{self, DirEntry, File},
io::{BufRead, BufReader, Read, Write},
path::{Path, PathBuf},
process::{Command, Stdio},
@ -21,6 +21,8 @@ use crate::{
const MINIMUM_SUPPORTED_VERSION: PythonVersion = PythonVersion { major: 3, minor: 7 };
/// Maximum Python version that can be used as minimum required Python version with abi3.
const ABI3_MAX_MINOR: u8 = 9;
/// Name of config file exported by "export-config" feature.
const EXPORT_CONFIG_FILENAME: &str = ".pyo3-export-config";
/// Gets an environment variable owned by cargo.
///
@ -155,6 +157,24 @@ impl InterpreterConfig {
for flag in &self.build_flags.0 {
println!("cargo:rustc-cfg=py_sys_config=\"{}\"", flag)
}
if cfg!(feature = "export-config") {
let output_path =
Path::new(&cargo_env_var("OUT_DIR").unwrap()).join(EXPORT_CONFIG_FILENAME);
if let Ok(config_file) = File::create(&output_path) {
if self.to_writer(config_file).is_err() {
warn!(
"Failed to export build config - this may be a problem for external crates that \
depend on the pyo3 config."
);
} else {
println!(
"cargo:PYO3_EXPORT_CONFIG={}",
output_path.canonicalize().unwrap().to_str().unwrap()
);
}
}
}
}
#[doc(hidden)]
@ -339,6 +359,14 @@ print("mingw", get_platform().startswith("mingw"))
InterpreterConfig::from_reader(reader)
}
/// Create an InterpreterConfig generated from pyo3-build-config using the "export-config"
/// feature
pub fn from_pyo3_export_config() -> Result<Self> {
InterpreterConfig::from_path(Path::new(
&cargo_env_var("DEP_PYTHON_PYO3_EXPORT_CONFIG").unwrap(),
))
}
#[doc(hidden)]
pub fn from_reader(reader: impl Read) -> Result<Self> {
let reader = BufReader::new(reader);
@ -461,6 +489,37 @@ print("mingw", get_platform().startswith("mingw"))
}
Ok(())
}
/// Run a python script using the executable of this InterpreterConfig with additional
/// environment variables (e.g. PYTHONPATH) set.
pub fn run_python_script_with_envs<I, K, V>(&self, script: &str, envs: I) -> Result<String>
where
I: IntoIterator<Item = (K, V)>,
K: AsRef<OsStr>,
V: AsRef<OsStr>,
{
run_python_script_with_envs(
Path::new(
self.executable
.as_ref()
.expect("No interpreter executable!"),
),
script,
envs,
)
}
/// Run a python script using the executable of this InterpreterConfig.
pub fn run_python_script(&self, script: &str) -> Result<String> {
run_python_script(
Path::new(
self.executable
.as_ref()
.expect("No interpreter executable!"),
),
script,
)
}
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord)]
@ -1183,8 +1242,20 @@ fn default_lib_name_unix(
/// Run a python script using the specified interpreter binary.
fn run_python_script(interpreter: &Path, script: &str) -> Result<String> {
run_python_script_with_envs(interpreter, script, std::iter::empty::<(&str, &str)>())
}
/// Run a python script using the specified interpreter binary with additional environment
/// variables (e.g. PYTHONPATH) set.
fn run_python_script_with_envs<I, K, V>(interpreter: &Path, script: &str, envs: I) -> Result<String>
where
I: IntoIterator<Item = (K, V)>,
K: AsRef<OsStr>,
V: AsRef<OsStr>,
{
let out = Command::new(interpreter)
.env("PYTHONIOENCODING", "utf-8")
.envs(envs)
.stdin(Stdio::piped())
.stdout(Stdio::piped())
.stderr(Stdio::inherit())