Skip to content

Commit 1ef7456

Browse files
committed
unix: install pip and setuptools from wheels
This commit refactors the install of pip and setuptools. Previously, we installed both of these by invoking `setup.py` from the host Python. This worked, but it was somewhat old school. And in the case of cross-compiling, it installed the packages to the host Python, not the target Python. After this commit, we download wheels for both pip and setuptools and the install invokes the host Python but runs the pip wheel to invoke pip to install the packages. This is conceptually similar to how the `ensurepip` module works. The end result is that pip is used to install itself and setuptools into the appropriate output directory. This works with both native and cross builds. Aside from minor changes to the directory layout, the end result is the same as far as I can tell. But since cross-compiles now install pip and setuptools correctly, this fixes #84. Because pip now bootstraps self and this doesn't work on musl builds without a patch, we had to move the patching of pip to before it is invoked. We moved the patching of setuptools as well, because it is related.
1 parent 4905543 commit 1ef7456

File tree

4 files changed

+89
-65
lines changed

4 files changed

+89
-65
lines changed

cpython-unix/build-cpython.sh

+81-59
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,74 @@ export LLVM_PROFDATA=${TOOLS_PATH}/${TOOLCHAIN}/bin/llvm-profdata
2020
find ${TOOLS_PATH}/deps -name '*.so*' -exec rm {} \;
2121

2222
tar -xf Python-${PYTHON_VERSION}.tar.xz
23-
tar -xf setuptools-${SETUPTOOLS_VERSION}.tar.gz
24-
tar -xf pip-${PIP_VERSION}.tar.gz
23+
24+
PIP_WHEEL="${ROOT}/pip-${PIP_VERSION}-py3-none-any.whl"
25+
SETUPTOOLS_WHEEL="${ROOT}/setuptools-${SETUPTOOLS_VERSION}-py3-none-any.whl"
26+
27+
chmod 644 "${PIP_WHEEL}"
28+
chmod 644 "${SETUPTOOLS_WHEEL}"
29+
30+
# pip and setuptools don't properly handle the case where the current executable
31+
# isn't dynamic. This is tracked by https://github.com/pypa/pip/issues/6543.
32+
# We need to patch both.
33+
#
34+
# Ideally we'd do this later in the build. However, since we use the pip
35+
# wheel to bootstrap itself, we need to patch the wheel before it is used.
36+
#
37+
# Wheels are zip files. So we simply unzip, patch, and rezip.
38+
mkdir pip-tmp
39+
pushd pip-tmp
40+
unzip "${PIP_WHEEL}"
41+
42+
patch -p1 <<EOF
43+
diff --git a/pip/_internal/utils/glibc.py b/pip/_internal/utils/glibc.py
44+
index 819979d80..4ae91e364 100644
45+
--- a/pip/_internal/utils/glibc.py
46+
+++ b/pip/_internal/utils/glibc.py
47+
@@ -47,7 +47,10 @@ def glibc_version_string_ctypes():
48+
# manpage says, "If filename is NULL, then the returned handle is for the
49+
# main program". This way we can let the linker do the work to figure out
50+
# which libc our process is actually using.
51+
- process_namespace = ctypes.CDLL(None)
52+
+ try:
53+
+ process_namespace = ctypes.CDLL(None)
54+
+ except OSError:
55+
+ return None
56+
try:
57+
gnu_get_libc_version = process_namespace.gnu_get_libc_version
58+
except AttributeError:
59+
EOF
60+
61+
zip -r "${PIP_WHEEL}" *
62+
popd
63+
rm -rf pip-tmp
64+
65+
mkdir setuptools-tmp
66+
pushd setuptools-tmp
67+
unzip "${SETUPTOOLS_WHEEL}"
68+
69+
patch -p1 <<EOF
70+
diff --git a/setuptools/_vendor/packaging/tags.py b/setuptools/_vendor/packaging/tags.py
71+
index 9064910b..c541e648 100644
72+
--- a/setuptools/_vendor/packaging/tags.py
73+
+++ b/setuptools/_vendor/packaging/tags.py
74+
@@ -475,7 +475,10 @@ def _glibc_version_string_ctypes():
75+
# which libc our process is actually using.
76+
#
77+
# Note: typeshed is wrong here so we are ignoring this line.
78+
- process_namespace = ctypes.CDLL(None) # type: ignore
79+
+ try:
80+
+ process_namespace = ctypes.CDLL(None) # type: ignore
81+
+ except OSError:
82+
+ return None
83+
try:
84+
gnu_get_libc_version = process_namespace.gnu_get_libc_version
85+
except AttributeError:
86+
EOF
87+
88+
zip -r "${SETUPTOOLS_WHEEL}" *
89+
popd
90+
rm -rf setuptools-tmp
2591

2692
# If we are cross-compiling, we need to build a host Python to use during
2793
# the build.
@@ -50,7 +116,9 @@ if [ "${BUILD_TRIPLE}" != "${TARGET_TRIPLE}" ]; then
50116
;;
51117
esac
52118

53-
CC="${HOST_CC}" CFLAGS="${EXTRA_HOST_CFLAGS}" CPPFLAGS="${EXTRA_HOST_CFLAGS}" LDFLAGS="${EXTRA_HOST_LDFLAGS}" ./configure --prefix "${TOOLS_PATH}/pyhost"
119+
CC="${HOST_CC}" CFLAGS="${EXTRA_HOST_CFLAGS}" CPPFLAGS="${EXTRA_HOST_CFLAGS}" LDFLAGS="${EXTRA_HOST_LDFLAGS}" ./configure \
120+
--prefix "${TOOLS_PATH}/pyhost" \
121+
--without-ensurepip
54122

55123
# When building on macOS 10.15 (and possibly earlier) using the 11.0
56124
# SDK, the _ctypes extension fails to import due to a missing symbol on
@@ -741,63 +809,17 @@ if [ "${PYBUILD_SHARED}" = "1" ]; then
741809
fi
742810
fi
743811

744-
# Install pip so we can patch it to work with non-dynamic executables
745-
# and work around https://github.com/pypa/pip/issues/6543. But pip's bundled
746-
# setuptools has the same bug! So we need to install a patched version.
747-
pushd ${ROOT}/setuptools-${SETUPTOOLS_VERSION}
748-
patch -p1 <<EOF
749-
diff --git a/setuptools/_vendor/packaging/tags.py b/setuptools/_vendor/packaging/tags.py
750-
index 9064910b..c541e648 100644
751-
--- a/setuptools/_vendor/packaging/tags.py
752-
+++ b/setuptools/_vendor/packaging/tags.py
753-
@@ -475,7 +475,10 @@ def _glibc_version_string_ctypes():
754-
# which libc our process is actually using.
755-
#
756-
# Note: typeshed is wrong here so we are ignoring this line.
757-
- process_namespace = ctypes.CDLL(None) # type: ignore
758-
+ try:
759-
+ process_namespace = ctypes.CDLL(None) # type: ignore
760-
+ except OSError:
761-
+ return None
762-
try:
763-
gnu_get_libc_version = process_namespace.gnu_get_libc_version
764-
except AttributeError:
765-
EOF
766-
767-
${BUILD_PYTHON} setup.py install
768-
popd
769-
770-
pushd ${ROOT}/pip-${PIP_VERSION}
771-
772-
# pip 21 shipped DOS line endings. https://github.com/pypa/pip/issues/9638.
773-
# Let's fix that.
774-
if [ "${PYBUILD_PLATFORM}" = "macos" ]; then
775-
find . -name '*.py' -exec perl -i -pe 's/\r\n$/\n/g' {} \;
776-
else
777-
find . -name '*.py' -exec sed -i 's/\r$//g' {} \;
778-
fi
779-
780-
patch -p1 <<EOF
781-
diff --git a/src/pip/_internal/utils/glibc.py b/src/pip/_internal/utils/glibc.py
782-
index 819979d80..4ae91e364 100644
783-
--- a/src/pip/_internal/utils/glibc.py
784-
+++ b/src/pip/_internal/utils/glibc.py
785-
@@ -47,7 +47,10 @@ def glibc_version_string_ctypes():
786-
# manpage says, "If filename is NULL, then the returned handle is for the
787-
# main program". This way we can let the linker do the work to figure out
788-
# which libc our process is actually using.
789-
- process_namespace = ctypes.CDLL(None)
790-
+ try:
791-
+ process_namespace = ctypes.CDLL(None)
792-
+ except OSError:
793-
+ return None
794-
try:
795-
gnu_get_libc_version = process_namespace.gnu_get_libc_version
796-
except AttributeError:
797-
EOF
812+
# Install setuptools and pip as they are common tools that should be in any
813+
# Python distribution.
814+
#
815+
# We disabled ensurepip because we insist on providing our own pip and don't
816+
# want the final product to possibly be contaminated by another version.
817+
#
818+
# It is possible for the Python interpreter to run wheels directly. So we
819+
# simply use our pip to install self. Kinda crazy, but it works!
798820

799-
${BUILD_PYTHON} setup.py install
800-
popd
821+
${BUILD_PYTHON} "${PIP_WHEEL}/pip" install --prefix="${ROOT}/out/python/install" --no-cache-dir --no-index "${PIP_WHEEL}"
822+
${BUILD_PYTHON} "${PIP_WHEEL}/pip" install --prefix="${ROOT}/out/python/install" --no-cache-dir --no-index "${SETUPTOOLS_WHEEL}"
801823

802824
# Emit metadata to be used in PYTHON.json.
803825
cat > ${ROOT}/generate_metadata.py << EOF

cpython-unix/build.Dockerfile

+1
Original file line numberDiff line numberDiff line change
@@ -23,4 +23,5 @@ RUN apt-get install \
2323
tar \
2424
xz-utils \
2525
unzip \
26+
zip \
2627
zlib1g-dev

cpython-unix/build.cross.Dockerfile

+1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ RUN apt-get install \
4343
tar \
4444
xz-utils \
4545
unzip \
46+
zip \
4647
zlib1g-dev
4748

4849
# Cross-building.

pythonbuild/downloads.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -286,9 +286,9 @@
286286
"version": "0.12",
287287
},
288288
"pip": {
289-
"url": "https://files.pythonhosted.org/packages/52/e1/06c018197d8151383f66ebf6979d951995cf495629fc54149491f5d157d0/pip-21.2.4.tar.gz",
290-
"size": 1564487,
291-
"sha256": "0eb8a1516c3d138ae8689c0c1a60fde7143310832f9dc77e11d8a4bc62de193b",
289+
"url": "https://files.pythonhosted.org/packages/ca/31/b88ef447d595963c01060998cb329251648acf4a067721b0452c45527eb8/pip-21.2.4-py3-none-any.whl",
290+
"size": 1555100,
291+
"sha256": "fa9ebb85d3fd607617c0c44aca302b1b45d87f9c2a1649b46c26167ca4296323",
292292
"version": "21.2.4",
293293
},
294294
"readline": {
@@ -301,9 +301,9 @@
301301
"license_file": "LICENSE.readline.txt",
302302
},
303303
"setuptools": {
304-
"url": "https://files.pythonhosted.org/packages/db/e2/c0ced9ccffb61432305665c22842ea120c0f649eec47ecf2a45c596707c4/setuptools-57.4.0.tar.gz",
305-
"size": 2141309,
306-
"sha256": "6bac238ffdf24e8806c61440e755192470352850f3419a52f26ffe0a1a64f465",
304+
"url": "https://files.pythonhosted.org/packages/bd/25/5bdf7f1adeebd4e3fa76b2e2f045ae53ee208e40a4231ad0f0c3007e4353/setuptools-57.4.0-py3-none-any.whl",
305+
"size": 819017,
306+
"sha256": "a49230977aa6cfb9d933614d2f7b79036e9945c4cdd7583163f4e920b83418d6",
307307
"version": "57.4.0",
308308
},
309309
"sqlite": {

0 commit comments

Comments
 (0)