diff --git a/Changelog.md b/Changelog.md index 7124c8325..36dd7ba3a 100644 --- a/Changelog.md +++ b/Changelog.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 * Add Linux armv7l python sysconfig in [#901](https://github.com/PyO3/maturin/pull/901) * Add NetBSD python sysconfig in [#903](https://github.com/PyO3/maturin/pull/903) +* Update 'replace_needed' to reduce total calls to 'patchelf' in [#905](https://github.com/PyO3/maturin/pull/905) ## [0.12.15] - 2022-05-07 diff --git a/src/auditwheel/patchelf.rs b/src/auditwheel/patchelf.rs index f3cd2a1ad..181e40917 100644 --- a/src/auditwheel/patchelf.rs +++ b/src/auditwheel/patchelf.rs @@ -4,16 +4,15 @@ use std::path::Path; use std::process::Command; /// Replace a declared dependency on a dynamic library with another one (`DT_NEEDED`) -pub fn replace_needed>( +pub fn replace_needed, N: AsRef>( file: impl AsRef, - old_lib: &str, - new_lib: &S, + old_new_pairs: &[(O, N)], ) -> Result<()> { let mut cmd = Command::new("patchelf"); - cmd.arg("--replace-needed") - .arg(old_lib) - .arg(new_lib) - .arg(file.as_ref()); + for (old, new) in old_new_pairs { + cmd.arg("--replace-needed").arg(old).arg(new); + } + cmd.arg(file.as_ref()); let output = cmd .output() .context("Failed to execute 'patchelf', did you install it? Hint: Try `pip install maturin[patchelf]` (or just `pip install patchelf`)")?; diff --git a/src/build_context.rs b/src/build_context.rs index 73858da53..b4e21f555 100644 --- a/src/build_context.rs +++ b/src/build_context.rs @@ -309,23 +309,34 @@ impl BuildContext { if !lib.rpath.is_empty() || !lib.runpath.is_empty() { patchelf::set_rpath(&dest_path, &libs_dir)?; } - patchelf::replace_needed(artifact, &lib.name, &new_soname)?; soname_map.insert( lib.name.clone(), (new_soname.clone(), dest_path.clone(), lib.needed.clone()), ); } + let replacements = soname_map + .iter() + .map(|(k, v)| (k, v.0.clone())) + .collect::>(); + if !replacements.is_empty() { + patchelf::replace_needed(artifact, &replacements[..])?; + } + // we grafted in a bunch of libraries and modified their sonames, but // they may have internal dependencies (DT_NEEDED) on one another, so // we need to update those records so each now knows about the new // name of the other. for (new_soname, path, needed) in soname_map.values() { + let mut replacements = Vec::new(); for n in needed { if soname_map.contains_key(n) { - patchelf::replace_needed(path, n, &soname_map[n].0)?; + replacements.push((n, soname_map[n].0.clone())); } } + if !replacements.is_empty() { + patchelf::replace_needed(artifact, &replacements[..])?; + } writer.add_file_with_permissions(libs_dir.join(new_soname), path, 0o755)?; }