Skip to content

Commit 50279e2

Browse files
committed
Handle archived dylibs on AIX
In recent Rust versions, the dylib format for AIX has changed to reflect that shared libraries on AIX are normal archived, in the Big archive format. See rust-lang/rust#132362. However, Python wheels on the platforms still use un-archived shared objects, so this change updates module_writer to unarchive the archived dylib before we copy it over to the wheel.
1 parent 5976207 commit 50279e2

File tree

2 files changed

+47
-6
lines changed

2 files changed

+47
-6
lines changed

src/module_writer.rs

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -793,6 +793,32 @@ fn handle_cffi_call_result(
793793
}
794794
}
795795

796+
// Extract the shared object from a AIX big library archive
797+
fn unpack_big_archive(
798+
target: &Target,
799+
artifact: &Path,
800+
temp_dir_path: &Path,
801+
) -> Result<PathBuf> {
802+
// Newer rust generates archived dylibs on AIX, as shared
803+
// libraries are typically archived on the platform.
804+
if target.cross_compiling() {
805+
bail!("can't unpack big archive format while cross_compiling")
806+
}
807+
debug!("Unpacking archive {}", artifact.display());
808+
let mut ar_command = Command::new("ar");
809+
ar_command
810+
.current_dir(temp_dir_path)
811+
.arg("-X64")
812+
.arg("x")
813+
.arg(artifact);
814+
let status = ar_command.status().expect("Failed to run ar");
815+
if !status.success() {
816+
bail!(r#"ar finished with "{}": `{:?}`"#, status, ar_command,)
817+
}
818+
let unpacked_artifact = temp_dir_path.join(artifact.with_extension("so").file_name().unwrap());
819+
Ok(unpacked_artifact)
820+
}
821+
796822
/// Copies the shared library into the module, which is the only extra file needed with bindings
797823
#[allow(clippy::too_many_arguments)]
798824
#[instrument(skip_all)]
@@ -825,23 +851,32 @@ pub fn write_bindings_module(
825851
python_interpreter.get_library_name(ext_name)
826852
};
827853

854+
let artifact_is_big_ar = target.is_aix() && artifact.extension().unwrap_or(OsStr::new(" ")) == OsStr::new("a");
855+
let temp_dir= if artifact_is_big_ar { Some(tempfile::tempdir()?)} else {None};
856+
let artifact_buff = if artifact_is_big_ar { Some(unpack_big_archive(target, artifact, temp_dir.as_ref().unwrap().path())?) } else { None };
857+
let artifact = if artifact_is_big_ar { artifact_buff.as_ref().unwrap() } else { artifact };
858+
828859
if !editable {
829860
write_python_part(writer, project_layout, pyproject_toml)
830861
.context("Failed to add the python module to the package")?;
831862
}
832863
if let Some(python_module) = &project_layout.python_module {
833864
if editable {
834-
let target = project_layout.rust_module.join(&so_filename);
865+
let target_file = project_layout.rust_module.join(&so_filename);
835866
// Remove existing so file to avoid triggering SIGSEV in running process
836867
// See https://github.com/PyO3/maturin/issues/758
837-
debug!("Removing {}", target.display());
838-
let _ = fs::remove_file(&target);
868+
debug!("Removing {}", target_file.display());
869+
let _ = fs::remove_file(&target_file);
839870

840-
debug!("Copying {} to {}", artifact.display(), target.display());
841-
fs::copy(artifact, &target).context(format!(
871+
debug!(
872+
"Copying {} to {}",
873+
artifact.display(),
874+
target_file.display()
875+
);
876+
fs::copy(artifact, &target_file).context(format!(
842877
"Failed to copy {} to {}",
843878
artifact.display(),
844-
target.display()
879+
target_file.display()
845880
))?;
846881
} else {
847882
let relative = project_layout

src/target.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -616,6 +616,12 @@ impl Target {
616616
self.os == Os::Hurd
617617
}
618618

619+
/// Returns true if we're building a binary for AIX
620+
#[inline]
621+
pub fn is_aix(&self) -> bool {
622+
self.os == Os::Aix
623+
}
624+
619625
/// Returns true if the current platform's target env is Musl
620626
#[inline]
621627
pub fn is_musl_libc(&self) -> bool {

0 commit comments

Comments
 (0)