Skip to content

Commit 0450bf1

Browse files
committed
unix: normalize build configuration to aid portability
This commit implements a long desired feature to normalize the build configuration in various distribution files post build but pre packaging. The goal of this general feature is to make distributions highly portable. Before, configurations (which were used to e.g. compile extension modules) referenced build environment paths, like `/tools`. This is not desirable and can confuse downstream users when unexpected settings are used. The impetus for this work is #194. As part of this change we strip the `-fdebug-default-version` argument from `CFLAGS` to restore CFLAGS compatibility with GCC. There's no doubt additional settings that could be normalized. Those can be implemented as follow-ups.
1 parent 7ade52e commit 0450bf1

File tree

2 files changed

+72
-0
lines changed

2 files changed

+72
-0
lines changed

cpython-unix/build-cpython.sh

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,69 @@ fi
550550
${BUILD_PYTHON} "${PIP_WHEEL}/pip" install --prefix="${ROOT}/out/python/install" --no-cache-dir --no-index "${PIP_WHEEL}"
551551
${BUILD_PYTHON} "${PIP_WHEEL}/pip" install --prefix="${ROOT}/out/python/install" --no-cache-dir --no-index "${SETUPTOOLS_WHEEL}"
552552

553+
# Hack up the system configuration settings to aid portability.
554+
#
555+
# The goal here is to make the system configuration as generic as possible so
556+
# that a) it works on as many machines as possible b) doesn't leak details
557+
# about the build environment, which is non-portable.
558+
cat > ${ROOT}/hack_sysconfig.py << EOF
559+
import os
560+
import sys
561+
import sysconfig
562+
563+
ROOT = sys.argv[1]
564+
565+
MAJMIN = ".".join([str(sys.version_info[0]), str(sys.version_info[1])])
566+
PYTHON_CONFIG = os.path.join(ROOT, "install", "bin", "python%s-config" % MAJMIN)
567+
PLATFORM_CONFIG = os.path.join(ROOT, sysconfig.get_config_var("LIBPL").lstrip("/"))
568+
MAKEFILE = os.path.join(PLATFORM_CONFIG, "Makefile")
569+
SYSCONFIGDATA = os.path.join(
570+
ROOT,
571+
"install",
572+
"lib",
573+
"python%s" % MAJMIN,
574+
"%s.py" % sysconfig._get_sysconfigdata_name(),
575+
)
576+
577+
def replace_in_file(path, search, replace):
578+
with open(path, "rb") as fh:
579+
data = fh.read()
580+
581+
if search.encode("utf-8") in data:
582+
print("replacing '%s' in %s with '%s'" % (search, path, replace))
583+
else:
584+
print("warning: '%s' not in %s" % (search, path))
585+
586+
data = data.replace(search.encode("utf-8"), replace.encode("utf-8"))
587+
588+
with open(path, "wb") as fh:
589+
fh.write(data)
590+
591+
592+
def replace_in_all(search, replace):
593+
replace_in_file(PYTHON_CONFIG, search, replace)
594+
replace_in_file(MAKEFILE, search, replace)
595+
replace_in_file(SYSCONFIGDATA, search, replace)
596+
597+
598+
# -fdebug-default-version is Clang only. Strip so compiling works on GCC.
599+
replace_in_all("-fdebug-default-version=4", "")
600+
601+
# Remove some build environment paths.
602+
# This is /tools on Linux but can be a dynamic path / temp directory on macOS
603+
# and when not using container builds.
604+
tools_path = os.environ["TOOLS_PATH"]
605+
replace_in_all("-I%s/deps/include/ncursesw" % tools_path, "")
606+
replace_in_all("-I%s/deps/include/uuid" % tools_path, "")
607+
replace_in_all("-I%s/deps/include" % tools_path, "")
608+
replace_in_all("-I%s/deps/libedit/include" % tools_path, "")
609+
replace_in_all("-L%s/deps/libedit/lib" % tools_path, "")
610+
replace_in_all("-L%s/deps/lib" % tools_path, "")
611+
612+
EOF
613+
614+
${BUILD_PYTHON} ${ROOT}/hack_sysconfig.py ${ROOT}/out/python
615+
553616
# Emit metadata to be used in PYTHON.json.
554617
cat > ${ROOT}/generate_metadata.py << EOF
555618
import codecs

docs/quirks.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,3 +454,12 @@ distros like Debian/Ubuntu and RedHat).
454454
Until we have a better solution here, just understand that anything looking
455455
at ``sysconfig`` could resolve non-existent paths or names of binaries that
456456
don't exist on the current machine.
457+
458+
Starting with the Linux and macOS distributions released in 2024, we do
459+
normalize some values in these files at build time. Normalizations include:
460+
461+
* Removing compiler flags that are non-portable.
462+
* Removing references to build paths (e.g. ``/tools`` on Linux).
463+
464+
If there is a build time normalization that you think should be performed to
465+
make distributions more portable, please file a GitHub issue.

0 commit comments

Comments
 (0)