Skip to content

Commit

Permalink
Use goblin instead of shelling out to patchelf to get rpath
Browse files Browse the repository at this point in the history
  • Loading branch information
messense committed Sep 27, 2022
1 parent 4d710e2 commit 5407ef8
Show file tree
Hide file tree
Showing 3 changed files with 19 additions and 20 deletions.
1 change: 1 addition & 0 deletions Changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* Fix duplicated `Cargo.toml` of local dependencies in sdist in [#1114](https://github.com/PyO3/maturin/pull/1114)
* Add support for Cargo workspace dependencies inheritance in [#1123](https://github.com/PyO3/maturin/pull/1123)
* Add support for Cargo workspace metadata inheritance in [#1131](https://github.com/PyO3/maturin/pull/1131)
* Use `goblin` instead of shelling out to `patchelf` to get rpath in [#1139](https://github.com/PyO3/maturin/pull/1139)

## [0.13.3] - 2022-09-15

Expand Down
27 changes: 14 additions & 13 deletions src/auditwheel/patchelf.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,18 +78,19 @@ pub fn set_rpath<S: AsRef<OsStr>>(file: impl AsRef<Path>, rpath: &S) -> Result<(
}

/// Get the `RPATH` of executables and libraries
pub fn get_rpath(file: impl AsRef<Path>) -> Result<String> {
let mut cmd = Command::new("patchelf");
cmd.arg("--print-rpath").arg(file.as_ref());
let output = cmd
.output()
.context("Failed to execute 'patchelf', did you install it?")?;
if !output.status.success() {
bail!(
"patchelf --print-rpath failed: {}",
String::from_utf8_lossy(&output.stderr)
);
pub fn get_rpath(file: impl AsRef<Path>) -> Result<Vec<String>> {
let file = file.as_ref();
let contents = fs_err::read(&file)?;
match goblin::Object::parse(&contents) {
Ok(goblin::Object::Elf(elf)) => {
let rpaths = if !elf.runpaths.is_empty() {
elf.runpaths
} else {
elf.rpaths
};
Ok(rpaths.iter().map(|r| r.to_string()).collect())
}
Ok(_) => bail!("'{}' is not an ELF file", file.display()),
Err(e) => bail!("Failed to parse ELF file at '{}': {}", file.display(), e),
}
let rpath = String::from_utf8(output.stdout)?;
Ok(rpath.trim().to_string())
}
11 changes: 4 additions & 7 deletions src/build_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -240,11 +240,10 @@ impl BuildContext {
continue;
}
let old_rpaths = patchelf::get_rpath(&artifact.path)?;
let mut new_rpaths: Vec<&str> =
old_rpaths.split(':').filter(|r| !r.is_empty()).collect();
let mut new_rpaths = old_rpaths.clone();
for path in &artifact.linked_paths {
if !old_rpaths.contains(path) {
new_rpaths.push(path);
new_rpaths.push(path.to_string());
}
}
let new_rpath = new_rpaths.join(":");
Expand Down Expand Up @@ -364,13 +363,11 @@ impl BuildContext {
// Currently artifact .so file always resides at ${module_name}/${module_name}.so
let artifact_dir = Path::new(&self.module_name);
for artifact in artifacts {
let old_rpaths = patchelf::get_rpath(&artifact.path)?;
let mut new_rpaths = patchelf::get_rpath(&artifact.path)?;
// TODO: clean existing rpath entries if it's not pointed to a location within the wheel
// See https://github.com/pypa/auditwheel/blob/353c24250d66951d5ac7e60b97471a6da76c123f/src/auditwheel/repair.py#L160
let mut new_rpaths: Vec<&str> =
old_rpaths.split(':').filter(|r| !r.is_empty()).collect();
let new_rpath = Path::new("$ORIGIN").join(relpath(&libs_dir, artifact_dir));
new_rpaths.push(new_rpath.to_str().unwrap());
new_rpaths.push(new_rpath.to_str().unwrap().to_string());
let new_rpath = new_rpaths.join(":");
patchelf::set_rpath(&artifact.path, &new_rpath)?;
}
Expand Down

0 comments on commit 5407ef8

Please sign in to comment.