Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

WIP: Generalize the rpath API for relocatable Python installations #4890

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ use std::env;

use pyo3_build_config::pyo3_build_script_impl::{cargo_env_var, errors::Result};
use pyo3_build_config::{
add_python_framework_link_args, bail, print_feature_cfgs, InterpreterConfig,
add_python_link_args, bail, print_feature_cfgs, InterpreterConfig,
};

fn ensure_auto_initialize_ok(interpreter_config: &InterpreterConfig) -> Result<()> {
Expand Down Expand Up @@ -44,8 +44,8 @@ fn configure_pyo3() -> Result<()> {
// Emit cfgs like `invalid_from_utf8_lint`
print_feature_cfgs();

// Make `cargo test` etc work on macOS with Xcode bundled Python
add_python_framework_link_args();
// Make `cargo test` etc work on non-global Python installations
add_python_link_args();

Ok(())
}
Expand Down
14 changes: 14 additions & 0 deletions guide/src/getting-started.md
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,9 @@ crate-type = ["cdylib"]

[dependencies]
pyo3 = { {{#PYO3_CRATE_VERSION}}, features = ["extension-module"] }

[build-dependencies]
pyo3-build-config = { {{#PYO3_CRATE_VERSION} }
```

## pyproject.toml
Expand All @@ -141,6 +144,17 @@ classifiers = [
]
```

## build.rs

Finally, in order to make `cargo test` work correctly, you should create
a `build.rs` file with the following contents:

```
fn main() {
pyo3_build_config::add_python_link_args();
}
```

## Running code

After this you can setup Rust code to be available in Python as below; for example, you can place this code in `src/lib.rs`:
Expand Down
81 changes: 80 additions & 1 deletion pyo3-build-config/src/impl_.rs
Original file line number Diff line number Diff line change
Expand Up @@ -167,8 +167,12 @@ pub struct InterpreterConfig {
///
/// Serialized to multiple `extra_build_script_line` values.
pub extra_build_script_lines: Vec<String>,

/// macOS Python3.framework requires special rpath handling
pub python_framework_prefix: Option<String>,

/// Relocatable Python installations require special rpath handling
pub relocatable: bool,
}

impl InterpreterConfig {
Expand Down Expand Up @@ -265,6 +269,7 @@ print("calcsize_pointer", struct.calcsize("P"))
print("mingw", get_platform().startswith("mingw"))
print("ext_suffix", get_config_var("EXT_SUFFIX"))
print("gil_disabled", get_config_var("Py_GIL_DISABLED"))
print_if_set("python_build_standalone", get_config_var("PYTHON_BUILD_STANDALONE"))
"#;
let output = run_python_script(interpreter.as_ref(), SCRIPT)?;
let map: HashMap<String, String> = parse_script_output(&output);
Expand Down Expand Up @@ -315,6 +320,13 @@ print("gil_disabled", get_config_var("Py_GIL_DISABLED"))
_ => panic!("Unknown Py_GIL_DISABLED value"),
};

let relocatable = match map.get("python_build_standalone").map(String::as_str) {
None => false,
Some("0") => false,
Some("1") => true,
_ => panic!("Unknown PYTHON_BUILD_STANDALONE value"),
};

let lib_name = if cfg!(windows) {
default_lib_name_windows(
version,
Expand Down Expand Up @@ -365,6 +377,7 @@ print("gil_disabled", get_config_var("Py_GIL_DISABLED"))
suppress_build_script_link_lines: false,
extra_build_script_lines: vec![],
python_framework_prefix,
relocatable,
})
}

Expand Down Expand Up @@ -410,6 +423,10 @@ print("gil_disabled", get_config_var("Py_GIL_DISABLED"))
Some(value) => value == "1",
None => false,
};
let relocatable = match sysconfigdata.get_value("python_build_standalone") {
Some(value) => value == "1",
None => false,
};
let lib_name = Some(default_lib_name_unix(
version,
implementation,
Expand All @@ -434,6 +451,7 @@ print("gil_disabled", get_config_var("Py_GIL_DISABLED"))
suppress_build_script_link_lines: false,
extra_build_script_lines: vec![],
python_framework_prefix,
relocatable,
})
}

Expand Down Expand Up @@ -511,6 +529,7 @@ print("gil_disabled", get_config_var("Py_GIL_DISABLED"))
let mut suppress_build_script_link_lines = None;
let mut extra_build_script_lines = vec![];
let mut python_framework_prefix = None;
let mut relocatable = None;

for (i, line) in lines.enumerate() {
let line = line.context("failed to read line from config")?;
Expand Down Expand Up @@ -540,6 +559,7 @@ print("gil_disabled", get_config_var("Py_GIL_DISABLED"))
extra_build_script_lines.push(value.to_string());
}
"python_framework_prefix" => parse_value!(python_framework_prefix, value),
"relocatable" => parse_value!(relocatable, value),
unknown => warn!("unknown config key `{}`", unknown),
}
}
Expand Down Expand Up @@ -571,6 +591,7 @@ print("gil_disabled", get_config_var("Py_GIL_DISABLED"))
suppress_build_script_link_lines: suppress_build_script_link_lines.unwrap_or(false),
extra_build_script_lines,
python_framework_prefix,
relocatable: relocatable.unwrap_or(false),
})
}

Expand Down Expand Up @@ -663,12 +684,13 @@ print("gil_disabled", get_config_var("Py_GIL_DISABLED"))
write_option_line!(executable)?;
write_option_line!(pointer_width)?;
write_line!(build_flags)?;
write_option_line!(python_framework_prefix)?;
write_line!(suppress_build_script_link_lines)?;
for line in &self.extra_build_script_lines {
writeln!(writer, "extra_build_script_line={}", line)
.context("failed to write extra_build_script_line")?;
}
write_option_line!(python_framework_prefix)?;
write_line!(relocatable)?;
Ok(())
}

Expand Down Expand Up @@ -1601,7 +1623,10 @@ fn default_cross_compile(cross_compile_config: &CrossCompileConfig) -> Result<In
build_flags: BuildFlags::default(),
suppress_build_script_link_lines: false,
extra_build_script_lines: vec![],
// Because this is only used for extensions, we know we do not
// need any rpath handling.
python_framework_prefix: None,
relocatable: false,
})
}

Expand Down Expand Up @@ -1644,7 +1669,10 @@ fn default_abi3_config(host: &Triple, version: PythonVersion) -> Result<Interpre
build_flags: BuildFlags::default(),
suppress_build_script_link_lines: false,
extra_build_script_lines: vec![],
// Because this is only used for extensions, we know we do not
// need any rpath handling.
python_framework_prefix: None,
relocatable: false,
})
}

Expand Down Expand Up @@ -2028,6 +2056,7 @@ mod tests {
suppress_build_script_link_lines: true,
extra_build_script_lines: vec!["cargo:test1".to_string(), "cargo:test2".to_string()],
python_framework_prefix: None,
relocatable: false,
};
let mut buf: Vec<u8> = Vec::new();
config.to_writer(&mut buf).unwrap();
Expand Down Expand Up @@ -2057,6 +2086,7 @@ mod tests {
suppress_build_script_link_lines: false,
extra_build_script_lines: vec![],
python_framework_prefix: None,
relocatable: true,
};
let mut buf: Vec<u8> = Vec::new();
config.to_writer(&mut buf).unwrap();
Expand All @@ -2079,6 +2109,7 @@ mod tests {
suppress_build_script_link_lines: true,
extra_build_script_lines: vec!["cargo:test1".to_string(), "cargo:test2".to_string()],
python_framework_prefix: None,
relocatable: false,
};
let mut buf: Vec<u8> = Vec::new();
config.to_writer(&mut buf).unwrap();
Expand Down Expand Up @@ -2106,6 +2137,7 @@ mod tests {
suppress_build_script_link_lines: false,
extra_build_script_lines: vec![],
python_framework_prefix: None,
relocatable: false,
}
)
}
Expand All @@ -2129,6 +2161,7 @@ mod tests {
suppress_build_script_link_lines: false,
extra_build_script_lines: vec![],
python_framework_prefix: None,
relocatable: false,
}
)
}
Expand Down Expand Up @@ -2232,6 +2265,7 @@ mod tests {
suppress_build_script_link_lines: false,
extra_build_script_lines: vec![],
python_framework_prefix: None,
relocatable: false,
}
);
}
Expand Down Expand Up @@ -2262,6 +2296,7 @@ mod tests {
suppress_build_script_link_lines: false,
extra_build_script_lines: vec![],
python_framework_prefix: None,
relocatable: false,
}
);

Expand Down Expand Up @@ -2289,6 +2324,37 @@ mod tests {
suppress_build_script_link_lines: false,
extra_build_script_lines: vec![],
python_framework_prefix: None,
relocatable: false,
}
);
}

#[test]
fn config_from_sysconfigdata_relocatable() {
let mut sysconfigdata = Sysconfigdata::new();
sysconfigdata.insert("SOABI", "cpython-37m-x86_64-linux-gnu");
sysconfigdata.insert("VERSION", "3.7");
sysconfigdata.insert("Py_ENABLE_SHARED", "1");
sysconfigdata.insert("LIBDIR", "/home/xyz/Downloads/python/lib");
sysconfigdata.insert("LDVERSION", "3.7m");
sysconfigdata.insert("SIZEOF_VOID_P", "8");
sysconfigdata.insert("PYTHON_BUILD_STANDALONE", "1");
assert_eq!(
InterpreterConfig::from_sysconfigdata(&sysconfigdata).unwrap(),
InterpreterConfig {
abi3: false,
build_flags: BuildFlags::from_sysconfigdata(&sysconfigdata),
pointer_width: Some(64),
executable: None,
implementation: PythonImplementation::CPython,
lib_dir: Some("/home/xyz/Downloads/python/lib".into()),
lib_name: Some("python3.7m".into()),
shared: true,
version: PythonVersion::PY37,
suppress_build_script_link_lines: false,
extra_build_script_lines: vec![],
python_framework_prefix: None,
relocatable: true,
}
);
}
Expand All @@ -2313,6 +2379,7 @@ mod tests {
suppress_build_script_link_lines: false,
extra_build_script_lines: vec![],
python_framework_prefix: None,
relocatable: false,
}
);
}
Expand All @@ -2337,6 +2404,7 @@ mod tests {
suppress_build_script_link_lines: false,
extra_build_script_lines: vec![],
python_framework_prefix: None,
relocatable: false,
}
);
}
Expand Down Expand Up @@ -2372,6 +2440,7 @@ mod tests {
suppress_build_script_link_lines: false,
extra_build_script_lines: vec![],
python_framework_prefix: None,
relcoatable: false,
}
);
}
Expand Down Expand Up @@ -2407,6 +2476,7 @@ mod tests {
suppress_build_script_link_lines: false,
extra_build_script_lines: vec![],
python_framework_prefix: None,
relocatable: false,
}
);
}
Expand Down Expand Up @@ -2442,6 +2512,7 @@ mod tests {
suppress_build_script_link_lines: false,
extra_build_script_lines: vec![],
python_framework_prefix: None,
relocatable; false,
}
);
}
Expand Down Expand Up @@ -2479,6 +2550,7 @@ mod tests {
suppress_build_script_link_lines: false,
extra_build_script_lines: vec![],
python_framework_prefix: None,
relocatable: false,
}
);
}
Expand Down Expand Up @@ -2827,6 +2899,7 @@ mod tests {
suppress_build_script_link_lines: false,
extra_build_script_lines: vec![],
python_framework_prefix: None,
relocatable: false,
};

config
Expand All @@ -2850,6 +2923,7 @@ mod tests {
suppress_build_script_link_lines: false,
extra_build_script_lines: vec![],
python_framework_prefix: None,
relocatable: false,
};

assert!(config
Expand Down Expand Up @@ -2915,6 +2989,7 @@ mod tests {
suppress_build_script_link_lines: false,
extra_build_script_lines: vec![],
python_framework_prefix: None,
relocatable: false,
}
)
}
Expand Down Expand Up @@ -3040,6 +3115,7 @@ mod tests {
suppress_build_script_link_lines: false,
extra_build_script_lines: vec![],
python_framework_prefix: None,
relocatable: false,
};
assert_eq!(
interpreter_config.build_script_outputs(),
Expand Down Expand Up @@ -3080,6 +3156,7 @@ mod tests {
suppress_build_script_link_lines: false,
extra_build_script_lines: vec![],
python_framework_prefix: None,
relocatable: false,
};

assert_eq!(
Expand Down Expand Up @@ -3128,6 +3205,7 @@ mod tests {
suppress_build_script_link_lines: false,
extra_build_script_lines: vec![],
python_framework_prefix: None,
relocatable: false,
};

assert_eq!(
Expand Down Expand Up @@ -3162,6 +3240,7 @@ mod tests {
suppress_build_script_link_lines: false,
extra_build_script_lines: vec![],
python_framework_prefix: None,
relocatable: false,
};

assert_eq!(
Expand Down
Loading
Loading