Skip to content

Commit b62b289

Browse files
committed
unix: properly define PYTHON_ARCH for more triples
We were inserting malformed symlinks into the archive because we didn't annotate all target triples. This commit hopefully fixes that. As part of debugging this, I also discovered that cross builds were missing "d" in abiflags. This commit should also fix that. To prevent this from happening again we teach the validation code to ensure all symlink targets exist in the archive.
1 parent f763de1 commit b62b289

File tree

2 files changed

+74
-9
lines changed

2 files changed

+74
-9
lines changed

cpython-unix/build-cpython.sh

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -794,6 +794,12 @@ import os
794794
import sys
795795
import sysconfig
796796
797+
# When doing cross builds, sysconfig still picks up abiflags from the
798+
# host Python, which is never built in debug mode. Patch abiflags accordingly.
799+
if os.environ.get("CPYTHON_DEBUG") and "d" not in sysconfig.get_config_var("abiflags"):
800+
sys.abiflags += "d"
801+
sysconfig._CONFIG_VARS["abiflags"] += "d"
802+
797803
metadata = {
798804
"python_abi_tag": sys.abiflags,
799805
"python_implementation_cache_tag": sys.implementation.cache_tag,
@@ -817,7 +823,6 @@ metadata = {
817823
"python_config_vars": {k: str(v) for k, v in sysconfig.get_config_vars().items()},
818824
}
819825
820-
821826
# When cross-compiling, we use a host Python to run this script. There are
822827
# some hacks to get sysconfig to pick up the correct data file. However,
823828
# these hacks don't work for sysconfig.get_paths() and we get paths to the host
@@ -864,11 +869,43 @@ touch "${LIB_DYNLOAD}/.empty"
864869

865870
# Symlink libpython so we don't have 2 copies.
866871
if [ -n "${PYTHON_BINARY_SUFFIX}" ]; then
867-
if [ "${PYBUILD_PLATFORM}" = "macos" ]; then
868-
PYTHON_ARCH="darwin"
869-
else
870-
PYTHON_ARCH="x86_64-linux-gnu"
871-
fi
872+
case "${TARGET_TRIPLE}" in
873+
aarch64-unknown-linux-gnu)
874+
PYTHON_ARCH="aarch64-linux-gnu"
875+
;;
876+
# This is too aggressive. But we don't have patches in place for
877+
# setting the platform name properly on non-Darwin.
878+
*-apple-*)
879+
PYTHON_ARCH="darwin"
880+
;;
881+
armv7-unknown-linux-gnueabi)
882+
PYTHON_ARCH="armv7-linux-gnueabi"
883+
;;
884+
armv7-unknown-linux-gnueabihf)
885+
PYTHON_ARCH="armv7-linux-gnueabihf"
886+
;;
887+
i686-unknown-linux-gnu)
888+
PYTHON_ARCH="i386-linux-gnu"
889+
;;
890+
mips-unknown-linux-gnu)
891+
PYTHON_ARCH="mips-linux-gnu"
892+
;;
893+
mipsel-unknown-linux-gnu)
894+
PYTHON_ARCH="mipsel-linux-gnu"
895+
;;
896+
mips64el-unknown-linux-gnuabi64)
897+
PYTHON_ARCH="mips64el-linux-gnuabi64"
898+
;;
899+
s390x-unknown-linux-gnu)
900+
PYTHON_ARCH="s390x-linux-gnu"
901+
;;
902+
x86_64-unknown-linux-*)
903+
PYTHON_ARCH="x86_64-linux-gnu"
904+
;;
905+
*)
906+
echo "unhandled target triple: ${TARGET_TRIPLE}"
907+
exit 1
908+
esac
872909

873910
LIBPYTHON=libpython${PYTHON_MAJMIN_VERSION}${PYTHON_BINARY_SUFFIX}.a
874911
ln -sf \

src/main.rs

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -612,7 +612,7 @@ fn validate_possible_object_file(
612612
Ok((errors, seen_dylibs))
613613
}
614614

615-
fn validate_json(json: &PythonJsonMain, triple: &str) -> Result<Vec<String>> {
615+
fn validate_json(json: &PythonJsonMain, triple: &str, is_debug: bool) -> Result<Vec<String>> {
616616
let mut errors = vec![];
617617

618618
if json.version != "7" {
@@ -650,6 +650,16 @@ fn validate_json(json: &PythonJsonMain, triple: &str) -> Result<Vec<String>> {
650650
));
651651
}
652652

653+
if is_debug
654+
&& !json
655+
.python_config_vars
656+
.get("abiflags")
657+
.unwrap()
658+
.contains('d')
659+
{
660+
errors.push("abiflags does not contain 'd'".to_string());
661+
}
662+
653663
for extension in json.build_info.extensions.keys() {
654664
if GLOBALLY_BANNED_EXTENSIONS.contains(&extension.as_str()) {
655665
errors.push(format!("banned extension detected: {}", extension));
@@ -663,6 +673,7 @@ fn validate_distribution(dist_path: &Path) -> Result<Vec<String>> {
663673
let mut errors = vec![];
664674
let mut seen_dylibs = BTreeSet::new();
665675
let mut seen_paths = BTreeSet::new();
676+
let mut seen_symlink_targets = BTreeSet::new();
666677

667678
let dist_filename = dist_path
668679
.file_name()
@@ -696,6 +707,8 @@ fn validate_distribution(dist_path: &Path) -> Result<Vec<String>> {
696707
return Err(anyhow!("could not parse Python version from filename"));
697708
};
698709

710+
let is_debug = dist_filename.contains("-debug-");
711+
699712
let reader = std::io::BufReader::new(fh);
700713
let dctx = zstd::stream::Decoder::new(reader)?;
701714
let mut tf = tar::Archive::new(dctx);
@@ -707,10 +720,12 @@ fn validate_distribution(dist_path: &Path) -> Result<Vec<String>> {
707720

708721
let mut entry = entries.next().unwrap()?;
709722
if entry.path()?.display().to_string() == "python/PYTHON.json" {
723+
seen_paths.insert(entry.path()?.to_path_buf());
724+
710725
let mut data = Vec::new();
711726
entry.read_to_end(&mut data)?;
712727
let json = parse_python_json(&data).context("parsing PYTHON.json")?;
713-
errors.extend(validate_json(&json, triple)?);
728+
errors.extend(validate_json(&json, triple, is_debug)?);
714729

715730
wanted_python_paths.extend(json.python_paths.values().map(|x| format!("python/{}", x)));
716731
} else {
@@ -726,6 +741,10 @@ fn validate_distribution(dist_path: &Path) -> Result<Vec<String>> {
726741

727742
seen_paths.insert(path.clone());
728743

744+
if let Some(link_name) = entry.link_name()? {
745+
seen_symlink_targets.insert(path.parent().unwrap().join(link_name));
746+
}
747+
729748
// If this path starts with a path referenced in wanted_python_paths,
730749
// remove the prefix from wanted_python_paths so we don't error on it
731750
// later.
@@ -773,7 +792,16 @@ fn validate_distribution(dist_path: &Path) -> Result<Vec<String>> {
773792

774793
if path == PathBuf::from("python/PYTHON.json") {
775794
let json = parse_python_json(&data).context("parsing PYTHON.json")?;
776-
errors.extend(validate_json(&json, triple)?);
795+
errors.extend(validate_json(&json, triple, is_debug)?);
796+
}
797+
}
798+
799+
for path in seen_symlink_targets {
800+
if !seen_paths.contains(&path) {
801+
errors.push(format!(
802+
"symlink target {} referenced in archive but not found",
803+
path.display()
804+
));
777805
}
778806
}
779807

0 commit comments

Comments
 (0)