|
| 1 | +#!/bin/bash |
| 2 | +# Top-level build script called from Dockerfile |
| 3 | + |
| 4 | +# Stop at any error, show all commands |
| 5 | +set -ex |
| 6 | + |
| 7 | +# Set build environment variables |
| 8 | +MY_DIR=$(dirname "${BASH_SOURCE[0]}") |
| 9 | +. $MY_DIR/build_env.sh |
| 10 | + |
| 11 | +# Dependencies for compiling Python that we want to remove from |
| 12 | +# the final image after compiling Python |
| 13 | +PYTHON_COMPILE_DEPS="zlib-devel bzip2-devel expat-devel ncurses-devel sqlite-devel readline-devel tk-devel gdbm-devel db4-devel libpcap-devel xz-devel" |
| 14 | + |
| 15 | +# Libraries that are allowed as part of the manylinux2010 profile |
| 16 | +# Extract from PEP: https://www.python.org/dev/peps/pep-0571/#the-manylinux2010-policy |
| 17 | +# On RPM-based systems, they are provided by these packages: |
| 18 | +# Package: Libraries |
| 19 | +# glib2: libglib-2.0.so.0, libgthread-2.0.so.0, libgobject-2.0.so.0 |
| 20 | +# glibc: libresolv.so.2, libutil.so.1, libnsl.so.1, librt.so.1, libcrypt.so.1, libpthread.so.0, libdl.so.2, libm.so.6, libc.so.6 |
| 21 | +# libICE: libICE.so.6 |
| 22 | +# libX11: libX11.so.6 |
| 23 | +# libXext: libXext.so.6 |
| 24 | +# libXrender: libXrender.so.1 |
| 25 | +# libgcc: libgcc_s.so.1 |
| 26 | +# libstdc++: libstdc++.so.6 |
| 27 | +# mesa: libGL.so.1 |
| 28 | +# |
| 29 | +# PEP is missing the package for libSM.so.6 for RPM based system |
| 30 | +# Install development packages (except for libgcc which is provided by gcc install) |
| 31 | +MANYLINUX2010_DEPS="glibc-devel libstdc++-devel glib2-devel libX11-devel libXext-devel libXrender-devel mesa-libGL-devel libICE-devel libSM-devel" |
| 32 | + |
| 33 | +# Get build utilities |
| 34 | +source $MY_DIR/build_utils.sh |
| 35 | + |
| 36 | +# See https://unix.stackexchange.com/questions/41784/can-yum-express-a-preference-for-x86-64-over-i386-packages |
| 37 | +echo "multilib_policy=best" >> /etc/yum.conf |
| 38 | + |
| 39 | +# https://hub.docker.com/_/centos/ |
| 40 | +# "Additionally, images with minor version tags that correspond to install |
| 41 | +# media are also offered. These images DO NOT recieve updates as they are |
| 42 | +# intended to match installation iso contents. If you choose to use these |
| 43 | +# images it is highly recommended that you include RUN yum -y update && yum |
| 44 | +# clean all in your Dockerfile, or otherwise address any potential security |
| 45 | +# concerns." |
| 46 | +# Decided not to clean at this point: https://github.com/pypa/manylinux/pull/129 |
| 47 | +yum -y update |
| 48 | + |
| 49 | +# Software collection (for devtoolset-8) and EPEL support (for cmake28 & yasm) |
| 50 | +yum -y install centos-release-scl https://dl.fedoraproject.org/pub/epel/epel-release-latest-6.noarch.rpm |
| 51 | + |
| 52 | +# Development tools and libraries |
| 53 | +yum -y install \ |
| 54 | + automake \ |
| 55 | + bison \ |
| 56 | + bzip2 \ |
| 57 | + cmake28 \ |
| 58 | + devtoolset-8-binutils \ |
| 59 | + devtoolset-8-gcc \ |
| 60 | + devtoolset-8-gcc-c++ \ |
| 61 | + devtoolset-8-gcc-gfortran \ |
| 62 | + diffutils \ |
| 63 | + gettext \ |
| 64 | + file \ |
| 65 | + kernel-devel-`uname -r` \ |
| 66 | + libffi-devel \ |
| 67 | + make \ |
| 68 | + patch \ |
| 69 | + perl-devel \ |
| 70 | + unzip \ |
| 71 | + which \ |
| 72 | + yasm \ |
| 73 | + ${PYTHON_COMPILE_DEPS} |
| 74 | + |
| 75 | +# Build an OpenSSL for both curl and the Pythons. We'll delete this at the end. |
| 76 | +build_openssl $OPENSSL_ROOT $OPENSSL_HASH |
| 77 | + |
| 78 | +# Install curl so we can have TLS 1.2 in this ancient container. |
| 79 | +build_curl $CURL_ROOT $CURL_HASH |
| 80 | +hash -r |
| 81 | +curl --version |
| 82 | +curl-config --features |
| 83 | + |
| 84 | +# Install a git we link against OpenSSL so that we can use TLS 1.2 |
| 85 | +build_git $GIT_ROOT $GIT_HASH |
| 86 | +git version |
| 87 | + |
| 88 | +# Install newest autoconf |
| 89 | +build_autoconf $AUTOCONF_ROOT $AUTOCONF_HASH |
| 90 | +autoconf --version |
| 91 | + |
| 92 | +# Install newest automake |
| 93 | +build_automake $AUTOMAKE_ROOT $AUTOMAKE_HASH |
| 94 | +automake --version |
| 95 | + |
| 96 | +# Install newest libtool |
| 97 | +build_libtool $LIBTOOL_ROOT $LIBTOOL_HASH |
| 98 | +libtool --version |
| 99 | + |
| 100 | +# Install a more recent SQLite3 |
| 101 | +curl -fsSLO $SQLITE_AUTOCONF_DOWNLOAD_URL/$SQLITE_AUTOCONF_VERSION.tar.gz |
| 102 | +check_sha256sum $SQLITE_AUTOCONF_VERSION.tar.gz $SQLITE_AUTOCONF_HASH |
| 103 | +tar xfz $SQLITE_AUTOCONF_VERSION.tar.gz |
| 104 | +cd $SQLITE_AUTOCONF_VERSION |
| 105 | +do_standard_install |
| 106 | +cd .. |
| 107 | +rm -rf $SQLITE_AUTOCONF_VERSION* |
| 108 | + |
| 109 | +# Compile the latest Python releases. |
| 110 | +# (In order to have a proper SSL module, Python is compiled |
| 111 | +# against a recent openssl [see env vars above], which is linked |
| 112 | +# statically. |
| 113 | +mkdir -p /opt/python |
| 114 | +build_cpythons $CPYTHON_VERSIONS |
| 115 | + |
| 116 | +PY36_BIN=/opt/python/cp36-cp36m/bin |
| 117 | + |
| 118 | +# Install certifi and auditwheel |
| 119 | +$PY36_BIN/pip install --require-hashes -r $MY_DIR/py36-requirements.txt |
| 120 | + |
| 121 | +# Our openssl doesn't know how to find the system CA trust store |
| 122 | +# (https://github.com/pypa/manylinux/issues/53) |
| 123 | +# And it's not clear how up-to-date that is anyway |
| 124 | +# So let's just use the same one pip and everyone uses |
| 125 | +ln -s $($PY36_BIN/python -c 'import certifi; print(certifi.where())') \ |
| 126 | + /opt/_internal/certs.pem |
| 127 | +# If you modify this line you also have to modify the versions in the |
| 128 | +# Dockerfiles: |
| 129 | +export SSL_CERT_FILE=/opt/_internal/certs.pem |
| 130 | + |
| 131 | +# Now we can delete our built OpenSSL headers/static libs since we've linked everything we need |
| 132 | +rm -rf /usr/local/ssl |
| 133 | + |
| 134 | +# Install patchelf (latest with unreleased bug fixes) |
| 135 | +curl -fsSL -o patchelf.tar.gz https://github.com/NixOS/patchelf/archive/$PATCHELF_VERSION.tar.gz |
| 136 | +check_sha256sum patchelf.tar.gz $PATCHELF_HASH |
| 137 | +tar -xzf patchelf.tar.gz |
| 138 | +(cd patchelf-$PATCHELF_VERSION && ./bootstrap.sh && do_standard_install) |
| 139 | +rm -rf patchelf.tar.gz patchelf-$PATCHELF_VERSION |
| 140 | + |
| 141 | +ln -s $PY36_BIN/auditwheel /usr/local/bin/auditwheel |
| 142 | + |
| 143 | +# HACK: The newly compiled and installed curl messes with the system's |
| 144 | +# py2.6 installation, on which yum depends. Work around it by |
| 145 | +# rewiring libcurl.so specifically for yum. /usr/local/bin/ has higher |
| 146 | +# priority on the PATH than /usr/bin/ |
| 147 | +cat <<'EOF' > /usr/local/bin/yum && chmod +x /usr/local/bin/yum |
| 148 | +#!/bin/bash |
| 149 | +if [ "x$(arch)" != xi686 ]; then |
| 150 | + LD_PRELOAD=/usr/lib64/libcurl.so.4 |
| 151 | +else |
| 152 | + LD_PRELOAD=/usr/lib/libcurl.so.4 |
| 153 | +fi |
| 154 | +export LD_PRELOAD |
| 155 | +/usr/bin/yum "$@" |
| 156 | +EOF |
| 157 | +# the above might not shadow the real yum just yet, so call hash to be |
| 158 | +# sure: |
| 159 | +type yum |
| 160 | +hash yum |
| 161 | + |
| 162 | + |
| 163 | +# Clean up development headers and other unnecessary stuff for |
| 164 | +# final image |
| 165 | +yum -y erase \ |
| 166 | + avahi \ |
| 167 | + bitstream-vera-fonts \ |
| 168 | + freetype \ |
| 169 | + gettext \ |
| 170 | + gtk2 \ |
| 171 | + hicolor-icon-theme \ |
| 172 | + libX11 \ |
| 173 | + wireless-tools \ |
| 174 | + ${PYTHON_COMPILE_DEPS} > /dev/null 2>&1 |
| 175 | +yum -y install ${MANYLINUX2010_DEPS} |
| 176 | +yum -y clean all > /dev/null 2>&1 |
| 177 | +yum list installed |
| 178 | + |
| 179 | +# we don't need libpython*.a, and they're many megabytes |
| 180 | +find /opt/_internal -name '*.a' -print0 | xargs -0 rm -f |
| 181 | + |
| 182 | +# Strip what we can -- and ignore errors, because this just attempts to strip |
| 183 | +# *everything*, including non-ELF files: |
| 184 | +find /opt/_internal -type f -print0 \ |
| 185 | + | xargs -0 -n1 strip --strip-unneeded 2>/dev/null || true |
| 186 | +find /usr/local -type f -print0 \ |
| 187 | + | xargs -0 -n1 strip --strip-unneeded 2>/dev/null || true |
| 188 | + |
| 189 | +for PYTHON in /opt/python/*/bin/python; do |
| 190 | + # Smoke test to make sure that our Pythons work, and do indeed detect as |
| 191 | + # being manylinux compatible: |
| 192 | + $PYTHON $MY_DIR/manylinux-check.py |
| 193 | + # Make sure that SSL cert checking works |
| 194 | + $PYTHON $MY_DIR/ssl-check.py |
| 195 | +done |
| 196 | + |
| 197 | +# We do not need the Python test suites, or indeed the precompiled .pyc and |
| 198 | +# .pyo files. Partially cribbed from: |
| 199 | +# https://github.com/docker-library/python/blob/master/3.4/slim/Dockerfile |
| 200 | +find /opt/_internal -depth \ |
| 201 | + \( -type d -a -name test -o -name tests \) \ |
| 202 | + -o \( -type f -a -name '*.pyc' -o -name '*.pyo' \) | xargs rm -rf |
| 203 | + |
| 204 | +# Fix libc headers to remain compatible with C99 compilers. |
| 205 | +find /usr/include/ -type f -exec sed -i 's/\bextern _*inline_*\b/extern __inline __attribute__ ((__gnu_inline__))/g' {} + |
| 206 | + |
| 207 | +# remove useless things that have been installed by devtoolset-8 |
| 208 | +rm -rf /opt/rh/devtoolset-8/root/usr/share/man |
| 209 | +find /opt/rh/devtoolset-8/root/usr/share/locale -mindepth 1 -maxdepth 1 -not \( -name 'en*' -or -name 'locale.alias' \) | xargs rm -rf |
| 210 | +rm -rf /usr/share/backgrounds |
| 211 | +# if we updated glibc, we need to strip locales again... |
| 212 | +localedef --list-archive | grep -v -i ^en_US.utf8 | xargs localedef --delete-from-archive |
| 213 | +mv -f /usr/lib/locale/locale-archive /usr/lib/locale/locale-archive.tmpl |
| 214 | +build-locale-archive |
| 215 | +find /usr/share/locale -mindepth 1 -maxdepth 1 -not \( -name 'en*' -or -name 'locale.alias' \) | xargs rm -rf |
| 216 | +find /usr/local/share/locale -mindepth 1 -maxdepth 1 -not \( -name 'en*' -or -name 'locale.alias' \) | xargs rm -rf |
| 217 | +rm -rf /usr/local/share/man |
| 218 | + |
0 commit comments