Skip to content

Commit 92d1e55

Browse files
authored
Merge pull request #754 from messense/cross-repair
Add support for repairing cross compiled linux wheels
2 parents 72fd0e7 + 2c875db commit 92d1e55

File tree

7 files changed

+76
-46
lines changed

7 files changed

+76
-46
lines changed

Cargo.lock

Lines changed: 12 additions & 21 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,8 @@ ignore = "0.4.18"
5757
dialoguer = "0.9.0"
5858
console = "0.15.0"
5959
minijinja = "0.8.2"
60-
lddtree = "0.1.4"
60+
lddtree = "0.2.0"
61+
cc = "1.0.72"
6162

6263
[dev-dependencies]
6364
indoc = "1.0.3"

Changelog.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
* Add support for repairing cross compiled linux wheels in [#754](https://github.com/PyO3/maturin/pull/754)
11+
1012
## [0.12.5] - 2021-12-20
1113

1214
* Fix docs for `new` and `init` commands in `maturin --help` in [#734](https://github.com/PyO3/maturin/pull/734)

src/auditwheel/audit.rs

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,6 @@ pub fn auditwheel_rs(
256256
if !target.is_linux() || platform_tag == Some(PlatformTag::Linux) {
257257
return Ok((Policy::default(), false));
258258
}
259-
let cross_compiling = target.cross_compiling();
260259
let arch = target.target_arch().to_string();
261260
let mut file = File::open(path).map_err(AuditWheelError::IoError)?;
262261
let mut buffer = Vec::new();
@@ -300,15 +299,10 @@ pub fn auditwheel_rs(
300299
should_repair = false;
301300
break;
302301
}
303-
Err(err @ AuditWheelError::LinksForbiddenLibrariesError(..)) => {
304-
// TODO: support repair for cross compiled wheels
305-
if !cross_compiling {
306-
highest_policy = Some(policy.clone());
307-
should_repair = true;
308-
break;
309-
} else {
310-
return Err(err);
311-
}
302+
Err(AuditWheelError::LinksForbiddenLibrariesError(..)) => {
303+
highest_policy = Some(policy.clone());
304+
should_repair = true;
305+
break;
312306
}
313307
Err(AuditWheelError::VersionedSymbolTooNewError(..))
314308
| Err(AuditWheelError::BlackListedSymbolsError(..))
@@ -340,14 +334,9 @@ pub fn auditwheel_rs(
340334
should_repair = false;
341335
Ok(policy)
342336
}
343-
Err(err @ AuditWheelError::LinksForbiddenLibrariesError(..)) => {
344-
// TODO: support repair for cross compiled wheels
345-
if !cross_compiling {
346-
should_repair = true;
347-
Ok(policy)
348-
} else {
349-
Err(err)
350-
}
337+
Err(AuditWheelError::LinksForbiddenLibrariesError(..)) => {
338+
should_repair = true;
339+
Ok(policy)
351340
}
352341
Err(err) => Err(err),
353342
}

src/auditwheel/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,4 +8,4 @@ mod repair;
88
pub use audit::*;
99
pub use platform_tag::PlatformTag;
1010
pub use policy::{Policy, MANYLINUX_POLICIES, MUSLLINUX_POLICIES};
11-
pub use repair::{get_external_libs, hash_file};
11+
pub use repair::{find_external_libs, hash_file};

src/auditwheel/repair.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@ use fs_err as fs;
55
use lddtree::DependencyAnalyzer;
66
use sha2::{Digest, Sha256};
77
use std::io;
8-
use std::path::Path;
8+
use std::path::{Path, PathBuf};
99

10-
pub fn get_external_libs(
10+
pub fn find_external_libs(
1111
artifact: impl AsRef<Path>,
1212
policy: &Policy,
13+
sysroot: PathBuf,
1314
) -> Result<Vec<lddtree::Library>, AuditWheelError> {
14-
let dep_analyzer = DependencyAnalyzer::new();
15+
let dep_analyzer = DependencyAnalyzer::new(sysroot);
1516
let deps = dep_analyzer.analyze(artifact).unwrap();
1617
let mut ext_libs = Vec::new();
1718
for (name, lib) in deps.libraries {

src/build_context.rs

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::auditwheel::{
2-
auditwheel_rs, get_external_libs, hash_file, patchelf, PlatformTag, Policy,
2+
auditwheel_rs, find_external_libs, hash_file, patchelf, PlatformTag, Policy,
33
};
44
use crate::compile::warn_missing_py_init;
55
use crate::module_writer::{
@@ -15,6 +15,7 @@ use lddtree::Library;
1515
use std::borrow::Cow;
1616
use std::collections::HashMap;
1717
use std::path::{Path, PathBuf};
18+
use std::process::{Command, Stdio};
1819

1920
/// The way the rust code is used in the wheel
2021
#[derive(Clone, Debug, PartialEq, Eq)]
@@ -272,7 +273,8 @@ impl BuildContext {
272273
}
273274
})?;
274275
let external_libs = if should_repair && !self.editable {
275-
get_external_libs(&artifact, &policy).with_context(|| {
276+
let sysroot = get_sysroot_path(&self.target)?;
277+
find_external_libs(&artifact, &policy, sysroot).with_context(|| {
276278
if let Some(platform_tag) = platform_tag {
277279
format!("Error repairing wheel for {} compliance", platform_tag)
278280
} else {
@@ -685,6 +687,50 @@ fn relpath(to: &Path, from: &Path) -> PathBuf {
685687
result
686688
}
687689

690+
/// Get sysroot path from target C compiler
691+
///
692+
/// Currently only gcc is supported, clang doesn't have a `--print-sysroot` option
693+
/// TODO: allow specify sysroot from environment variable?
694+
fn get_sysroot_path(target: &Target) -> Result<PathBuf> {
695+
use crate::target::get_host_target;
696+
697+
let host_triple = get_host_target()?;
698+
let target_triple = target.target_triple();
699+
if host_triple != target_triple {
700+
let mut build = cc::Build::new();
701+
build
702+
// Suppress cargo metadata for example env vars printing
703+
.cargo_metadata(false)
704+
// opt_level, host and target are required
705+
.opt_level(0)
706+
.host(&host_triple)
707+
.target(target_triple);
708+
let compiler = build
709+
.try_get_compiler()
710+
.with_context(|| format!("Failed to get compiler for {}", target_triple))?;
711+
let path = compiler.path();
712+
let out = Command::new(path)
713+
.arg("--print-sysroot")
714+
.stdout(Stdio::piped())
715+
.stderr(Stdio::null())
716+
.output()
717+
.with_context(|| format!("Failed to run `{} --print-sysroot`", path.display()))?;
718+
if out.status.success() {
719+
let sysroot = String::from_utf8(out.stdout)
720+
.context("Failed to read the sysroot path")?
721+
.trim()
722+
.to_owned();
723+
return Ok(PathBuf::from(sysroot));
724+
} else {
725+
bail!(
726+
"Failed to get the sysroot path: {}",
727+
String::from_utf8(out.stderr)?
728+
);
729+
}
730+
}
731+
Ok(PathBuf::from("/"))
732+
}
733+
688734
#[cfg(test)]
689735
mod test {
690736
use super::relpath;

0 commit comments

Comments
 (0)