Skip to content

Commit 1b7a198

Browse files
committed
Give _tkinter $ORIGIN-relative dependencies on glibc and an rpath on musl
Partially addresses #742 and makes it consistent with what we're doing on macOS. There's an argument in the comments above that we should not set an rpath on libpython (except on musl where it's needed), and I need to see if I still believe that. In the meantime I'm following that pattern and setting $ORIGIN-relative NEEDED on glibc and rpath on musl only. This also adds a specific ldd regression test but not the additional tests listed in #742.
1 parent 51d355f commit 1b7a198

File tree

2 files changed

+50
-0
lines changed

2 files changed

+50
-0
lines changed

cpython-unix/build-cpython.sh

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -821,6 +821,25 @@ if [ "${PYBUILD_SHARED}" = "1" ]; then
821821
${ROOT}/out/python/install/lib/libpython3.so
822822
fi
823823
fi
824+
825+
# PyInstaller would like to see `ldd` work on modules.
826+
# https://github.com/pyinstaller/pyinstaller/issues/9204#issuecomment-3171583553
827+
# Also this probably helps programs linking libpython avoid having to set an rpath.
828+
patchelf_args=()
829+
if [ "${CC}" == "musl-clang" ]; then
830+
patchelf_args+=(--set-rpath '${ORIGIN}/../..')
831+
else
832+
for lib in ${ROOT}/out/python/install/lib/*; do
833+
basename=${lib##*/}
834+
patchelf_args+=(--replace-needed "$basename" '${ORIGIN}/../../'"$basename")
835+
done
836+
fi
837+
# At the moment, python3 and libpython don't have shared-library
838+
# dependencies, but at some point we will want to run this for
839+
# them too.
840+
for module in ${ROOT}/out/python/install/lib/python*/lib-dynload/*.so; do
841+
patchelf "${patchelf_args[@]}" "$module"
842+
done
824843
fi
825844
fi
826845

src/validation.rs

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2186,6 +2186,37 @@ fn verify_distribution_behavior(dist_path: &Path) -> Result<Vec<String>> {
21862186
errors.push("errors running interpreter tests".to_string());
21872187
}
21882188

2189+
// Explicitly test ldd directly on the extension modules, which PyInstaller
2190+
// relies on. This is not strictly needed for a working distribution (e.g.
2191+
// you can set an rpath on just python+libpython), so we test here for
2192+
// compatibility with tools that run ldd.
2193+
// that fails this check (e.g. by setting an rpath on just python+libpython).
2194+
// https://github.com/pyinstaller/pyinstaller/issues/9204#issuecomment-3171050891
2195+
if cfg!(target_os = "linux") {
2196+
for (name, variants) in python_json.build_info.extensions.iter() {
2197+
if name == "_crypt" {
2198+
// Our test environment may lack libcrypt (and _crypt is
2199+
// split out specifically because of this problem).
2200+
continue;
2201+
}
2202+
for ext in variants {
2203+
let Some(shared_lib) = &ext.shared_lib else {
2204+
continue;
2205+
};
2206+
let shared_lib_path = temp_dir.path().join("python").join(shared_lib);
2207+
let output = duct::cmd("ldd", [shared_lib_path])
2208+
.unchecked()
2209+
.stdout_capture()
2210+
.run()
2211+
.context(format!("Failed to run `ldd {}`", shared_lib))?;
2212+
let stdout = String::from_utf8_lossy(&output.stdout);
2213+
if !output.status.success() || stdout.contains("not found") {
2214+
errors.push(format!("Error from `ldd {}`:\n{}", shared_lib, stdout));
2215+
}
2216+
}
2217+
}
2218+
}
2219+
21892220
Ok(errors)
21902221
}
21912222

0 commit comments

Comments
 (0)