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

Add auditwheel support for musllinux #597

Merged
merged 2 commits into from
Aug 25, 2021
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
1 change: 1 addition & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]

* Add path option for Python source in [#584](https://github.com/PyO3/maturin/pull/584)
* Add auditwheel support for musllinux in [#597](https://github.com/PyO3/maturin/pull/597)
* `[tool.maturin]` options from `pyproject.toml` will be used automatically in [#605](https://github.com/PyO3/maturin/pull/605)
* Skip unavailable Python interpreters from pyenv in [#609](https://github.com/PyO3/maturin/pull/609)

Expand Down
46 changes: 31 additions & 15 deletions src/auditwheel/audit.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use super::policy::{Policy, POLICIES};
use super::policy::{Policy, MANYLINUX_POLICIES, MUSLLINUX_POLICIES};
use crate::auditwheel::PlatformTag;
use crate::Target;
use crate::target::{Arch, Target};
use anyhow::Result;
use fs_err::File;
use goblin::elf::{sym::STT_FUNC, Elf};
Expand Down Expand Up @@ -253,18 +253,6 @@ pub fn auditwheel_rs(
if !target.is_linux() || platform_tag == Some(PlatformTag::Linux) {
return Ok(Policy::default());
}
if let Some(musl_tag @ PlatformTag::Musllinux { .. }) = platform_tag {
// TODO: add support for musllinux: https://github.com/pypa/auditwheel/issues/305
eprintln!("⚠️ Warning: no auditwheel support for musllinux yet");
// HACK: fake a musllinux policy
return Ok(Policy {
name: musl_tag.to_string(),
aliases: Vec::new(),
priority: 0,
symbol_versions: Default::default(),
lib_whitelist: Default::default(),
});
}
let arch = target.target_arch().to_string();
let mut file = File::open(path).map_err(AuditWheelError::IoError)?;
let mut buffer = Vec::new();
Expand All @@ -276,8 +264,36 @@ pub fn auditwheel_rs(
let versioned_libraries = find_versioned_libraries(&elf, &buffer)?;

// Find the highest possible policy, if any
let platform_policies = match platform_tag {
Some(PlatformTag::Manylinux { .. }) | None => MANYLINUX_POLICIES.clone(),
Some(PlatformTag::Musllinux { .. }) => {
MUSLLINUX_POLICIES
.clone()
.into_iter()
.map(|mut policy| {
// Fixup musl libc lib_whitelist
if policy.lib_whitelist.remove("libc.so") {
let new_soname = match target.target_arch() {
Arch::Aarch64 => "libc.musl-aarch64.so.1",
Arch::Armv7L => "libc.musl-armv7.so.1",
Arch::Powerpc64Le => "libc.musl-ppc64le.so.1",
Arch::Powerpc64 => "", // musllinux doesn't support ppc64
Arch::X86 => "libc.musl-x86.so.1",
Arch::X86_64 => "libc.musl-x86_64.so.1",
Arch::S390X => "libc.musl-s390x.so.1",
};
if !new_soname.is_empty() {
policy.lib_whitelist.insert(new_soname.to_string());
}
}
policy
})
.collect()
}
Some(PlatformTag::Linux) => unreachable!(),
};
let mut highest_policy = None;
for policy in POLICIES.iter() {
for policy in platform_policies.iter() {
let result = policy_is_satisfied(policy, &elf, &arch, &deps, &versioned_libraries);
match result {
Ok(_) => {
Expand Down
File renamed without changes.
2 changes: 1 addition & 1 deletion src/auditwheel/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ mod policy;

pub use self::audit::*;
pub use platform_tag::PlatformTag;
pub use policy::{Policy, POLICIES};
pub use policy::{Policy, MANYLINUX_POLICIES, MUSLLINUX_POLICIES};
48 changes: 48 additions & 0 deletions src/auditwheel/musllinux-policy.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
[
{"name": "linux",
"aliases": [],
"priority": 0,
"symbol_versions": {},
"lib_whitelist": []
},
{"name": "musllinux_1_1",
"aliases": [],
"priority": 100,
"symbol_versions": {
"i686": {
},
"x86_64": {
},
"aarch64": {
},
"ppc64le": {
},
"s390x": {
},
"armv7l": {
}
},
"lib_whitelist": [
"libc.so"
]},
{"name": "musllinux_1_2",
"aliases": [],
"priority": 90,
"symbol_versions": {
"i686": {
},
"x86_64": {
},
"aarch64": {
},
"ppc64le": {
},
"s390x": {
},
"armv7l": {
}
},
"lib_whitelist": [
"libc.so"
]}
]
48 changes: 35 additions & 13 deletions src/auditwheel/policy.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,24 @@ use std::fmt::{Display, Formatter};

/// The policies (allowed symbols) for the different manylinux tags, sorted from highest
/// priority to lowest
pub static POLICIES: Lazy<Vec<Policy>> = Lazy::new(|| {
// https://github.com/pypa/auditwheel/blob/master/auditwheel/policy/policy.json
let mut policies: Vec<Policy> = serde_json::from_slice(include_bytes!("policy.json"))
pub static MANYLINUX_POLICIES: Lazy<Vec<Policy>> = Lazy::new(|| {
// https://github.com/pypa/auditwheel/blob/master/auditwheel/policy/manylinux-policy.json
let mut policies: Vec<Policy> = serde_json::from_slice(include_bytes!("manylinux-policy.json"))
.expect("invalid manylinux policy.json file");
policies.sort_by_key(|policy| -policy.priority);
policies
});

/// The policies (allowed symbols) for the different musllinux tags, sorted from highest
/// priority to lowest
pub static MUSLLINUX_POLICIES: Lazy<Vec<Policy>> = Lazy::new(|| {
// https://github.com/pypa/auditwheel/blob/master/auditwheel/policy/musllinux-policy.json
let mut policies: Vec<Policy> = serde_json::from_slice(include_bytes!("musllinux-policy.json"))
.expect("invalid musllinux policy.json file");
policies.sort_by_key(|policy| -policy.priority);
policies
});

/// Manylinux policy
#[derive(Debug, Clone, PartialEq, Deserialize)]
pub struct Policy {
Expand All @@ -35,7 +45,7 @@ pub struct Policy {
impl Default for Policy {
fn default() -> Self {
// defaults to linux
Policy::from_priority(0).unwrap()
Policy::from_name("linux").unwrap()
}
}

Expand All @@ -62,7 +72,12 @@ impl PartialOrd for Policy {
impl Policy {
/// Get highest priority policy than self
pub fn higher_priority_policies(&self) -> impl Iterator<Item = &Policy> {
POLICIES.iter().filter(move |p| p.priority > self.priority)
let policies = if self.name.starts_with("musllinux") {
&MUSLLINUX_POLICIES
} else {
&MANYLINUX_POLICIES
};
policies.iter().filter(move |p| p.priority > self.priority)
}

/// Get platform tag from this policy
Expand All @@ -72,21 +87,21 @@ impl Policy {

/// Get policy by it's platform tag name
pub fn from_name(name: &str) -> Option<Self> {
POLICIES
let policies = if name.starts_with("musllinux") {
&MUSLLINUX_POLICIES
} else {
&MANYLINUX_POLICIES
};
policies
.iter()
.find(|p| p.name == name || p.aliases.iter().any(|alias| alias == name))
.cloned()
}

/// Get policy by it's priority
pub fn from_priority(priority: i64) -> Option<Self> {
POLICIES.iter().find(|p| p.priority == priority).cloned()
}
}

#[cfg(test)]
mod test {
use super::{Policy, POLICIES};
use super::{Policy, MANYLINUX_POLICIES, MUSLLINUX_POLICIES};

#[test]
fn test_load_policy() {
Expand All @@ -106,7 +121,14 @@ mod test {

#[test]
fn test_policy_manylinux_tag() {
for policy in POLICIES.iter() {
for policy in MANYLINUX_POLICIES.iter() {
let _tag = policy.platform_tag();
}
}

#[test]
fn test_policy_musllinux_tag() {
for policy in MUSLLINUX_POLICIES.iter() {
let _tag = policy.platform_tag();
}
}
Expand Down