Skip to content
Merged
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
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -481,7 +481,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: dtolnay/rust-toolchain@1.83.0
- uses: dtolnay/rust-toolchain@1.85.0
# Caching
- name: Cache cargo build
uses: Swatinem/rust-cache@v2
Expand Down
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ categories = [
"development-tools::ffi",
"command-line-utilities",
]
edition = "2021"
rust-version = "1.83"
edition = "2024"
rust-version = "1.85"

[[bin]]
name = "maturin"
Expand Down
36 changes: 21 additions & 15 deletions src/auditwheel/audit.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
use super::musllinux::{find_musl_libc, get_musl_version};
use super::policy::{Policy, MANYLINUX_POLICIES, MUSLLINUX_POLICIES};
use crate::auditwheel::{find_external_libs, PlatformTag};
use super::policy::{MANYLINUX_POLICIES, MUSLLINUX_POLICIES, Policy};
use crate::auditwheel::{PlatformTag, find_external_libs};
use crate::compile::BuildArtifact;
use crate::target::Target;
use anyhow::{bail, Context, Result};
use anyhow::{Context, Result, bail};
use fs_err::File;
use goblin::elf::{sym::STT_FUNC, Elf};
use goblin::elf::{Elf, sym::STT_FUNC};
use lddtree::Library;
use once_cell::sync::Lazy;
use regex::Regex;
Expand All @@ -32,19 +32,19 @@ pub enum AuditWheelError {
/// The elf file isn't manylinux/musllinux compatible. Contains the list of offending
/// libraries.
#[error(
"Your library links libpython ({0}), which libraries must not do. Have you forgotten to activate the extension-module feature?",
"Your library links libpython ({0}), which libraries must not do. Have you forgotten to activate the extension-module feature?"
)]
LinksLibPythonError(String),
/// The elf file isn't manylinux/musllinux compatible. Contains the list of offending
/// libraries.
#[error(
"Your library is not {0} compliant because it links the following forbidden libraries: {1:?}",
"Your library is not {0} compliant because it links the following forbidden libraries: {1:?}"
)]
LinksForbiddenLibrariesError(Policy, Vec<String>),
/// The elf file isn't manylinux/musllinux compatible. Contains the list of offending
/// libraries.
#[error(
"Your library is not {0} compliant because of the presence of too-recent versioned symbols: {1:?}. Consider building in a manylinux docker container",
"Your library is not {0} compliant because of the presence of too-recent versioned symbols: {1:?}. Consider building in a manylinux docker container"
)]
VersionedSymbolTooNewError(Policy, Vec<String>),
/// The elf file isn't manylinux/musllinux compatible. Contains the list of offending
Expand All @@ -55,7 +55,9 @@ pub enum AuditWheelError {
#[error("Your library is not {0} compliant because it has unsupported architecture: {1}")]
UnsupportedArchitecture(Policy, String),
/// This platform tag isn't defined by auditwheel yet
#[error("{0} compatibility policy is not defined by auditwheel yet, pass `--auditwheel=skip` to proceed anyway")]
#[error(
"{0} compatibility policy is not defined by auditwheel yet, pass `--auditwheel=skip` to proceed anyway"
)]
UndefinedPolicy(PlatformTag),
/// Failed to analyze external shared library dependencies of the wheel
#[error("Failed to analyze external shared library dependencies of the wheel")]
Expand Down Expand Up @@ -564,8 +566,8 @@ pub fn relpath(to: &Path, from: &Path) -> PathBuf {

#[cfg(test)]
mod tests {
use crate::auditwheel::audit::relpath;
use crate::Target;
use crate::auditwheel::audit::relpath;
use pretty_assertions::assert_eq;
use std::path::Path;

Expand Down Expand Up @@ -623,12 +625,16 @@ rustflags = ["-L", "dependency=/usr/local/lib", "-L", "/some/other/path", "-C",

if let Some(paths) = paths {
assert_eq!(paths.len(), 2);
assert!(paths
.iter()
.any(|p| p.to_string_lossy() == "/usr/local/lib"));
assert!(paths
.iter()
.any(|p| p.to_string_lossy() == "/some/other/path"));
assert!(
paths
.iter()
.any(|p| p.to_string_lossy() == "/usr/local/lib")
);
assert!(
paths
.iter()
.any(|p| p.to_string_lossy() == "/some/other/path")
);
} else {
// It's possible that rustflags parsing fails in some environments,
// so we just verify the function doesn't panic
Expand Down
2 changes: 1 addition & 1 deletion src/auditwheel/patchelf.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use anyhow::{bail, Context, Result};
use anyhow::{Context, Result, bail};
use std::ffi::OsStr;
use std::path::Path;
use std::process::Command;
Expand Down
2 changes: 1 addition & 1 deletion src/auditwheel/policy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ impl Policy {

#[cfg(test)]
mod tests {
use super::{Arch, Policy, MANYLINUX_POLICIES, MUSLLINUX_POLICIES};
use super::{Arch, MANYLINUX_POLICIES, MUSLLINUX_POLICIES, Policy};
use crate::PlatformTag;
use pretty_assertions::assert_eq;

Expand Down
26 changes: 16 additions & 10 deletions src/build_context.rs
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
use crate::auditwheel::{get_policy_and_libs, patchelf, relpath, AuditWheelMode};
use crate::auditwheel::{AuditWheelMode, get_policy_and_libs, patchelf, relpath};
use crate::auditwheel::{PlatformTag, Policy};
use crate::bridge::Abi3Version;
use crate::build_options::CargoOptions;
use crate::compile::{warn_missing_py_init, CompileTarget};
use crate::compile::{CompileTarget, warn_missing_py_init};
use crate::compression::CompressionOptions;
use crate::module_writer::{
add_data, write_bin, write_bindings_module, write_cffi_module, write_python_part,
write_uniffi_module, write_wasm_launcher, WheelWriter,
WheelWriter, add_data, write_bin, write_bindings_module, write_cffi_module, write_python_part,
write_uniffi_module, write_wasm_launcher,
};
use crate::project_layout::ProjectLayout;
use crate::source_distribution::source_distribution;
use crate::target::validate_wheel_filename_for_pypi;
use crate::target::{Arch, Os};
use crate::{
compile, pyproject_toml::Format, BridgeModel, BuildArtifact, Metadata24, ModuleWriter,
PyProjectToml, PythonInterpreter, Target,
BridgeModel, BuildArtifact, Metadata24, ModuleWriter, PyProjectToml, PythonInterpreter, Target,
compile, pyproject_toml::Format,
};
use anyhow::{anyhow, bail, Context, Result};
use anyhow::{Context, Result, anyhow, bail};
use cargo_metadata::CrateType;
use cargo_metadata::Metadata;
use fs_err as fs;
Expand Down Expand Up @@ -399,15 +399,19 @@ impl BuildContext {
}

if matches!(self.auditwheel, AuditWheelMode::Check) {
eprintln!("🖨️ Your library is not manylinux/musllinux compliant because it requires copying the following libraries:");
eprintln!(
"🖨️ Your library is not manylinux/musllinux compliant because it requires copying the following libraries:"
);
for lib in ext_libs.iter().flatten() {
if let Some(path) = lib.realpath.as_ref() {
eprintln!(" {} => {}", lib.name, path.display())
} else {
eprintln!(" {} => not found", lib.name)
};
}
bail!("Can not repair the wheel because `--auditwheel=check` is specified, re-run with `--auditwheel=repair` to copy the libraries.");
bail!(
"Can not repair the wheel because `--auditwheel=check` is specified, re-run with `--auditwheel=repair` to copy the libraries."
);
}

patchelf::verify_patchelf()?;
Expand Down Expand Up @@ -573,7 +577,9 @@ impl BuildContext {
pub fn get_platform_tag(&self, platform_tags: &[PlatformTag]) -> Result<String> {
if let Ok(host_platform) = env::var("_PYTHON_HOST_PLATFORM") {
let override_platform = host_platform.replace(['.', '-'], "_");
eprintln!("🚉 Overriding platform tag from _PYTHON_HOST_PLATFORM environment variable as {override_platform}.");
eprintln!(
"🚉 Overriding platform tag from _PYTHON_HOST_PLATFORM environment variable as {override_platform}."
);
return Ok(override_platform);
}

Expand Down
96 changes: 62 additions & 34 deletions src/build_options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ use crate::target::{
detect_arch_from_python, detect_target_from_cross_python, is_arch_supported_by_pypi,
};
use crate::{BridgeModel, BuildContext, PyO3, PythonInterpreter, Target};
use anyhow::{bail, format_err, Context, Result};
use anyhow::{Context, Result, bail, format_err};
use cargo_metadata::{CrateType, PackageId, TargetKind};
use cargo_metadata::{Metadata, Node};
use cargo_options::heading;
Expand Down Expand Up @@ -274,16 +274,19 @@ impl BuildOptions {
"🐍 Using host {host_python} for cross-compiling preparation"
);
// pyo3
env::set_var("PYO3_PYTHON", &host_python.executable);
// legacy pyo3 versions
env::set_var("PYTHON_SYS_EXECUTABLE", &host_python.executable);
unsafe {
env::set_var("PYO3_PYTHON", &host_python.executable);
env::set_var("PYTHON_SYS_EXECUTABLE", &host_python.executable)
};

let sysconfig_path =
find_sysconfigdata(cross_lib_dir.as_ref(), target)?;
env::set_var(
"MATURIN_PYTHON_SYSCONFIGDATA_DIR",
sysconfig_path.parent().unwrap(),
);
unsafe {
env::set_var(
"MATURIN_PYTHON_SYSCONFIGDATA_DIR",
sysconfig_path.parent().unwrap(),
)
};

let sysconfig_data =
parse_sysconfigdata(host_python, sysconfig_path)?;
Expand Down Expand Up @@ -342,7 +345,9 @@ impl BuildOptions {
});
} else {
if interpreter.is_empty() && !self.find_interpreter {
bail!("Couldn't find any python interpreters. Please specify at least one with -i");
bail!(
"Couldn't find any python interpreters. Please specify at least one with -i"
);
}
for interp in interpreter {
// If `-i` looks like a file path, check if it's a valid interpreter
Expand Down Expand Up @@ -445,7 +450,9 @@ impl BuildOptions {
.context("Invalid PYO3_CONFIG_FILE")?;
Ok(vec![PythonInterpreter::from_config(interpreter_config)])
} else if generate_import_lib {
eprintln!("🐍 Not using a specific python interpreter (automatically generating windows import library)");
eprintln!(
"🐍 Not using a specific python interpreter (automatically generating windows import library)"
);
let mut found_interpreters = found_interpreters;
// fake a python interpreter if none directly found
if found_interpreters.is_empty() {
Expand Down Expand Up @@ -642,11 +649,7 @@ impl BuildContextBuilder {
.split("-arch")
.filter_map(|x| {
let x = x.trim();
if x.is_empty() {
None
} else {
Some(x)
}
if x.is_empty() { None } else { Some(x) }
})
.collect();
match (arches.contains("x86_64"), arches.contains("arm64")) {
Expand Down Expand Up @@ -817,7 +820,9 @@ impl BuildContextBuilder {
let compile_targets =
filter_cargo_targets(&cargo_metadata, bridge, config_targets.as_deref())?;
if compile_targets.is_empty() {
bail!("No Cargo targets to build, please check your bindings configuration in pyproject.toml.");
bail!(
"No Cargo targets to build, please check your bindings configuration in pyproject.toml."
);
}

let crate_name = cargo_toml.package.name;
Expand Down Expand Up @@ -1219,20 +1224,29 @@ pub fn find_bridge(cargo_metadata: &Metadata, bridge: Option<&str>) -> Result<Br
let bindings = find_pyo3_bindings(&deps, &packages)?.context("unknown binding type")?;
BridgeModel::PyO3(bindings)
}
} else if let Some(bindings) = find_pyo3_bindings(&deps, &packages)? {
if !targets.contains(&CrateType::CDyLib) && targets.contains(&CrateType::Bin) {
BridgeModel::Bin(Some(bindings))
} else {
BridgeModel::PyO3(bindings)
}
} else if deps.contains_key("uniffi") {
BridgeModel::UniFfi
} else if targets.contains(&CrateType::CDyLib) {
BridgeModel::Cffi
} else if targets.contains(&CrateType::Bin) {
BridgeModel::Bin(find_pyo3_bindings(&deps, &packages)?)
} else {
bail!("Couldn't detect the binding type; Please specify them with --bindings/-b")
match find_pyo3_bindings(&deps, &packages)? {
Some(bindings) => {
if !targets.contains(&CrateType::CDyLib) && targets.contains(&CrateType::Bin) {
BridgeModel::Bin(Some(bindings))
} else {
BridgeModel::PyO3(bindings)
}
}
_ => {
if deps.contains_key("uniffi") {
BridgeModel::UniFfi
} else if targets.contains(&CrateType::CDyLib) {
BridgeModel::Cffi
} else if targets.contains(&CrateType::Bin) {
BridgeModel::Bin(find_pyo3_bindings(&deps, &packages)?)
} else {
bail!(
"Couldn't detect the binding type; Please specify them with --bindings/-b"
)
}
}
}
};

if !bridge.is_pyo3() {
Expand Down Expand Up @@ -1330,7 +1344,9 @@ fn find_interpreter(
.iter()
.map(|i| format!("{} {}.{}", i.interpreter_kind, i.major, i.minor))
.collect::<Vec<_>>();
bail!("Interpreters {found:?} were found in maturin's bundled sysconfig, but compiling for Windows without an interpreter requires PyO3's `generate-import-lib` feature");
bail!(
"Interpreters {found:?} were found in maturin's bundled sysconfig, but compiling for Windows without an interpreter requires PyO3's `generate-import-lib` feature"
);
}

found_interpreters.extend(sysconfig_interps);
Expand All @@ -1343,7 +1359,10 @@ fn find_interpreter(
if found_interpreters.is_empty() {
if interpreter.is_empty() {
if let Some(requires_python) = requires_python {
bail!("Couldn't find any python interpreters with version {}. Please specify at least one with -i", requires_python);
bail!(
"Couldn't find any python interpreters with version {}. Please specify at least one with -i",
requires_python
);
} else {
bail!("Couldn't find any python interpreters. Please specify at least one with -i");
}
Expand Down Expand Up @@ -1378,7 +1397,10 @@ fn find_interpreter_in_host(

if interpreters.is_empty() {
if let Some(requires_python) = requires_python {
bail!("Couldn't find any python interpreters with {}. Please specify at least one with -i", requires_python);
bail!(
"Couldn't find any python interpreters with {}. Please specify at least one with -i",
requires_python
);
} else {
bail!("Couldn't find any python interpreters. Please specify at least one with -i");
}
Expand Down Expand Up @@ -1431,9 +1453,15 @@ fn find_interpreter_in_sysconfig(
} else {
// if interpreter not known
if std::path::Path::new(&python).is_file() {
bail!("Python interpreter should be a kind of interpreter (e.g. 'python3.14' or 'pypy3.11') when cross-compiling, got path to interpreter: {}", python);
bail!(
"Python interpreter should be a kind of interpreter (e.g. 'python3.14' or 'pypy3.11') when cross-compiling, got path to interpreter: {}",
python
);
} else {
bail!("Unsupported Python interpreter for cross-compilation: {}; supported interpreters are pypy, graalpy, and python (cpython)", python);
bail!(
"Unsupported Python interpreter for cross-compilation: {}; supported interpreters are pypy, graalpy, and python (cpython)",
python
);
}
};
if python_ver.is_empty() {
Expand Down
2 changes: 1 addition & 1 deletion src/cargo_toml.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use anyhow::{bail, Context, Result};
use anyhow::{Context, Result, bail};
use fs_err as fs;
use serde::{Deserialize, Serialize};
use std::collections::HashMap;
Expand Down
6 changes: 3 additions & 3 deletions src/ci.rs
Original file line number Diff line number Diff line change
Expand Up @@ -672,7 +672,7 @@ jobs:\n",
#[cfg(test)]
mod tests {
use super::GenerateCI;
use crate::{bridge::PyO3Crate, Abi3Version, BridgeModel, PyO3};
use crate::{Abi3Version, BridgeModel, PyO3, bridge::PyO3Crate};
use expect_test::expect;
use semver::Version;

Expand Down Expand Up @@ -1299,12 +1299,12 @@ mod tests {

#[test]
fn test_generate_github_zig_pytest() {
let gen = GenerateCI {
let r#gen = GenerateCI {
zig: true,
pytest: true,
..Default::default()
};
let conf = gen
let conf = r#gen
.generate_github(
"example",
&BridgeModel::PyO3(PyO3 {
Expand Down
4 changes: 2 additions & 2 deletions src/compile.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use crate::target::RUST_1_64_0;
#[cfg(feature = "zig")]
use crate::PlatformTag;
use crate::target::RUST_1_64_0;
use crate::{BridgeModel, BuildContext, PythonInterpreter, Target};
use anyhow::{anyhow, bail, Context, Result};
use anyhow::{Context, Result, anyhow, bail};
use cargo_metadata::CrateType;
use fat_macho::FatWriter;
use fs_err::{self as fs, File};
Expand Down
Loading
Loading