diff --git a/README.rst b/README.rst index 8c04ba61a..9dfac6d7b 100644 --- a/README.rst +++ b/README.rst @@ -146,7 +146,7 @@ Image content All images currently contain: -- CPython 3.5, 3.6, 3.7, 3.8 and 3.9, installed in +- CPython 3.6, 3.7, 3.8 and 3.9, PyPy 3.7 installed in ``/opt/python/-``. The directories are named after the PEP 425 tags for each environment -- e.g. ``/opt/python/cp37-cp37m`` contains a CPython 3.7 build, and @@ -165,6 +165,8 @@ default ``sys.abiflags`` became an empty string: the ``m`` flag for pymalloc became useless (builds with and without pymalloc are ABI compatible) and so has been removed. (e.g. ``/opt/python/cp38-cp38``) +Note that PyPy is not available on ppc64le & s390x. + Building Docker images ---------------------- diff --git a/docker/Dockerfile b/docker/Dockerfile index b48ef11fb..31aacdd4f 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -131,7 +131,9 @@ COPY build_scripts/cpython-pubkey-310-311.txt /build_scripts/cpython-pubkeys.txt RUN manylinux-entrypoint /build_scripts/build-cpython.sh 3.10.0b1 -FROM build_cpython AS all_cpython +FROM build_cpython AS all_python +COPY build_scripts/install-pypy.sh /build_scripts/install-pypy.sh +RUN manylinux-entrypoint /build_scripts/install-pypy.sh 3.7 7.3.4 COPY --from=build_cpython36 /opt/_internal /opt/_internal/ COPY --from=build_cpython37 /opt/_internal /opt/_internal/ COPY --from=build_cpython38 /opt/_internal /opt/_internal/ @@ -144,7 +146,7 @@ FROM runtime_base COPY --from=build_git /manylinux-rootfs / COPY --from=build_swig /manylinux-rootfs / COPY --from=build_cpython /manylinux-rootfs / -COPY --from=all_cpython /opt/_internal /opt/_internal/ +COPY --from=all_python /opt/_internal /opt/_internal/ COPY build_scripts/finalize.sh build_scripts/update-system-packages.sh build_scripts/python-tag-abi-tag.py build_scripts/requirements.txt build_scripts/requirements-tools.txt /build_scripts/ RUN manylinux-entrypoint /build_scripts/finalize.sh && rm -rf /build_scripts diff --git a/docker/build_scripts/finalize.sh b/docker/build_scripts/finalize.sh index d375e1327..103996619 100755 --- a/docker/build_scripts/finalize.sh +++ b/docker/build_scripts/finalize.sh @@ -10,7 +10,7 @@ MY_DIR=$(dirname "${BASH_SOURCE[0]}") source $MY_DIR/build_utils.sh mkdir /opt/python -for PREFIX in $(find /opt/_internal/ -mindepth 1 -maxdepth 1 -name 'cpython*'); do +for PREFIX in $(find /opt/_internal/ -mindepth 1 -maxdepth 1 \( -name 'cpython*' -o -name 'pypy*' \)); do # Some python's install as bin/python3. Make them available as # bin/python. if [ -e ${PREFIX}/bin/python3 ] && [ ! -e ${PREFIX}/bin/python ]; then @@ -28,8 +28,12 @@ for PREFIX in $(find /opt/_internal/ -mindepth 1 -maxdepth 1 -name 'cpython*'); ln -s ${PREFIX} /opt/python/${ABI_TAG} # Make versioned python commands available directly in environment. PYVERS=$(${PREFIX}/bin/python -c "import sys; print('.'.join(map(str, sys.version_info[:2])))") - ln -s ${PREFIX}/bin/python /usr/local/bin/python${PYVERS} - ln -s ${PREFIX}/bin/pip /usr/local/bin/pip${PYVERS} + if [[ "${PREFIX}" == *"/pypy"* ]]; then + ln -s ${PREFIX}/bin/python /usr/local/bin/pypy${PYVERS} + else + ln -s ${PREFIX}/bin/python /usr/local/bin/python${PYVERS} + ln -s ${PREFIX}/bin/pip /usr/local/bin/pip${PYVERS} + fi done # Create venv for auditwheel & certifi diff --git a/docker/build_scripts/install-pypy.sh b/docker/build_scripts/install-pypy.sh new file mode 100755 index 000000000..d820ca763 --- /dev/null +++ b/docker/build_scripts/install-pypy.sh @@ -0,0 +1,65 @@ +#!/bin/bash + +# Stop at any error, show all commands +set -exuo pipefail + +# Get script directory +MY_DIR=$(dirname "${BASH_SOURCE[0]}") + +# Get build utilities +source $MY_DIR/build_utils.sh + + +PYTHON_VERSION=$1 +PYPY_VERSION=$2 +PYPY_DOWNLOAD_URL=https://downloads.python.org/pypy + + +function get_shortdir { + local exe=$1 + $exe -c 'import sys; print("pypy%d.%d-%d.%d.%d" % (sys.version_info[:2]+sys.pypy_version_info[:3]))' +} + + +mkdir -p /tmp +cd /tmp + +case ${AUDITWHEEL_ARCH} in + x86_64) PYPY_ARCH=linux64;; + i686) PYPY_ARCH=linux32;; + aarch64) PYPY_ARCH=aarch64;; + *) echo "No PyPy for ${AUDITWHEEL_ARCH}"; exit 0;; +esac + +TARBALL=pypy${PYTHON_VERSION}-v${PYPY_VERSION}-${PYPY_ARCH}.tar.bz2 +TMPDIR=/tmp/${TARBALL/.tar.bz2//} +PREFIX="/opt/_internal" + +mkdir -p ${PREFIX} + +fetch_source ${TARBALL} ${PYPY_DOWNLOAD_URL} + +tar -xf ${TARBALL} + +# the new PyPy 3 distributions don't have pypy symlinks to pypy3 +if [ ! -f "${TMPDIR}/bin/pypy" ]; then + ln -s pypy3 ${TMPDIR}/bin/pypy +fi + +# rename the directory to something shorter like pypy3.7-7.3.4 +PREFIX=${PREFIX}/$(get_shortdir ${TMPDIR}/bin/pypy) +mv ${TMPDIR} ${PREFIX} + +# add a generic "python" symlink +if [ ! -f "${PREFIX}/bin/python" ]; then + ln -s pypy ${PREFIX}/bin/python +fi + +# remove debug symbols +rm ${PREFIX}/bin/*.debug + +# We do not need the Python test suites +find ${PREFIX} -depth \( -type d -a -name test -o -name tests \) | xargs rm -rf + +# We do not need precompiled .pyc and .pyo files. +clean_pyc ${PREFIX} diff --git a/tests/run_tests.sh b/tests/run_tests.sh index c945ecfbb..8ffd44e39 100755 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -24,17 +24,24 @@ for PYTHON in /opt/python/*/bin/python; do $PYTHON $MY_DIR/manylinux-check.py ${AUDITWHEEL_POLICY} ${AUDITWHEEL_ARCH} # Make sure that SSL cert checking works $PYTHON $MY_DIR/ssl-check.py - # Make sure sqlite3 module can be loaded properly and is the manylinux version one - # c.f. https://github.com/pypa/manylinux/issues/1030 - $PYTHON -c 'import sqlite3; print(sqlite3.sqlite_version); assert sqlite3.sqlite_version_info[0:2] >= (3, 34)' - # pythonx.y & pipx.y shall be available directly in PATH + IMPLEMENTATION=$(${PYTHON} -c "import sys; print(sys.implementation.name)") PYVERS=$(${PYTHON} -c "import sys; print('.'.join(map(str, sys.version_info[:2])))") - LINK_VERSION=$(python${PYVERS} -V) + if [ "${IMPLEMENTATION}" == "pypy" ]; then + LINK_PREFIX=pypy + else + LINK_PREFIX=python + # Make sure sqlite3 module can be loaded properly and is the manylinux version one + # c.f. https://github.com/pypa/manylinux/issues/1030 + $PYTHON -c 'import sqlite3; print(sqlite3.sqlite_version); assert sqlite3.sqlite_version_info[0:2] >= (3, 34)' + # pipx.y shall be available directly in PATH + LINK_VERSION=$(pip${PYVERS} -V) + REAL_VERSION=$(${PYTHON} -m pip -V) + test "${LINK_VERSION%% from *}" = "${REAL_VERSION%% from *}" + fi + # pythonx.y or pypyx.y shall be available directly in PATH + LINK_VERSION=$(${LINK_PREFIX}${PYVERS} -V) REAL_VERSION=$(${PYTHON} -V) test "${LINK_VERSION}" = "${REAL_VERSION}" - LINK_VERSION=$(pip${PYVERS} -V) - REAL_VERSION=$(${PYTHON} -m pip -V) - test "${LINK_VERSION%% from *}" = "${REAL_VERSION%% from *}" done # minimal tests for tools that should be present