@@ -27,7 +27,6 @@ function abort() {
2727case " ${STACK:? } " in
2828 heroku-22 | heroku-24)
2929 SUPPORTED_PYTHON_VERSIONS=(
30- " 3.9"
3130 " 3.10"
3231 " 3.11"
3332 " 3.12"
@@ -58,10 +57,6 @@ case "${PYTHON_MAJOR_VERSION}" in
5857 SIGSTORE_IDENTITY=' pablogsal@python.org'
5958 SIGSTORE_ISSUER=' https://accounts.google.com'
6059 ;;
61- 3.9)
62- SIGSTORE_IDENTITY=' lukasz@langa.pl'
63- SIGSTORE_ISSUER=' https://github.com/login/oauth'
64- ;;
6560 * )
6661 abort " Unsupported Python version '${PYTHON_MAJOR_VERSION} '!"
6762 ;;
@@ -102,42 +97,34 @@ CONFIGURE_OPTS=(
10297 " --enable-optimizations"
10398 # Make autoconf's configure option validation more strict.
10499 " --enable-option-checking=fatal"
100+ # Shared builds are beneficial for a number of reasons:
101+ # - Reduces the size of the build, since it avoids the duplication between
102+ # the Python binary and the static library.
103+ # - Permits use-cases that only work with the shared Python library,
104+ # and not the static library (such as `pycall.rb` or `PyO3`).
105+ # - More consistent with the official Python Docker images and other distributions.
106+ #
107+ # Shared builds are slower unless `no-semantic-interposition`and LTO is used,
108+ # however, as of Python 3.10 `no-semantic-interposition` is enabled by default:
109+ # https://fedoraproject.org/wiki/Changes/PythonNoSemanticInterpositionSpeedup
110+ # https://github.com/python/cpython/issues/83161
111+ " --enable-shared"
105112 # Install Python into `/tmp/python` rather than the default of `/usr/local`.
106113 " --prefix=${INSTALL_DIR} "
107114 # Skip running `ensurepip` as part of install, since the buildpack installs a curated
108115 # version of pip itself (which ensures it's consistent across Python patch releases).
109116 " --with-ensurepip=no"
117+ " --with-lto"
118+ # Counter-intuitively, the static library is still generated by default even when
119+ # the shared library is enabled, so we disable it to reduce the build size.
120+ # This option only exists for Python 3.10+.
121+ " --without-static-libpython"
110122)
111123
112- if [[ " ${PYTHON_MAJOR_VERSION} " != + (3.9) ]]; then
113- CONFIGURE_OPTS+=(
114- # Shared builds are beneficial for a number of reasons:
115- # - Reduces the size of the build, since it avoids the duplication between
116- # the Python binary and the static library.
117- # - Permits use-cases that only work with the shared Python library,
118- # and not the static library (such as `pycall.rb` or `PyO3`).
119- # - More consistent with the official Python Docker images and other distributions.
120- #
121- # However, shared builds are slower unless `no-semantic-interposition`and LTO is used:
122- # https://fedoraproject.org/wiki/Changes/PythonNoSemanticInterpositionSpeedup
123- # https://github.com/python/cpython/issues/83161
124- #
125- # It's only as of Python 3.10 that `no-semantic-interposition` is enabled by default,
126- # so we only use shared builds on Python 3.10+ to avoid needing to override the default
127- # compiler flags.
128- " --enable-shared"
129- " --with-lto"
130- # Counter-intuitively, the static library is still generated by default even when
131- # the shared library is enabled, so we disable it to reduce the build size.
132- # This option only exists for Python 3.10+.
133- " --without-static-libpython"
134- )
135- fi
136-
137- if [[ " ${PYTHON_MAJOR_VERSION} " != + (3.9| 3.10) ]]; then
124+ if [[ " ${PYTHON_MAJOR_VERSION} " != + (3.10) ]]; then
138125 CONFIGURE_OPTS+=(
139126 # Skip building the test modules, since we remove them after the build anyway.
140- # This feature was added in Python 3.10+ , however it wasn't until Python 3.11
127+ # This feature was added in Python 3.10, however it wasn't until Python 3.11
141128 # that compatibility issues between it and PGO were fixed:
142129 # https://github.com/python/cpython/pull/29315
143130 " --disable-test-modules"
155142# - https://wiki.ubuntu.com/ToolChain/CompilerFlags
156143# - https://wiki.debian.org/Hardening
157144# - https://github.com/docker-library/python/issues/810
158- # We only use `dpkg-buildflags` for Python versions where we build in shared mode (Python 3.9+),
159- # since some of the options it enables interferes with the stripping of static libraries.
160- if [[ " ${PYTHON_MAJOR_VERSION} " == + (3.9) ]]; then
161- EXTRA_CFLAGS=' '
162- LDFLAGS=' -Wl,--strip-all'
163- else
164- EXTRA_CFLAGS=" $( dpkg-buildflags --get CFLAGS) "
165- LDFLAGS=" $( dpkg-buildflags --get LDFLAGS) -Wl,--strip-all"
166- fi
145+ EXTRA_CFLAGS=" $( dpkg-buildflags --get CFLAGS) "
146+ LDFLAGS=" $( dpkg-buildflags --get LDFLAGS) -Wl,--strip-all"
167147
168148CPU_COUNT=" $( nproc) "
169149make -j " ${CPU_COUNT} " " EXTRA_CFLAGS=${EXTRA_CFLAGS} " " LDFLAGS=${LDFLAGS} "
170150make install
171151
172- if [[ " ${PYTHON_MAJOR_VERSION} " == + (3.9) ]]; then
173- # On older versions of Python we're still building the static library, which has to be
174- # manually stripped since the linker stripping enabled in LDFLAGS doesn't cover them.
175- # We're using `--strip-unneeded` since `--strip-all` would remove the `.symtab` section
176- # that is required for static libraries to be able to be linked.
177- # `find` is used since there are multiple copies of the static library in version-specific
178- # locations, eg:
179- # - `lib/libpython3.9.a`
180- # - `lib/python3.9/config-3.9-x86_64-linux-gnu/libpython3.9.a`
181- find " ${INSTALL_DIR} " -type f -name ' *.a' -print -exec strip --strip-unneeded ' {}' +
182- elif ! find " ${INSTALL_DIR} " -type f -name ' *.a' -print -exec false ' {}' +; then
152+ if ! find " ${INSTALL_DIR} " -type f -name ' *.a' -print -exec false ' {}' +; then
183153 abort " Unexpected static libraries found!"
184154fi
185155
@@ -220,7 +190,7 @@ LD_LIBRARY_PATH="${SRC_DIR}" "${SRC_DIR}/python" -m compileall -f --invalidation
220190# (e.g. `python -m pydoc`) if needed.
221191rm " ${INSTALL_DIR} " /bin/{idle,pydoc}*
222192# The 2to3 module and entrypoint was removed from the stdlib in Python 3.13.
223- if [[ " ${PYTHON_MAJOR_VERSION} " == + (3.9 | 3. 10| 3.11| 3.12) ]]; then
193+ if [[ " ${PYTHON_MAJOR_VERSION} " == + (3.10| 3.11| 3.12) ]]; then
224194 rm " ${INSTALL_DIR} " /bin/2to3*
225195fi
226196
0 commit comments