diff options
author | srv <enmanuel.saravia.externo@pandero.com.pe> | 2025-05-19 12:40:23 +0200 |
---|---|---|
committer | srv <enmanuel.saravia.externo@pandero.com.pe> | 2025-05-19 12:40:23 +0200 |
commit | c092428b53c1306252b66b51f49482650ec1f38b (patch) | |
tree | b2cb5436b0552fc966995e4140dfbcf9a22fb14a /python-build-bin | |
parent | 4366a7c9a4131d5ab5ce400573275a8f8f41a6c2 (diff) |
tlaunch requeriment are compiled, thinkpad touchpad requeriment are compiled, docker requeriment in progress is a long task yet and add validate size
Diffstat (limited to 'python-build-bin')
-rw-r--r-- | python-build-bin/.gitignore | 18 | ||||
-rw-r--r-- | python-build-bin/PKGBUILD | 27 | ||||
-rw-r--r-- | python-build-bin/README.md | 2 | ||||
-rw-r--r-- | python-build-bin/keys/pgp/2FDEC9863E5E14C7BC429F27B9D0E45146A241E8.asc | 92 | ||||
-rw-r--r-- | python-build-bin/keys/pgp/3DCE51D60930EBA47858BA4146F633CBB0EB4BF2.asc | 186 | ||||
-rwxr-xr-x | python-build-bin/python-build | 2519 |
6 files changed, 2844 insertions, 0 deletions
diff --git a/python-build-bin/.gitignore b/python-build-bin/.gitignore new file mode 100644 index 0000000..e4912e4 --- /dev/null +++ b/python-build-bin/.gitignore @@ -0,0 +1,18 @@ +# ---> ArchLinuxPackages +*.tar +*.tar.* +*.jar +*.exe +*.msi +*.zip +*.tgz +*.log +*.log.* +*.sig + +pkg/ +src/ + +*.service +*.timer +*.socket diff --git a/python-build-bin/PKGBUILD b/python-build-bin/PKGBUILD new file mode 100644 index 0000000..a7dd3ef --- /dev/null +++ b/python-build-bin/PKGBUILD @@ -0,0 +1,27 @@ +# Maintainer: Saravia +pkgname=python-build-bin +pkgver=20240515 +pkgrel=1 +pkgdesc="Standalone precompiled python-build from pyenv (minimal wrapper)" +arch=('x86_64') +url="https://github.com/pyenv/pyenv" +license=('MIT') +depends=('bash') +source=( + "python-build::https://raw.githubusercontent.com/pyenv/pyenv/master/plugins/python-build/bin/python-build" +) +sha512sums=('c071c8a70814e7895476ba1d7c4960773b8231a54ea7916d2b05e4021b7efd404be3264466f5e46839d3f210b9841647935cbf86b96b0e0debde3a871ab261cd') + +options=('!strip') + +prepare() { + chmod +x "$srcdir/python-build" +} + +build() { + return 0 +} + +package() { + install -Dm755 "$srcdir/python-build" "$pkgdir/usr/bin/python-build" +} diff --git a/python-build-bin/README.md b/python-build-bin/README.md new file mode 100644 index 0000000..d6ba366 --- /dev/null +++ b/python-build-bin/README.md @@ -0,0 +1,2 @@ +# python-build + diff --git a/python-build-bin/keys/pgp/2FDEC9863E5E14C7BC429F27B9D0E45146A241E8.asc b/python-build-bin/keys/pgp/2FDEC9863E5E14C7BC429F27B9D0E45146A241E8.asc new file mode 100644 index 0000000..93b66e5 --- /dev/null +++ b/python-build-bin/keys/pgp/2FDEC9863E5E14C7BC429F27B9D0E45146A241E8.asc @@ -0,0 +1,92 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +mQINBGAm+DIBEACWuIKIcoD5lqt6cndFiGRXuDrmRt+dRmtcJxm0hbgerjCL++4y +9VgU+jlIdJbd5x9LW5q6Yd34z2jROXxpCiMlp/iEZvz31dwQ3LZ3GDfgSlP/oFyT +CjaHHTqJML5EMN9Rj5iXcs07ayfL3abQ5oe1L/WB2JDrWb+pyggvJXEuONeOFfzr +GPp+tn/y2beD1fFc3iU77al4Nm4iGXLpHhjne4z9jY7d+OrPP7TTfTRJyBokRUJY +5qX5LEf9OMfr+FCedryn25UFvwACHYfyaoiCzkAyOPwg0Qgh1Su4928S9bsanyqb +PWl2kujBYBWTmIDvFIlGlAUzgHec5CB4K9AVyD8FEqHAYK6CqaRdMPjEfi0fjBFP +XafaeThFbxeha8h1TSJqBiIl6+c9t3uSb2I/S/LtMGvGUkK+fMcnN9a6XGqNiPQq +zhYSHt2Q5rafwKFDx43kN2nuF1JZbgnI3RP6bnEF/ryS4SaQZ/1QJTSfUNlT0FHT +RZpeAaUPyWLIYmqvcuhmWC1n9yeU9uep9X4FOFvfU+O1uIz529uUF/5YlDzV2u8e +gB6a+dX4nZaVJiZEqdZZij10avG7Emh6nsbEnHesYBjmRYckqk4v9YJuxVI7WVft +liUfBI52fZJpRaqB0At4paK3qmGc34fho2Pj7NikkGEeH//MOZFvJ+Q4bQARAQAB +tCJIZW5yeSBTY2hyZWluZXIgPGhzY2hyZWluQGNlcm4uY2g+iQJOBBMBCAA4FiEE +L97Jhj5eFMe8Qp8nudDkUUaiQegFAmBjUy4CGwMFCwkIBwIGFQoJCAsCBBYCAwEC +HgECF4AACgkQudDkUUaiQejbDA/9Hk5u7xPUE/p2SkZZ0OgdsnU1eVGD3+GPkSZx +6mC0eiDT2ez+J9KZlIoUJZzktVWoGCYv326bQpE+iD/S0/RJzoADOlpQw7W+joTe +D3oRhr4+CXPXmQ2laoXk3lW+WejZO6IpruWR58VFQgNSZKiV09UeJtg90/4xptJr +zx6KPr8Ch5ksUOD8MvRx0hLdsYSxL0eToFB54OVOU1vBEFNIWpddhWSjHncVlRpa +wAVfhkNq271XH2UzUhf1LG/n6lzg+OoGld8LB1n0oVNfGdmKv2ZBRL+Ffwn4QGl0 +Pw4pMAraGxvOnHtOQtgTSiOYH17ggZ+9zK7U4R6y5j8V+u8NXSX/TFoB78HmooN3 +zeuWVLY//EpOb2F/UYmopW61NWH8oeI2Pr6cQGh0MVmFSrlo/ngtuCkT8VNkhROm ++v7DHC4fB6s/4bd6TffXA9IW1SZaExDEiOE3QQgIEXPq5ispUGEH3f3Aad6ZG014 +jWU8tNs9VY3iiZbF+tGDTqnMORL1lx/wnK5btgYZHbkCXBuirlEiXOeQsMT5sPiQ +Ktp3myd+6bN7xjJAYZ6lpbnKBkYIwDGNY6srhLRpk+d4aglXBy+zOQaTXG87Rf3P +dVA/WqQXCbEDjfBzSy3Ay83ybE8nE0W7zSgFamdaCALYvJNMwj9AQopBfiD5f29v +JiouipG0J0hlbnJ5IFNjaHJlaW5lciA8aGVucnlmc0BwcmluY2V0b24uZWR1PokC +TgQTAQgAOBYhBC/eyYY+XhTHvEKfJ7nQ5FFGokHoBQJgY1MOAhsDBQsJCAcCBhUK +CQgLAgQWAgMBAh4BAheAAAoJELnQ5FFGokHoC4sP/34hhPNaoiwYlpJ5RG8MHgdK +ejxAIyeFxWVs9IgDMERHAHzMr4IJnefga6yCOVMLwWE6dJii0xlubH+P4iOtiHCb +EynnR13TK4SWWNjtwDob2QgMlLw+zOYYUGw844bHkJ2SeIu2U+85M/d6VFOh7pQr +IfHlKI8HVWztkYtF/9BPjmQdeHxN16uPcYA0l5tU5rD9j9/aVCKmuVjONh1tS6eq +y1h7JNdI3dLUVOVQ0r7vfk65y7t4ofkXfq5BRBu1OsUBA9ok9AKWXltusMxTXl+x +8ueZXS0HIiaqeGE9WU14K+xfOWCYV9oSqz8NV5ElmowtRCCPFuarc3zjwhrNUQ30 +slOPdAe9zMYb5Klu9eo5WTJXcuoHFACru775K9prd0JK4oRr/uKU/JZkcXKWmbRW +bzbKDA2qBe7HZfpXmiYTWHqufoCC3JmJgXd6aC7gG2Wfprz+XqAN+syiZXxdW5Gj +9FgaC56SiJWy4D96zzWmhC0uE4I+ZAuiw0AT7x4vjqoh9SvbSpu/lkS4qZb2HNi+ +N4GUyW9KEQx0HtTyES5+MFBkRQrMLvjcS4wUb/vUGqMm5D/xC34+2k0ngUd6Qt+O ++ktRWm3EJ5eOPg/vHwNl3pscMFUPboIhxBEmIjNM/Y6z48mNBLbHwqZUef9FkfZr +SRoPsdVsW8Hlkm/w3rS8tC1IZW5yeSBTY2hyZWluZXIgPGhlbnJ5c2NocmVpbmVy +aWlpQGdtYWlsLmNvbT6JAk4EEwEIADgWIQQv3smGPl4Ux7xCnye50ORRRqJB6AUC +YGNSfgIbAwULCQgHAgYVCgkICwIEFgIDAQIeAQIXgAAKCRC50ORRRqJB6DKiD/9w +4gcUNIl774ya6eA56E1gsewwMh4xY+WvhuqzTvckSbbbdOTjZ6W3ygnjyixm2cXV +3SGdaODUVVbKUwXpwi8WBNQivZs0hJiqbQBdGHouYAd+FspvqKNliFKgLNhuqb6K +Nf84z42G4eqeL/s3Y9eNFgK7pv82U0S8Mf6yqB9fsoR3LPnrZjRRCh+pdJVfkVZh +9uW5rE490zQHQ8wleWwRwszXy5BRTjBYxOeh0gGtqKlZsJtk2Ndf4X6yxuJ0ZDCR +FfZgEWhoiVsMqBXaNp3YLAGmgmTqMNeb23umljT0FD4I43/V2KlOQQAE8AYwXmsT +g5A/Mv8n8GIH3UHsfVag9fg0HSd04P8EzOcOqLMlI7vmwJyssTl1WjIYypMLpW79 +dyVB4ZWGYcqtLKfWAkVLvVkRcQUMW/1HgzIbbDQJL+eSYxdTx2+Jmk0L7OidDYjM +Ssd16xoW3aOlLg1Y7pJ65FKttdtzxlxB43DUPqCNK7fAZ/ZHJTOMbFuy7fMsN7H3 +ExAHOChgk/ExUPyPSWxO3ulXd+bLmbKO7XtgMf7+w1wWFP9vb4Q9aOVyKmnWJt2f +vx0cFT3+6437Oyg9xABgesrKzydtsdpIBgS0s5EptpnpImUKyq0+cbXzNnsNbHlH +z/s6ajwHQSXWILb+yi/VlBdMFDuRwZtDDzpkpz6/mbQ8SGVucnkgU2NocmVpbmVy +IChNQlAgMTYpIDxoZW5yeWlpaUB1c2Vycy5ub3JlcGx5LmdpdGh1Yi5jb20+iQJO +BBMBCAA4FiEEL97Jhj5eFMe8Qp8nudDkUUaiQegFAmAm+DICGwMFCwkIBwIGFQoJ +CAsCBBYCAwECHgECF4AACgkQudDkUUaiQegJcQ/+NEjt1NQSgFwRWYAbmQoA0GT9 +o1+93iXxHMhUEr5FZKNrRPPv/WCDCzJZwKg1Owjb7EXGIy0+HODhv0YURC37/fX7 +2y9TQnxf9RHrnUCFzA+/NJMrm9iAM/Nr2uClB588a1Km15MMQJhgfbD27ZC0h0nG +H3RxUDTVL8YoyqkCz9HWGpCLDibfNdnYykYy/c77hTeoZfV04a3jAzg0OD5WEaFZ +Cp/BNGKwPKXE8hmamZyidkpAZSNzlibRFnW+AG01afZ6Jhm42gJYOaHIvM47fYpv +7EbPWsDfjlcJBNNtescPWysZIKw6xC+WJzKXktCMmQT4JUarxu2yvx9AkKyOlP6P +OILUYj2V2IUfCcVAJHYfHHG+li54X0l5lw+qU2jTUd6UIbcJ7rVM3g/sXLZEawv5 +6Ukz4prqmI/m+YN+TO8EIrcIvBXtPhT7fUOZCn6npqH2VFPcGIA1viV95sFHp9Zs +Dh14tzeLqVRiA4GGcIJh4k37rpCISO3QyNlBfEMqMKbLwZ9MFLBLScVpnH027tVL +ykndioJ6s+RFSp4SBtjw3MKWRfJxO1f0bCmxO6m0t7iqSFuICVS8B/UDdDleq18/ +MS1iD6uf164iTypunRh509RW+J3XG4hFFvwyxvAZ9sLj4zbuEuTyC3DhRUFMYl2d +Tce4w0a+eqsfE+5eTru5Ag0EYCb4MgEQAOONyIOpk/l4k1pubrcsjacMdpdJEdV7 +d/g7aBeahbdwTXBnwXg/hG7NmomTpq1Hrcd3hM/zvSA/VSJYwMh0AKBTQtakKWF9 +AXlXupCeArhaB1bXvpk2Gqgi3wEtHxd3UTs9LBsy/KpAnwufj5s/IjyKysn7FfLc +I9tsS8qztqGxPdXMEtfyqvaAuModAtQOF6sZ5SRM7glFzlPeF1XBteO8nxT9Z2Xo +zB79r8P0R9NeLEhjLaePkDEOnCADaEbSo4YRHKjCDO9+DPfJw2GO9nw8Jb0j+LA1 +qIMxzt1UJiCOyConPy8aWP7UTgNoUDMxC3r0PFhvnnvb2Z7+yWdlqHqiIhtC3bKK +ONsXyeOwwEUE4K2wRJ0XS9AgdaXFlMSi9tdpdISzNDzHdAp5T7KLPSKk4qRxuKBO +D6GIwn+M8ubHfyEsAo0peVMrH1Z63CDYN3fVIHR/xue6YIJLCTnvvU1pCLBZe4Hg +IVWNosajzRMF9bSlYUkdi2ZfrsN9+bo3IGB0KeQWqB23xMNn7svBU7Th8rESBVss +/VxwO1y2UmqFo5fFEj9djOse50/xoz1AgJtbelm/jGXMPut+zFCPe1hQCATDZ8Uq +rSq0W/6MUszCy31qjzPm/YM+UcrmWZH0XN0bPc1ocw5uVeDud88ChdWDiOF0/OrF +WOWUSiqKJsGbABEBAAGJAjYEGAEIACAWIQQv3smGPl4Ux7xCnye50ORRRqJB6AUC +YCb4MgIbDAAKCRC50ORRRqJB6K0KD/48HqxkFDjYSMernroNrLgg7Be8PSpeySUz +J51/134xCi47EQjr7bUBrczon7mqUQtiVn+/ia2rumsu0uJcFs3lxSsj0r1yKVr6 +cCDzb1yiNxT13efmRWokse4jicTMqo1t5Q5uYIjPxjoT8MHp3sJcpS6oXbUDztbc +dSeXYwuhx7vGA5HvzJ4qo8SYT2RjzVY35T5hkf0QWTF89xZsmgdMlcYQO97syLTU +ro/YmHjhzwsRxAC5K+AYmZIvR67J0lrnKR98U1YNgqVjFbsJr8hIM29KwZWDWmza +IjgFGhrmJhgWcMrGzcxWzaHkNuI56s0HNIQsuJ9dMulp5mOPdvrdX8kllZJcL1aU +Y24NLM/+EM8vX733DmY8uwdNojTdicnnQcoCm6EW3Np8uZlUgTMq0+VduaWaGtye +D21w6lZjKFlixhouCk1zscC5/y8721vtFGuuMMVUTjVm4qvHBN2Tjw26U4RRdOW0 +y7a70O0KneIoyXrjLMQUySV3d13j6GWfPw4CEGEDZ+pFzS4M6U3m5Y+Q31N+one+ +lZgow+A3J8gKTOV9YNR7Ons1Kn+SuJ62p3UJlwiDc5VBRY2PLkpsErea6A33HV/H +5Nt1t7TQwGs9pRTaXIndOT5tKuWnPUraIfRhhPA1jNp/c/4roC6kLosM5htAcSfr +Kj097u15JQ== +=om07 +-----END PGP PUBLIC KEY BLOCK----- diff --git a/python-build-bin/keys/pgp/3DCE51D60930EBA47858BA4146F633CBB0EB4BF2.asc b/python-build-bin/keys/pgp/3DCE51D60930EBA47858BA4146F633CBB0EB4BF2.asc new file mode 100644 index 0000000..a0adeef --- /dev/null +++ b/python-build-bin/keys/pgp/3DCE51D60930EBA47858BA4146F633CBB0EB4BF2.asc @@ -0,0 +1,186 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +JxAAvBrH/nGF1opnde86pHbAM2MtZ48/ZmLkUGghxgXNkgkN1sdOixsY/hS19Fj0 +2MHTWF0CmY2SPczTEKNDm02iosdEPyLSBTokxStjH/H5MZ2Uk4iLybleIBmVsn1o +qffuUglvzpkPfEnRyCvpybulfP+F8B9H21CMsvG1ljQ9yveOZZGp2n5mNRGqR1Km +ZrEFsamkQg827qY89ZgNglhvogPl4wTjEkQseZNQAiy4sZsKi54pcNoUq80uh/qc +VwuV0T17dA3NZ+EjEsPLDJRd8hSRSl45W/LXta+o9OLMCqLUhe+ysC09hFw8p1Im +8rDh8L56Wesh9NejBeSHfxlCWlDT2s++ZNIsq2tcwtDUq71yzO73UX7hqWVrf+iL +rbwXiIlOebTutjzujAKDI6b44W6bolD+NHCldqJ+CRxp4vkQQTRdYzglC4bVqpRe +A4IJlCvuIUenWYB2LZfN8RjmKTZQc8XJwG9gwnRCu5O6xaIs+5x8tlcYNQASM7sK +J6tsQKb+zs5zogz96IFYtoz2t1x0i62VOtdhd91ber+jlXE9aJpHTMOAacG7ArUJ +GlR7PDTlcixT2L6HfVdRGGYDJl34UoJcg0R3gIGOI0t/m4fT0c8OIcdUNGN/gGYd +gtIi5jRI8FdI+T9jJpPLWd6aV5iLwV6I2uVc4EucTeMlH4c= +=BBWu +-----END PGP PUBLIC KEY BLOCK----- diff --git a/python-build-bin/python-build b/python-build-bin/python-build new file mode 100755 index 0000000..b8b1b92 --- /dev/null +++ b/python-build-bin/python-build @@ -0,0 +1,2519 @@ +#!/usr/bin/env bash +# +# Usage: python-build [-kpv] <definition> <prefix> +# python-build --definitions +# python-build --version +# +# -k/--keep Do not remove source tree after installation +# -p/--patch Apply a patch from stdin before building +# -v/--verbose Verbose mode: print compilation status to stdout +# -4/--ipv4 Resolve names to IPv4 addresses only +# -6/--ipv6 Resolve names to IPv6 addresses only +# --definitions List all built-in definitions +# --version Show version of python-build +# -g/--debug Build a debug version +# + +PYTHON_BUILD_VERSION="20180424" + +OLDIFS="$IFS" + +set -E +shopt -s extglob +[ -n "$PYENV_DEBUG" ] && { + export PS4='+(${BASH_SOURCE}:${LINENO}): ${FUNCNAME[0]:+${FUNCNAME[0]}(): }' + set -x +} + +exec 3<&2 # preserve original stderr at fd 3 + + +lib() { + parse_options() { + OPTIONS=() + ARGUMENTS=() + local arg option index + + for arg in "$@"; do + if [ "${arg:0:1}" = "-" ]; then + if [ "${arg:1:1}" = "-" ]; then + OPTIONS[${#OPTIONS[*]}]="${arg:2}" + else + index=1 + while option="${arg:$index:1}"; do + [ -n "$option" ] || break + OPTIONS[${#OPTIONS[*]}]="$option" + index=$(($index+1)) + done + fi + else + ARGUMENTS[${#ARGUMENTS[*]}]="$arg" + fi + done + } + + if [ "$1" == "--$FUNCNAME" ]; then + declare -f "$FUNCNAME" + echo "$FUNCNAME \"\$1\";" + exit + fi +} +lib "$1" + +READLINK=$(type -P readlink) +if [ -z "$READLINK" ]; then + echo "pyenv: cannot find readlink - are you missing GNU coreutils?" >&2 + exit 1 +fi + +resolve_link() { + $READLINK "$1" +} + +abs_dirname() { + local path="$1" + + # Use a subshell to avoid changing the current path + ( + while [ -n "$path" ]; do + cd_path="${path%/*}" + if [[ "$cd_path" != "$path" ]]; then + cd "$cd_path" + fi + name="${path##*/}" + path="$(resolve_link "$name" || true)" + done + + echo "$PWD" + ) +} + +capitalize() { + printf "%s" "$1" | tr a-z A-Z +} + +sanitize() { + printf "%s" "$1" | sed "s/[^A-Za-z0-9.-]/_/g; s/__*/_/g" +} + +colorize() { + if [ -t 1 ]; then printf "\e[%sm%s\e[m" "$1" "$2" + else echo -n "$2" + fi +} + +os_information() { + if type -p lsb_release >/dev/null; then + lsb_release -sir | xargs echo + elif type -p sw_vers >/dev/null; then + echo "OS X ${_PYTHON_BUILD_CACHE_SW_VERS:=$(sw_vers -productVersion)}" + elif [ -r /etc/os-release ]; then + source /etc/os-release + echo "$NAME" $VERSION_ID + else + local os="$(cat /etc/{centos,redhat,fedora,system}-release /etc/debian_version 2>/dev/null | head -n1)" + echo "${os:-$(uname -sr)}" + fi +} + +is_mac() { + [ "${_PYTHON_BUILD_CACHE_UNAME_S:=$(uname -s)}" = "Darwin" ] || return 1 + [ $# -eq 0 ] || [ "$(osx_version)" "$@" ] +} + +can_use_homebrew() { + [[ -n "$PYTHON_BUILD_USE_HOMEBREW" && -n "$PYTHON_BUILD_SKIP_HOMEBREW" ]] && { + echo "error: mutually exclusive environment variables PYTHON_BUILD_USE_HOMEBREW and PYTHON_BUILD_SKIP_HOMEBREW are set" >&3 + exit 1 + } + [[ -n "$PYTHON_BUILD_USE_HOMEBREW" ]] && return 0 + [[ -n "$PYTHON_BUILD_SKIP_HOMEBREW" ]] && return 1 + is_mac && return 0 + # In Linux, if Pyenv itself is installed with Homebrew, + # we assume the user wants to take dependencies from there as well by default + command -v brew &>/dev/null && [[ $(abs_dirname "${BASH_SOURCE}") == "$(abs_dirname "$(brew --prefix 2>/dev/null ||true)")"/* ]] && return 0 + return 1 +} + +# 9.1 -> 901 +# 10.9 -> 1009 +# 10.10 -> 1010 +osx_version() { + local -a ver + IFS=. ver=( ${_PYTHON_BUILD_CACHE_SW_VERS:=$(sw_vers -productVersion)} ) + IFS="$OLDIFS" + echo $(( ${ver[0]}*100 + ${ver[1]} )) +} + +build_failed() { + { echo + colorize 1 "BUILD FAILED" + echo " ($(os_information) using $(version))" + echo + + if ! rmdir "${BUILD_PATH}" 2>/dev/null; then + echo "Inspect or clean up the working tree at ${BUILD_PATH}" + fi + + if file_is_not_empty "$LOG_PATH"; then + colorize 33 "Results logged to ${LOG_PATH}" + printf "\n\n" + echo "Last 10 log lines:" + tail -n 10 "$LOG_PATH" + fi + } >&3 + exit 1 +} + +file_is_not_empty() { + local filename="$1" + local line_count="$(wc -l "$filename" 2>/dev/null || true)" + + if [ -n "$line_count" ]; then + words=( $line_count ) + [ "${words[0]}" -gt 0 ] + else + return 1 + fi +} + +num_cpu_cores() { + local num + case "${_PYTHON_BUILD_CACHE_UNAME_S:=$(uname -s)}" in + Darwin | *BSD ) + num="$(sysctl -n hw.ncpu 2>/dev/null || true)" + ;; + SunOS ) + num="$(getconf NPROCESSORS_ONLN 2>/dev/null || true)" + ;; + * ) + num="$({ getconf _NPROCESSORS_ONLN || + grep -c ^processor /proc/cpuinfo; } 2>/dev/null)" + num="${num#0}" + ;; + esac + echo "${num:-2}" +} + +install_package() { + install_package_using "tarball" 1 "$@" +} + +install_nightly_package() { + install_package_using "nightly_tarball" 2 "$@" +} + +install_git() { + install_package_using "git" 2 "$@" +} + +install_hg() { + install_package_using "hg" 2 "$@" +} + +install_svn() { + install_package_using "svn" 2 "$@" +} + +install_jar() { + install_package_using "jar" 1 "$@" +} + +install_zip() { + install_package_using "zip" 1 "$@" +} + +install_script() { + install_package_using "script" 1 "$@" +} + +install_package_using() { + local package_type="$1" + local package_type_nargs="$2" + local package_name="$3" + shift 3 + + local fetch_args=( "$package_name" "${@:1:$package_type_nargs}" ) + local make_args=( "$package_name" ) + local arg last_arg + + for arg in "${@:$(( $package_type_nargs + 1 ))}"; do + if [ "$last_arg" = "--if" ]; then + "$arg" || return 0 + elif [ "$arg" != "--if" ]; then + make_args["${#make_args[@]}"]="$arg" + fi + last_arg="$arg" + done + + pushd "$BUILD_PATH" >&4 + "fetch_${package_type}" "${fetch_args[@]}" + make_package "${make_args[@]}" + popd >&4 + + echo "Installed ${package_name} to ${PREFIX_PATH}" >&2 +} + +make_package() { + local package_name="$1" + shift + + pushd "$package_name" >&4 + setup_builtin_patches "$package_name" + before_install_package "$package_name" + build_package "$package_name" $* + after_install_package "$package_name" + cleanup_builtin_patches "$package_name" + fix_directory_permissions + popd >&4 +} + +compute_sha2() { + local output + if type shasum &>/dev/null; then + output="$(shasum -a 256 -b)" || return 1 + echo "${output% *}" + elif type openssl &>/dev/null; then + local openssl="$(command -v "$(brew --prefix openssl 2>/dev/null || true)"/bin/openssl openssl | head -n1)" + output="$("$openssl" dgst -sha256 2>/dev/null)" || return 1 + echo "${output##* }" + elif type sha256sum &>/dev/null; then + output="$(sha256sum -b)" || return 1 + echo "${output%% *}" + else + return 1 + fi +} + +compute_md5() { + local output + if type md5 &>/dev/null; then + md5 -q + elif type openssl &>/dev/null; then + output="$(openssl md5)" || return 1 + echo "${output##* }" + elif type md5sum &>/dev/null; then + output="$(md5sum -b)" || return 1 + echo "${output%% *}" + else + return 1 + fi +} + +has_checksum_support() { + local checksum_command="$1" + local has_checksum_var="HAS_CHECKSUM_SUPPORT_${checksum_command}" + + if [ -z "${!has_checksum_var+defined}" ]; then + printf -v "$has_checksum_var" "$(echo test | "$checksum_command" >/dev/null; echo $?)" + fi + return "${!has_checksum_var}" +} + +verify_checksum() { + local checksum_command + local filename="$1" + local expected_checksum="$(echo "$2" | tr [A-Z] [a-z])" + + # If the specified filename doesn't exist, return success + [ -e "$filename" ] || return 0 + + case "${#expected_checksum}" in + 0) return 0 ;; # empty checksum; return success + 32) checksum_command="compute_md5" ;; + 64) checksum_command="compute_sha2" ;; + *) + { echo + echo "unexpected checksum length: ${#expected_checksum} (${expected_checksum})" + echo "expected 0 (no checksum), 32 (MD5), or 64 (SHA2-256)" + echo + } >&4 + return 1 ;; + esac + + # If chosen provided checksum algorithm isn't supported, return success + has_checksum_support "$checksum_command" || return 0 + + # If the computed checksum is empty, return failure + local computed_checksum=`echo "$($checksum_command < "$filename")" | tr [A-Z] [a-z]` + [ -n "$computed_checksum" ] || return 1 + + if [ "$expected_checksum" != "$computed_checksum" ]; then + { echo + echo "checksum mismatch: ${filename} (file is corrupt)" + echo "expected $expected_checksum, got $computed_checksum" + echo + } >&4 + return 1 + fi +} + +http() { + local method="$1" + [ -n "$2" ] || return 1 + shift 1 + + PYTHON_BUILD_HTTP_CLIENT="${PYTHON_BUILD_HTTP_CLIENT:-$(detect_http_client)}" + [ -n "$PYTHON_BUILD_HTTP_CLIENT" ] || return 1 + + "http_${method}_${PYTHON_BUILD_HTTP_CLIENT}" "$@" +} + +detect_http_client() { + local client + for client in aria2c curl wget; do + if type "$client" &>/dev/null; then + echo "$client" + return + fi + done + echo "error: please install \`aria2c\`, \`curl\`, or \`wget\` and try again" >&2 + return 1 +} + +http_head_aria2c() { + aria2c --dry-run --no-conf=true ${ARIA2_OPTS} "$1" >&4 2>&1 +} + +http_get_aria2c() { + # aria2c always treats -o argument as a relative path + local out dir_out; + if [[ -n "$2" ]]; then + out="$(basename $2)"; + dir_out="$(dirname $2)"; + else + out="$(mktemp "out.XXXXXX")"; + dir_out="$TMPDIR"; + fi + + # In Ubuntu, aria2c is only available as a snap. Snaps cannot read or write /tmp + # (files cannot be found, any write result is silently discarded). + local aria2c_is_snap; + if [[ $(command -v aria2c) == "/snap/"* ]]; then aria2c_is_snap=1; fi + + if [[ -n $aria2c_is_snap ]]; then + local real_dir_out="$dir_out" + # presumably, snaps can always write to under $HOME + dir_out="$HOME" + fi + + if aria2c --allow-overwrite=true --no-conf=true -d "${dir_out}" -o "${out}" ${ARIA2_OPTS} "$1" >&4; then + [ -n "$2" ] || cat "${dir_out:-.}/${out}" + else + false + fi + ret=$? + + if [[ -n "$2" && -n $aria2c_is_snap ]]; then + mv "$dir_out/$out" "$real_dir_out/$out" + fi + return "$ret" +} + +http_head_curl() { + curl -qsILf ${CURL_OPTS} "$1" >&4 2>&1 +} + +http_get_curl() { + curl -q -o "${2:--}" -sSLf ${CURL_OPTS} "$1" +} + +http_head_wget() { + wget -q --spider ${WGET_OPTS} "$1" >&4 2>&1 +} + +http_get_wget() { + wget -nv ${WGET_OPTS} -O "${2:--}" "$1" +} + +fetch_tarball() { + local package_name="$1" + local package_url="$2" + local mirror_url + local checksum + local extracted_dir + + if [ "$package_url" != "${package_url/\#}" ]; then + checksum="${package_url#*#}" + package_url="${package_url%%#*}" + + if [ -n "$PYTHON_BUILD_MIRROR_URL" ]; then + if [[ -z "$PYTHON_BUILD_DEFAULT_MIRROR" || $package_url != */www.python.org/* ]]; then + mirror_url="${PYTHON_BUILD_MIRROR_URL}/$checksum" + fi + fi + fi + + local tar_args="xzf" + local package_filename="${package_name}.tar.gz" + + if [ "$package_url" != "${package_url%bz2}" ]; then + if ! type -p bzip2 >/dev/null; then + echo "warning: bzip2 not found; consider installing \`bzip2\` package" >&4 + fi + package_filename="${package_filename%.gz}.bz2" + tar_args="${tar_args/z/j}" + fi + + if [ "$package_url" != "${package_url%xz}" ]; then + if ! type -p xz >/dev/null; then + echo "warning: xz not found; consider installing \`xz\` package" >&4 + fi + package_filename="${package_filename%.gz}.xz" + tar_args="${tar_args/z/J}" + fi + + if ! reuse_existing_tarball "$package_filename" "$checksum"; then + # Report the cached file name -- sometimes, it's useful to know (#1743) + echo "Downloading ${package_filename}..." >&2 + http head "$mirror_url" && + download_tarball "$mirror_url" "$package_filename" "$checksum" || + download_tarball "$package_url" "$package_filename" "$checksum" + fi + + { if tar $tar_args "$package_filename"; then + if [ ! -d "$package_name" ]; then + extracted_dir="$(find_extracted_directory)" + mv "$extracted_dir" "$package_name" + fi + + if [ -z "$KEEP_BUILD_PATH" ]; then + rm -f "$package_filename" + else + true + fi + fi + } >&4 2>&1 +} + +find_extracted_directory() { + for f in *; do + if [ -d "$f" ]; then + echo "$f" + return + fi + done + echo "Extracted directory not found" >&2 + return 1 +} + +fetch_nightly_tarball() { + local package_name="$1" + local package_url="$2" + local package_pattern="$3" + fetch_tarball "$1" "$2" + if [ ! -e "${package_name}" ]; then + local nightly_package_name="$(echo ${package_pattern})" + if [ -e "${nightly_package_name}" ]; then + ln -fs "${nightly_package_name}" "${package_name}" + fi + fi +} + +reuse_existing_tarball() { + local package_filename="$1" + local checksum="$2" + + # Reuse existing file in build location + if [ -e "$package_filename" ] && verify_checksum "$package_filename" "$checksum"; then + return 0 + fi + + # Reuse previously downloaded file in cache location + [ -n "$PYTHON_BUILD_CACHE_PATH" ] || return 1 + local cached_package_filename="${PYTHON_BUILD_CACHE_PATH}/$package_filename" + + [ -e "$cached_package_filename" ] || return 1 + verify_checksum "$cached_package_filename" "$checksum" >&4 2>&1 || return 1 + ln -s "$cached_package_filename" "$package_filename" >&4 2>&1 || return 1 +} + +download_tarball() { + local official_source="www.python.org/ftp/python" + if [ -n "$PYTHON_BUILD_MIRROR_URL_SKIP_CHECKSUM" ]; then + local package_url="$(echo "$1" | sed -e "s|.*//${URL_BASE:-$official_source}|$PYTHON_BUILD_MIRROR_URL|g")" + else + local package_url="$1" + fi + [ -n "$package_url" ] || return 1 + + local package_filename="$2" + local checksum="$3" + + echo "-> $package_url" >&2 + + if http get "$package_url" "$package_filename" >&4 2>&1; then + verify_checksum "$package_filename" "$checksum" >&4 2>&1 || return 1 + else + echo "error: failed to download $package_filename" >&2 + return 1 + fi + + if [ -n "$PYTHON_BUILD_CACHE_PATH" ]; then + local cached_package_filename="${PYTHON_BUILD_CACHE_PATH}/$package_filename" + { mv "$package_filename" "$cached_package_filename" + ln -s "$cached_package_filename" "$package_filename" + } >&4 2>&1 || return 1 + fi +} + +has_tar_xz_support() { + [[ -z $_PYTHON_BUILD_FORCE_SKIP_XZ ]] && tar Jcf - /dev/null 1>/dev/null 2>&1 +} + +fetch_git() { + local package_name="$1" + local git_url="$2" + local git_ref="$3" + + echo "Cloning ${git_url}..." >&2 + + if type git &>/dev/null; then + if [ -n "$PYTHON_BUILD_CACHE_PATH" ]; then + pushd "$PYTHON_BUILD_CACHE_PATH" >&4 + local clone_name="$(sanitize "$git_url")" + if [ -e "${clone_name}" ]; then + { cd "${clone_name}" + git fetch --force "$git_url" "+${git_ref}:${git_ref}" + } >&4 2>&1 + else + git clone --bare --branch "$git_ref" "$git_url" "${clone_name}" >&4 2>&1 + fi + git_url="$PYTHON_BUILD_CACHE_PATH/${clone_name}" + popd >&4 + fi + + if [ -e "${package_name}" ]; then + ( cd "${package_name}" + git fetch --depth 1 origin "+${git_ref}" + git checkout -q -B "$git_ref" "origin/${git_ref}" + ) >&4 2>&1 + else + git clone --depth 1 --branch "$git_ref" "$git_url" "${package_name}" >&4 2>&1 + fi + else + echo "error: please install \`git\` and try again" >&2 + exit 1 + fi +} + +fetch_hg() { + local package_name="$1" + local hg_url="$2" + local hg_ref="$3" + + echo "Cloning ${hg_url}..." >&2 + + if type hg &>/dev/null; then + if [ -n "$PYTHON_BUILD_CACHE_PATH" ]; then + pushd "$PYTHON_BUILD_CACHE_PATH" >&4 + local clone_name="$(sanitize "$hg_url")" + if [ -e "${clone_name}" ]; then + { cd "${clone_name}" + hg pull --force "$hg_url" + } >&4 2>&1 + else + { hg clone --branch "$hg_ref" "$hg_url" "${clone_name}" + cd "${clone_name}" + hg update null + } >&4 2>&1 + fi + hg_url="$PYTHON_BUILD_CACHE_PATH/${clone_name}" + popd >&4 + fi + + hg clone --branch "$hg_ref" "$hg_url" "${package_name}" >&4 2>&1 + else + echo "error: please install \`mercurial\` and try again" >&2 + exit 1 + fi +} + +fetch_svn() { + local package_name="$1" + local svn_url="$2" + local svn_rev="$3" + + echo "Checking out ${svn_url}..." >&2 + + if type svn &>/dev/null; then + svn co -r "$svn_rev" "$svn_url" "${package_name}" >&4 2>&1 + elif type svnlite &>/dev/null; then + svnlite co -r "$svn_rev" "$svn_url" "${package_name}" >&4 2>&1 + else + echo "error: please install Subversion and try again" >&2 + exit 1 + fi +} + +fetch_jar() { + local package_name="$1" + local package_url="$2" + local mirror_url + local checksum + + if [ "$package_url" != "${package_url/\#}" ]; then + checksum="${package_url#*#}" + package_url="${package_url%%#*}" + + if [ -n "$PYTHON_BUILD_MIRROR_URL" ]; then + mirror_url="${PYTHON_BUILD_MIRROR_URL}/$checksum" + fi + fi + + local package_filename="${package_name}.jar" + + if ! reuse_existing_tarball "$package_filename" "$checksum"; then + echo "Downloading ${package_filename}..." >&2 + http head "$mirror_url" && + download_tarball "$mirror_url" "$package_filename" "$checksum" || + download_tarball "$package_url" "$package_filename" "$checksum" + fi + + # Must use full path to jar and destination directory: + # http://bugs.jython.org/issue2350 + { if $JAVA -jar "$PWD/${package_name}.jar" -s -d "$PWD/${package_name}"; then + if [ -z "$KEEP_BUILD_PATH" ]; then + rm -f "$package_filename" + else + true + fi + fi + } >&4 2>&1 +} + +fetch_zip() { + local package_name="$1" + local package_url="$2" + local mirror_url + local checksum + + if [ "$package_url" != "${package_url/\#}" ]; then + checksum="${package_url#*#}" + package_url="${package_url%%#*}" + + if [ -n "$PYTHON_BUILD_MIRROR_URL" ]; then + mirror_url="${PYTHON_BUILD_MIRROR_URL}/$checksum" + fi + fi + + local package_filename="${package_name}.zip" + + if ! reuse_existing_tarball "$package_filename" "$checksum"; then + echo "Downloading ${package_filename}..." >&2 + http head "$mirror_url" && + download_tarball "$mirror_url" "$package_filename" "$checksum" || + download_tarball "$package_url" "$package_filename" "$checksum" + fi + + { if unzip "$package_filename"; then + if [ -z "$KEEP_BUILD_PATH" ]; then + rm -f "$package_filename" + else + true + fi + fi + } >&4 2>&1 +} + +fetch_script() { + local package_name="$1" + local package_url="$2" + local mirror_url + local checksum + + if [ "$package_url" != "${package_url/\#}" ]; then + checksum="${package_url#*#}" + package_url="${package_url%%#*}" + + if [ -n "$PYTHON_BUILD_MIRROR_URL" ]; then + mirror_url="${PYTHON_BUILD_MIRROR_URL}/$checksum" + fi + fi + + local package_filename="${package_name}.sh" # TODO: extract suffix from ${package_url} + + if ! reuse_existing_tarball "$package_filename" "$checksum"; then + echo "Downloading ${package_filename}..." >&2 + http head "$mirror_url" && + download_tarball "$mirror_url" "$package_filename" "$checksum" || + download_tarball "$package_url" "$package_filename" "$checksum" + fi + + mkdir -p "$(dirname "${package_name}/${package_filename}")" + mv -f "${package_filename}" "${package_name}/${package_filename}" +} + +build_package() { + local package_name="$1" + shift + + if [ "$#" -eq 0 ]; then + local commands="standard" + else + local commands="$*" + fi + + echo "Installing ${package_name}..." >&2 + + [ -n "$HAS_PATCH" ] && apply_patch "$package_name" <(cat "${package_name}.patch") + + for command in $commands; do + "build_package_${command}" "$package_name" + done +} + +package_option() { + local package_name="$1" + local command_name="$2" + local variable="$(capitalize "${package_name}_${command_name}")_OPTS_ARRAY" + local array="$variable[@]" + shift 2 + local value=( "${!array}" "$@" ) + eval "$variable=( \"\${value[@]}\" )" +} + +build_package_warn_eol() { + local package_name="$1" + + { echo + echo "WARNING: $package_name is past its end of life and is now unsupported." + echo "It no longer receives bug fixes or critical security updates." + echo + } >&3 +} + +build_package_warn_unsupported() { + local package_name="$1" + + { echo + echo "WARNING: $package_name is nearing its end of life." + echo "It only receives critical security updates, no bug fixes." + echo + } >&3 +} + +build_package_standard_build() { + local package_name="$1" + + if [ "${MAKEOPTS+defined}" ]; then + MAKE_OPTS="$MAKEOPTS" + elif [ -z "${MAKE_OPTS+defined}" ]; then + MAKE_OPTS="-j $(num_cpu_cores)" + fi + + # Support YAML_CONFIGURE_OPTS, PYTHON_CONFIGURE_OPTS, etc. + local package_var_name="$(capitalize "${package_name%%-*}")" + local PACKAGE_CONFIGURE="${package_var_name}_CONFIGURE" + local PACKAGE_PREFIX_PATH="${package_var_name}_PREFIX_PATH" + local PACKAGE_CONFIGURE_OPTS="${package_var_name}_CONFIGURE_OPTS" + local PACKAGE_CONFIGURE_OPTS_ARRAY="${package_var_name}_CONFIGURE_OPTS_ARRAY[@]" + local PACKAGE_MAKE_OPTS="${package_var_name}_MAKE_OPTS" + local PACKAGE_MAKE_OPTS_ARRAY="${package_var_name}_MAKE_OPTS_ARRAY[@]" + local PACKAGE_CFLAGS="${package_var_name}_CFLAGS" + local PACKAGE_CPPFLAGS="${package_var_name}_CPPFLAGS" + local PACKAGE_LDFLAGS="${package_var_name}_LDFLAGS" + + if [ "$package_var_name" = "PYTHON" ]; then + use_homebrew || true + use_custom_tcltk || use_homebrew_tcltk || true + use_homebrew_readline || use_freebsd_pkg || true + use_homebrew_ncurses || true + if is_mac -ge 1014; then + use_xcode_sdk_zlib || use_homebrew_zlib || true + else + use_homebrew_zlib || true + fi + use_dsymutil || true + use_free_threading || true + fi + + ( if [[ -n "${!PACKAGE_CFLAGS}" ]]; then + export CFLAGS="${CFLAGS:+$CFLAGS }${!PACKAGE_CFLAGS}" + fi + if [[ -n "${!PACKAGE_CPPFLAGS}" ]]; then + export CPPFLAGS="${CPPFLAGS:+$CPPFLAGS }${!PACKAGE_CPPFLAGS}" + fi + if [[ -n "${!PACKAGE_LDFLAGS}" ]]; then + export LDFLAGS="${LDFLAGS:+$LDFLAGS }${!PACKAGE_LDFLAGS}" + fi + if [ -z "$CC" ] && is_mac -ge 1010; then + export CC=clang + fi + ${!PACKAGE_CONFIGURE:-./configure} --prefix="${!PACKAGE_PREFIX_PATH:-$PREFIX_PATH}" \ + "${!PACKAGE_CONFIGURE_OPTS_ARRAY}" $CONFIGURE_OPTS ${!PACKAGE_CONFIGURE_OPTS} || return 1 + ) >&4 2>&1 + + { "$MAKE" "${!PACKAGE_MAKE_OPTS_ARRAY}" $MAKE_OPTS ${!PACKAGE_MAKE_OPTS} + } >&4 2>&1 +} + +build_package_standard_install() { + local package_name="$1" + local package_var_name="$(capitalize "${package_name%%-*}")" + + local PACKAGE_MAKE_INSTALL_OPTS="${package_var_name}_MAKE_INSTALL_OPTS" + local PACKAGE_MAKE_INSTALL_OPTS_ARRAY="${package_var_name}_MAKE_INSTALL_OPTS_ARRAY[@]" + local PACKAGE_MAKE_INSTALL_TARGET="${package_var_name}_MAKE_INSTALL_TARGET" + + { "$MAKE" "${!PACKAGE_MAKE_INSTALL_TARGET:-install}" $MAKE_INSTALL_OPTS ${!PACKAGE_MAKE_INSTALL_OPTS} "${!PACKAGE_MAKE_INSTALL_OPTS_ARRAY}" + } >&4 2>&1 +} + +# Backward Compatibility for standard function +build_package_standard() { + build_package_standard_build "$@" + build_package_standard_install "$@" +} + +build_package_autoconf() { + { autoreconf + } >&4 2>&1 +} + +build_package_python() { + local package_name="$1" + + { "$PYTHON_BIN" setup.py install + } >&4 2>&1 +} + +remove_windows_files() { + cd "$PREFIX_PATH" + rm -f bin/*.exe bin/*.dll bin/*.bat +} + +build_package_jython() { + build_package_copy + { if [ -x "${PREFIX_PATH}/bin/jython" ] && [ ! -x "${PREFIX_PATH}/bin/python" ]; then + ( cd "${PREFIX_PATH}/bin" && ln -fs jython python ) + fi + } >&4 2>&1 + fix_jython_shebangs +} + +fix_jython_shebangs() { + # Workaround for Jython 2.7+ (#458) + for file in "${PREFIX_PATH}/bin"/*; do + case "$(head -n1 "${file}")" in + "#!"*"/bin/jython" ) + sed -i.bak "1 s:.*:#\!${PREFIX_PATH}\/bin\/jython:" "${file}" + ;; + "#!"*"/bin/python2.7"* ) + sed -i.bak "1 s:.*:#\!\/usr\/bin\/env python:" "${file}" + ;; + esac + rm -f "${file}.bak" + done +} + +build_package_jython_builder() { + ant >&4 2>&1 + ( cd "dist" && build_package_jython ) +} + +build_package_pyston2_2() { + # currently supported version 2.2 and 2.3 + build_package_copy + mkdir -p "${PREFIX_PATH}/bin" "${PREFIX_PATH}/lib" + local bin + shopt -s nullglob + for bin in "bin/"*; do + if [ -f "${bin}" ] && [ -x "${bin}" ] && [ ! -L "${bin}" ]; then + case "${bin##*/}" in + "pyston"* ) + ( cd "${PREFIX_PATH}/bin" && ln -fs "${bin##*/}" "python" ) + ;; + esac + fi + done + shopt -u nullglob +} + +build_package_pyston() { + # currently supported version 2.3.1v2 and higher + build_package_copy +} + +build_package_ironpython() { + mkdir -p "${PREFIX_PATH}/bin" + cp -fR . "${PREFIX_PATH}/bin" + chmod +x "${PREFIX_PATH}/bin/"*.exe + ( cd "${PREFIX_PATH}/bin" && ln -fs ipy.exe python ) +} + +build_package_ironpython_builder() { + xbuild Build.proj /t:Stage "/p:Mono=true;BaseConfiguration=Release" >&4 2>&1 + ( cd "Stage/Release/IronPython-"* && build_package_ironpython ) +} + +build_package_micropython_1_9() { + # supported version 1.9.3 and 1.9.4 + build_package_micropython "with_axtls" +} + +build_package_micropython() { + # supported version 1.10 and higher + if [ "${MAKEOPTS+defined}" ]; then + MAKE_OPTS="$MAKEOPTS" + elif [ -z "${MAKE_OPTS+defined}" ]; then + MAKE_OPTS="-j $(num_cpu_cores)" + fi + { cd mpy-cross + "$MAKE" $MAKE_OPTS + cd ../ports/unix + [ "$1" = "with_axtls" ] && "$MAKE" $MAKE_OPTS axtls + "$MAKE" $MAKE_OPTS CFLAGS_EXTRA="-DMICROPY_PY_SYS_PATH_DEFAULT='\".frozen:${PREFIX_PATH}/lib/micropython\"' $CFLAGS_EXTRA" + "$MAKE" install $MAKE_INSTALL_OPTS PREFIX="${PREFIX_PATH}" + ln -fs micropython "${PREFIX_PATH}/bin/python" + mkdir -p "${PREFIX_PATH}/lib/micropython" + }>&4 2>&1 +} + +pypy_architecture() { + case "${_PYTHON_BUILD_CACHE_UNAME_S:=$(uname -s)}" in + "Darwin" ) + case "$(uname -m)" in + "arm64" ) echo "osarm64" ;; + "x86_64" ) echo "osx64" ;; + * ) return 1 ;; + esac + ;; + "Linux" ) + case "$(uname -m)" in + "armel" ) echo "linux-armel" ;; + "armhf" | "armv6l" | "armv7l" ) echo "linux-armhf" ;; + "i386" | "i486" | "i586" | "i686" | "i786" ) echo "linux" ;; + "ppc64" ) echo "linux-ppc64" ;; + "ppc64le" ) echo "linux-ppc64le" ;; + "x86_64" ) echo "linux64" ;; + "aarch64" ) echo "linux-aarch64" ;; + * ) return 1 ;; + esac + ;; + "CYGWIN"* | "MINGW"* ) echo "win32" ;; + "FreeBSD" ) + case "$(uname -m)" in + "x86_64" ) echo "freebsd64" ;; + * ) return 1 ;; + esac + ;; + * ) return 1 ;; + esac +} + +graalpy_architecture() { + case "${_PYTHON_BUILD_CACHE_UNAME_S:=$(uname -s)}" in + "Darwin" ) + case "$(uname -m)" in + "x86_64" ) echo "macos-amd64" ;; + "arm64" ) echo "macos-aarch64" ;; + * ) return 1 ;; + esac + ;; + "Linux" ) + case "$(uname -m)" in + "x86_64" ) echo "linux-amd64" ;; + "aarch64" ) echo "linux-aarch64" ;; + * ) return 1 ;; + esac + ;; + esac +} + +pyston_architecture() { + pypy_architecture +} + +# Note: not used by graalpy >= 23.3.0 anymore +build_package_graalpython() { + build_package_copy + ln -fs "${PREFIX_PATH}/bin/graalpython" "${PREFIX_PATH}/bin/python" +} + +build_package_pypy() { + build_package_copy + mkdir -p "${PREFIX_PATH}/bin" "${PREFIX_PATH}/lib" + local bin + shopt -s nullglob + for bin in "bin/"*; do + if [ -f "${bin}" ] && [ -x "${bin}" ] && [ ! -L "${bin}" ]; then + case "${bin##*/}" in + "libpypy"* ) + ( cd "${PREFIX_PATH}/lib" && ln -fs "../bin/${bin##*/}" "${bin##*/}" ) + ;; + "pypy"* ) + ( cd "${PREFIX_PATH}/bin" && ln -fs "${bin##*/}" "python" ) + ;; + esac + fi + done + shopt -u nullglob +} + +build_package_pypy_builder() { + if [ -f "rpython/bin/rpython" ]; then # pypy 2.x + if [ -z "${PYPY_OPTS}" ]; then + local PYPY_OPTS="--opt=jit --batch --make-jobs=$(num_cpu_cores)" + fi + python "rpython/bin/rpython" ${PYPY_OPTS} "pypy/goal/targetpypystandalone.py" >&4 2>&1 + elif [ -f "pypy/translator/goal/translate.py" ]; then # pypy 1.x + if [ -z "${PYPY_OPTS}" ]; then + local PYPY_OPTS="--opt=jit" + fi + ( cd "pypy/translator/goal" && python "translate.py" ${PYPY_OPTS} "targetpypystandalone.py" ) 1>&4 2>&1 + else + echo "not a pypy source tree" 1>&3 + return 1 + fi + { mkdir -p "bin" "lib" + local pypy + for pypy in "pypy"*; do + if [ -f "${pypy}" ] && [ -x "${pypy}" ] && [ ! -L "${pypy}" ]; then + mv -f "${pypy}" "bin/${pypy##*/}" + fi + done + local libpypy + for libpypy in "libpypy"*; do + if [ -f "${libpypy}" ] && [ -x "${libpypy}" ] && [ ! -L "${libpypy}" ]; then + mv -f "${libpypy}" "bin/${libpypy##*/}" + fi + done + } >&4 2>&1 + build_package_pypy +} + +activepython_architecture() { + case "${_PYTHON_BUILD_CACHE_UNAME_S:=$(uname -s)}" in + "Darwin" ) echo "macosx10.9-i386-x86_64" ;; + "Linux" ) + case "$(uname -m)" in + "i386" | "i486" | "i586" | "i686" | "i786" ) echo "linux-x86" ;; + "x86_64" ) echo "linux-x86_64" ;; + * ) return 1 ;; + esac + ;; + * ) return 1 ;; + esac +} + +build_package_activepython() { + local package_name="$1" + { bash "install.sh" --install-dir "${PREFIX_PATH}" + } >&4 2>&1 +} + +anaconda_architecture() { + case "${_PYTHON_BUILD_CACHE_UNAME_S:=$(uname -s)}" in + "Darwin" ) + case "$(uname -m)" in + "arm64" ) echo "MacOSX-arm64" ;; + * ) echo "MacOSX-x86_64" ;; + esac + ;; + "Linux" ) + case "$(uname -m)" in + "armv7l" ) echo "Linux-armv7l" ;; + "aarch64" ) echo "Linux-aarch64" ;; + "i386" | "i486" | "i586" | "i686" | "i786" ) echo "Linux-x86" ;; + "ppc64le" ) echo "Linux-ppc64le" ;; + "x86_64" ) echo "Linux-x86_64" ;; + * ) return 1 ;; + esac + ;; + * ) return 1 ;; + esac +} + +build_package_anaconda() { + local package_name="$1" + { bash "${package_name}.sh" -f -b -p "${PREFIX_PATH}" + } >&4 2>&1 +} + +build_package_miniconda() { + build_package_anaconda "$@" + # Workaround to not upgrade conda when installing pip + # see https://github.com/pyenv/pyenv/issues/2070 + "${PREFIX_PATH}/bin/conda" install --yes "pip" "conda=$(${PREFIX_PATH}/bin/conda --version | cut -d ' ' -f 2)" +} + +build_package_copy() { + mkdir -p "$PREFIX_PATH" + cp -fR . "$PREFIX_PATH" +} + +before_install_package() { + local stub=1 +} + +after_install_package() { + local stub=1 +} + +setup_builtin_patches() { + local package_name="$1" + local package_patch_path="${DEFINITION_PATH%/*}/patches/${DEFINITION_PATH##*/}/${package_name}" + +# Apply built-in patches if patch was not given from stdin + if [[ -n "$HAS_STDIN_PATCH" ]] && package_is_python "${package_name}"; then + cat >"${package_name}.patch" + HAS_PATCH=true + elif [[ -d "${package_patch_path}" ]]; then + { find "${package_patch_path}" -maxdepth 1 -type f + } 2>/dev/null | sort | xargs cat 1>"${package_name}.patch" + HAS_PATCH=true + fi +} + +cleanup_builtin_patches() { + local package_name="$1" + rm -f "${package_name}.patch" + unset HAS_PATCH +} + +fix_directory_permissions() { + # Ensure installed directories are not world-writable + find "$PREFIX_PATH" -type d \( -perm -020 -o -perm -002 \) -exec chmod go-w {} \; +} + +require_java7() { + local version="$(java -version 2>&1 | grep '\(java\|openjdk\) version' | head -n1)" + if [[ $version != *[789]* ]]; then + colorize 1 "ERROR" >&3 + echo ": Java 7 required. Please install a 1.7-compatible JRE." >&3 + return 1 + fi +} + +require_gcc() { + local gcc="$(locate_gcc || true)" + + if [ -z "$gcc" ]; then + { echo + colorize 1 "ERROR" + echo ": This package must be compiled with GCC, but python-build couldn't" + echo "find a suitable \`gcc\` executable on your system. Please install GCC" + echo "and try again." + echo + + if is_mac; then + colorize 1 "DETAILS" + echo ": Apple no longer includes the official GCC compiler with Xcode" + echo "as of version 4.2. Instead, the \`gcc\` executable is a symlink to" + echo "\`llvm-gcc\`, a modified version of GCC which outputs LLVM bytecode." + echo + echo "For most programs the \`llvm-gcc\` compiler works fine. However," + echo "versions of CPython newer than 3.3.0 are incompatible with" + echo "\`llvm-gcc\`. To build newer versions of CPython you must have the official" + echo "GCC compiler installed on your system." + echo + + colorize 1 "TO FIX THE PROBLEM" + if type brew &>/dev/null; then + echo ": Install Homebrew's GCC package with this" + echo -n "command: " + colorize 4 "brew install gcc@4.9" + else + echo ": Install the official GCC compiler using these" + echo -n "packages: " + colorize 4 "https://github.com/kennethreitz/osx-gcc-installer/downloads" + fi + + echo + echo + echo "You will need to install the official GCC compiler to build newer" + echo "versions of CPython even if you have installed Apple's Command Line Tools" + echo "for Xcode package. The Command Line Tools for Xcode package only" + echo "includes \`llvm-gcc\`." + fi + } >&3 + return 1 + fi + + export CC="$gcc" + if is_mac -ge 1010; then + export MACOSX_DEPLOYMENT_TARGET=${MACOSX_DEPLOYMENT_TARGET:-10.9} + fi +} + +locate_gcc() { + local gcc gccs + IFS=: gccs=($(gccs_in_path)) + IFS="$OLDIFS" + + verify_gcc "$CC" || + verify_gcc "$(command -v gcc || true)" || { + for gcc in "${gccs[@]}"; do + verify_gcc "$gcc" && break || true + done + } + + return 1 +} + +gccs_in_path() { + local gcc path paths + local gccs=() + IFS=: paths=($PATH) + IFS="$OLDIFS" + + shopt -s nullglob + for path in "${paths[@]}"; do + for gcc in "$path"/gcc-*; do + gccs["${#gccs[@]}"]="$gcc" + done + done + shopt -u nullglob + + printf :%s "${gccs[@]}" +} + +verify_gcc() { + local gcc="$1" + if [ -z "$gcc" ]; then + return 1 + fi + + local version="$("$gcc" --version 2>/dev/null || true)" + if [ -z "$version" ]; then + return 1 + fi + + if echo "$version" | grep LLVM >/dev/null; then + return 1 + fi + + echo "$gcc" +} + +require_llvm() { + local llvm_version="$1" + if is_mac -ge 1010; then + if [[ "$PYTHON_CONFIGURE_OPTS" != *--llvm-* ]]; then + case "$llvm_version" in + 3.2 ) + package_option python configure --prebuilt-name="llvm-3.2-x86_64-apple-darwin13.tar.bz2" + ;; + 3.[56] ) + local llvm_config="$(locate_llvm "$llvm_version")" + if [ -n "$llvm_config" ]; then + package_option python configure --llvm-config="$llvm_config" + else + local homebrew_package="llvm@$llvm_version" + { echo + colorize 1 "ERROR" + echo ": Rubinius will not be able to compile using Apple's LLVM-based " + echo "build tools on OS X. You will need to install LLVM $llvm_version first." + echo + colorize 1 "TO FIX THE PROBLEM" + echo ": Install Homebrew's llvm package with this" + echo -n "command: " + colorize 4 "brew install $homebrew_package" + echo + } >&3 + return 1 + fi + ;; + esac + fi + fi +} + +locate_llvm() { + local llvm_version="$1" + local package llvm_config + shopt -s nullglob + for package in `brew list 2>/dev/null | grep "^llvm"`; do + llvm_config="$(echo "$(brew --prefix "$package")/bin/llvm-config"*)" + if [ -n "$llvm_config" ] && [[ "$("$llvm_config" --version)" = "$llvm_version"* ]]; then + echo "$llvm_config" + break + fi + done + shopt -u nullglob +} + +require_java() { + local java="$(command -v java || true)" + + if [ -z "$java" ]; then + { echo + colorize 1 "ERROR" + echo ": This package must be installed with java, but python-build couldn't" + echo "find a suitable \`java\` executable on your system. Please install Java" + echo "and try again." + echo + } >&3 + return 1 + fi + + export JAVA="$java" +} + +# Let Jython installer to generate shell script instead of python script even if there's `python2.7` available in `$PATH` (#800) +# FIXME: better function naming +unrequire_python27() { + export PATH="${BUILD_PATH}/bin:${PATH}" + mkdir -p "${BUILD_PATH}/bin" + if command -v python2.7 1>/dev/null 2>&1; then + echo false > "${BUILD_PATH}/bin/python2.7" + chmod +x "${BUILD_PATH}/bin/python2.7" + fi +} + +require_distro() { + for arg; do + if [[ "$(cat /etc/issue 2>/dev/null || true)" == "$arg"* ]]; then + return 0 + fi + done + { echo + colorize 1 "WARNING" + echo ": This binary distribution is built for the following distro(s): $@." + echo "installed binary may not run expectedly on other platforms." + echo + } >&2 + return 1 +} + +require_osx_version() { + function version { echo "$@" | awk -F. '{ printf("%d%03d%03d%03d\n", $1,$2,$3,$4); }'; } + + local required_version="$@" + local osx_version="${_PYTHON_BUILD_CACHE_SW_VERS:=$(sw_vers -productVersion)}" + if [[ $(version $osx_version) -ge $(version $required_version) ]]; then + return 0 + fi + return 1 +} + +configured_with_package_dir() { + local package_var_name="$(capitalize "$1")" + shift 1 + local PACKAGE_CONFIGURE_OPTS="${package_var_name}_CONFIGURE_OPTS" + local PACKAGE_CONFIGURE_OPTS_ARRAY="${package_var_name}_MAKE_OPTS_ARRAY[@]" + local arg flag + for arg in ${CONFIGURE_OPTS} ${!PACKAGE_CONFIGURE_OPTS} "${!PACKAGE_CONFIGURE_OPTS_ARRAY}"; do + if [[ "$arg" == "CPPFLAGS="* ]]; then + for flag in ${CPPFLAGS} ${arg##CPPFLAGS=}; do + if [[ "$flag" == "-I"* ]]; then + local header + for header in "$@"; do + if [ -e "${flag##-I}/${header#/}" ]; then + return 0 + fi + done + fi + done + fi + done + return 1 +} + +# `python-config` ignores LDFLAGS envvar. Adding to LIBS is the only way to add extra stuff +# to `python-config --ldflags` output +append_ldflags_libs() { + local args="$1" + export LDFLAGS="${LDFLAGS:+$LDFLAGS }$args" + export LIBS="${LIBS:+${LIBS% } }$args" +} +prepend_ldflags_libs() { + local args="$1" + export LDFLAGS="$args${LDFLAGS:+ $LDFLAGS}" + export LIBS="$args${LIBS:+ $LIBS}" +} + +use_homebrew() { + can_use_homebrew || return 1 + # unless Homebrew is at the default /usr/local, need to add its paths to + # compiler search to be able to use non-keg-only deps from there + if command -v brew &>/dev/null; then + local brew_prefix="$(brew --prefix 2>/dev/null || true)" + # /usr/local/lib:/usr/lib is the default library search path + if [[ -n $brew_prefix && $brew_prefix != "/usr" && $brew_prefix != "/usr/local" ]]; then + export CPPFLAGS="${CPPFLAGS:+$CPPFLAGS }-I${brew_prefix}/include" + append_ldflags_libs "-L${brew_prefix}/lib -Wl,-rpath,${brew_prefix}/lib" + fi + fi +} + +needs_yaml() { + ! configured_with_package_dir "python" "yaml.h" && + ! use_homebrew_yaml +} + +use_homebrew_yaml() { + can_use_homebrew || return 1 + local libdir="$(brew --prefix libyaml 2>/dev/null || true)" + if [ -d "$libdir" ]; then + echo "python-build: use libyaml from homebrew" + export CPPFLAGS="-I$libdir/include${CPPFLAGS:+ $CPPFLAGS}" + export LDFLAGS="-L$libdir/lib${LDFLAGS:+ ${LDFLAGS% }}" + else + return 1 + fi +} + +use_freebsd_pkg() { + # check if FreeBSD + if [ "FreeBSD" = "${_PYTHON_BUILD_CACHE_UNAME_S:=$(uname -s)}" ]; then + # use openssl if installed from Ports Collection + if pkg info -e openssl; then + package_option python configure --with-openssl="/usr/local" + fi + + # check if 11-R or later + release="${_PYTHON_BUILD_CACHE_UNAME_R:=$(uname -r)}" + if [ "${release%%.*}" -ge 11 ]; then + # Use packages from Ports Collection. + # + # Unlike Linux, BSD's cc does not look in /usr/local by default + # where Ports-installed packages are, but they are available via pkg-config. + # Surprisingly, CPython's Configure only uses pkg-config + # to locate some of the dependencies and not others. + # Here we detect those that are (as of this writing) known + # to not be searched via pkg-config. + # + # XXX: As a side effect, this would pick up any other libs from Ports + # that are searched via compiler + if pkg info -e readline || pkg info -e sqlite3; then + export CPPFLAGS="${CPPFLAGS:+$CPPFLAGS }-I/usr/local/include" + export LDFLAGS="${LDFLAGS:+$LDFLAGS }-L/usr/local/lib -Wl,-rpath,/usr/local/lib" + fi + fi + fi +} + +has_broken_mac_readline() { + # Mac OS X 10.4 has broken readline. + # https://github.com/pyenv/pyenv/issues/23 + is_mac && + ! configured_with_package_dir "python" "readline/rlconf.h" && + ! use_homebrew_readline +} + +use_homebrew_readline() { + can_use_homebrew || return 1 + if ! configured_with_package_dir "python" "readline/rlconf.h"; then + local libdir="$(brew --prefix readline 2>/dev/null || true)" + if [ -d "$libdir" ]; then + echo "python-build: use readline from homebrew" + export CPPFLAGS="-I$libdir/include${CPPFLAGS:+ $CPPFLAGS}" + export LDFLAGS="-L$libdir/lib${LDFLAGS:+ $LDFLAGS}" + else + return 1 + fi + fi +} + +use_homebrew_ncurses() { + can_use_homebrew || return 1 + local libdir="$(brew --prefix ncurses 2>/dev/null || true)" + if [ -d "$libdir" ]; then + echo "python-build: use ncurses from homebrew" + export CPPFLAGS="-I$libdir/include${CPPFLAGS:+ $CPPFLAGS}" + export LDFLAGS="-L$libdir/lib${LDFLAGS:+ $LDFLAGS}" + else + return 1 + fi +} + +prefer_openssl11() { + # Allow overriding the preference of OpenSSL version per definition basis (#1302, #1325, #1326) + PYTHON_BUILD_HOMEBREW_OPENSSL_FORMULA="${PYTHON_BUILD_HOMEBREW_OPENSSL_FORMULA:-openssl@1.1 openssl}" + export PYTHON_BUILD_HOMEBREW_OPENSSL_FORMULA +} + +prefer_openssl3() { + # Allow overriding the preference of OpenSSL version per definition basis (#1302, #1325, #1326) + PYTHON_BUILD_HOMEBREW_OPENSSL_FORMULA="${PYTHON_BUILD_HOMEBREW_OPENSSL_FORMULA:-openssl@3 openssl@1.1 openssl}" + export PYTHON_BUILD_HOMEBREW_OPENSSL_FORMULA +} + +build_package_mac_readline() { + # Install to a subdirectory since we don't want shims for bin/readline. + READLINE_PREFIX_PATH="${PREFIX_PATH}/readline" + + # Tell Python to use this readline for its extension. + export CPPFLAGS="-I${READLINE_PREFIX_PATH}/include${CPPFLAGS:+ $CPPFLAGS}" + export LDFLAGS="-L${READLINE_PREFIX_PATH}/lib${LDFLAGS:+ $LDFLAGS}" + + # Make sure pkg-config finds our build first. + export PKG_CONFIG_PATH="${READLINE_PREFIX_PATH}/lib/pkgconfig${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}" + + build_package_standard "$@" +} + +has_broken_mac_openssl() { + is_mac || return 1 + local openssl_version="$(/usr/bin/openssl version 2>/dev/null || true)" + [[ $openssl_version = "OpenSSL 0.9.8"?* || $openssl_version = "LibreSSL"* ]] && + ! use_homebrew_openssl +} + +use_homebrew_openssl() { + can_use_homebrew || return 1 + command -v brew >/dev/null || return 1 + for openssl in ${PYTHON_BUILD_HOMEBREW_OPENSSL_FORMULA:-openssl}; do + local ssldir="$(brew --prefix "${openssl}" || true)" + if [ -d "$ssldir" ]; then + echo "python-build: use ${openssl} from homebrew" + if [[ -n "${PYTHON_BUILD_CONFIGURE_WITH_OPENSSL:-}" ]]; then + # configure script of newer CPython versions support `--with-openssl` + # https://bugs.python.org/issue21541 + package_option python configure --with-openssl="${ssldir}" + else + export CPPFLAGS="-I$ssldir/include ${CPPFLAGS:+ $CPPFLAGS}" + export LDFLAGS="-L$ssldir/lib${LDFLAGS:+ $LDFLAGS}" + fi + export PKG_CONFIG_PATH="$ssldir/lib/pkgconfig/:${PKG_CONFIG_PATH}" + return + fi + done + return 1 +} + +build_package_mac_openssl() { + # Install to a subdirectory since we don't want shims for bin/openssl. + OPENSSL_PREFIX_PATH="${PREFIX_PATH}/openssl" + + # Put openssl.conf, certs, etc in ~/.pyenv/versions/*/openssl/ssl + OPENSSLDIR="${OPENSSLDIR:-$OPENSSL_PREFIX_PATH/ssl}" + + # Tell Python to use this openssl for its extension. + if [[ -n "${PYTHON_BUILD_CONFIGURE_WITH_OPENSSL:-}" ]]; then + # configure script of newer CPython versions support `--with-openssl` + # https://bugs.python.org/issue21541 + package_option python configure --with-openssl="${OPENSSL_PREFIX_PATH}" + else + export CPPFLAGS="-I${OPENSSL_PREFIX_PATH}/include ${CPPFLAGS:+ $CPPFLAGS}" + export LDFLAGS="-L${OPENSSL_PREFIX_PATH}/lib${LDFLAGS:+ $LDFLAGS}" + fi + + # Make sure pkg-config finds our build first. + export PKG_CONFIG_PATH="${OPENSSL_PREFIX_PATH}/lib/pkgconfig${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}" + + # Hint OpenSSL that we prefer a 64-bit build. + export KERNEL_BITS="64" + OPENSSL_CONFIGURE="${OPENSSL_CONFIGURE:-./config}" + + local nokerberos + [[ "$1" != openssl-1.0.* ]] || nokerberos=1 + + # switches introduced in OpenSSL 3.2 + local extra_no_features + [[ $(openssl_version $1) -ge 30200 ]] && extra_no_features=1 + + # Compile a shared lib with zlib dynamically linked. + package_option openssl configure --openssldir="$OPENSSLDIR" zlib-dynamic no-ssl3 shared ${nokerberos:+no-ssl2 no-krb5} ${extra_no_features:+no-docs no-apps} no-tests + + build_package_standard "$@" + + # Extract root certs from the system keychain in .pem format and rehash. + local pem_file="$OPENSSLDIR/cert.pem" + security find-certificate -a -p /Library/Keychains/System.keychain > "$pem_file" + security find-certificate -a -p /System/Library/Keychains/SystemRootCertificates.keychain >> "$pem_file" +} + +# openssl-1.0.1k -> 10001 +# openssl-3.2.1 -> 30201 +openssl_version() { + local -a ver + IFS=- ver=( ${1:?} ) + IFS=. ver=( ${ver[1]} ) + [[ ${ver[2]} =~ ^([[:digit:]]+)[[:alpha:]]$ ]] && ver[2]="${BASH_REMATCH[1]}" + echo $(( ${ver[0]}*10000 + ${ver[1]}*100 + ${ver[2]} )) +} + +# Post-install check that the openssl extension was built. +build_package_verify_openssl() { + "$RUBY_BIN" -e ' + manager = ARGV[0] + packages = { + "apt-get" => Hash.new {|h,k| "lib#{k}-dev" }.update( + "openssl" => "libssl-dev", + "zlib" => "zlib1g-dev" + ), + "yum" => Hash.new {|h,k| "#{k}-devel" }.update( + "yaml" => "libyaml-devel" + ) + } + + failed = %w[openssl readline zlib yaml].reject do |lib| + begin + require lib + rescue LoadError + $stderr.puts "The Ruby #{lib} extension was not compiled." + end + end + + if failed.size > 0 + $stderr.puts "ERROR: Ruby install aborted due to missing extensions" + $stderr.print "Try running `%s install -y %s` to fetch missing dependencies.\n\n" % [ + manager, + failed.map { |lib| packages.fetch(manager)[lib] }.join(" ") + ] unless manager.empty? + $stderr.puts "Configure options used:" + require "rbconfig"; require "shellwords" + RbConfig::CONFIG.fetch("configure_args").shellsplit.each { |arg| $stderr.puts " #{arg}" } + exit 1 + end + ' "$(basename "$(type -P yum apt-get | head -n1)")" >&4 2>&1 +} + +use_homebrew_zlib() { + can_use_homebrew || return 1 + local brew_zlib="$(brew --prefix zlib 2>/dev/null || true)" + if [ -d "$brew_zlib" ]; then + echo "python-build: use zlib from homebrew" + export CFLAGS="-I${brew_zlib} ${CFLAGS}" + fi +} + +use_xcode_sdk_zlib() { + # If a custom compiler is used, including XCode SDK will likely break it + [[ "${CC:-clang}" != "clang" || "$(command -v clang 2>/dev/null || true)" != "/usr/bin/clang" ]] && return 1 + local xc_sdk_path="$(xcrun --show-sdk-path 2>/dev/null || true)" + if [ -d "$xc_sdk_path" ]; then + echo "python-build: use zlib from xcode sdk" + # Even though SDK's compiler uses the SDK dirs implicitly, + # CPython's setup.py has to have nonstandard paths specified explicitly + # to search for zlib.h in them + export CPPFLAGS="${CPPFLAGS:+$CPPFLAGS }-I${xc_sdk_path}/usr/include" + if is_mac -ge 1100; then + export LDFLAGS="${LDFLAGS:+$LDFLAGS }-L${xc_sdk_path}/usr/lib" + fi + fi +} + +use_homebrew_tcltk() { + can_use_homebrew || return 1 + # Since https://github.com/Homebrew/homebrew-core/commit/f10e88617b41555193c22fdcba6109fe82155ee2 (10.11.2024), + # tcl-tk is 9.0 which is not compatible with CPython as of this writing + # but we'll keep it as backup for cases like non-updated Homebrew + local tcltk + for tcltk in "tcl-tk@8" "tcl-tk"; do + local tcltk_libdir="$(brew --prefix "${tcltk}" 2>/dev/null || true)" + if [ -d "$tcltk_libdir" ]; then + echo "python-build: use tcl-tk from homebrew" + if [[ -z "$PYTHON_BUILD_TCLTK_USE_PKGCONFIG" ]]; then + local tcltk_version="$(sh -c '. '"$tcltk_libdir"'/lib/tclConfig.sh; echo $TCL_VERSION')" + package_option python configure --with-tcltk-libs="-L$tcltk_libdir/lib -ltcl$tcltk_version -ltk$tcltk_version" + # In Homebrew Tcl/Tk 8.6.13, headers have been moved to the 'tcl-tk' subdir. + # We're not using tclConfig.sh here 'cuz it produces the version-specific path to <brew prefix>/Cellar + # and we'd rather have rpath set to <brew prefix>/opt/<...> to allow micro release upgrades without rebuilding + # XXX: do use tclConfig.sh and translate the paths if more path shenanigans appear in later releases + if [ -d "$tcltk_libdir/include/tcl-tk" ]; then + package_option python configure --with-tcltk-includes="-I$tcltk_libdir/include/tcl-tk" + else + package_option python configure --with-tcltk-includes="-I$tcltk_libdir/include" + fi + fi + export PKG_CONFIG_PATH="${tcltk_libdir}/lib/pkgconfig${PKG_CONFIG_PATH:+:$PKG_CONFIG_PATH}" + return 0 + fi + done + return 1 +} + +# FIXME: this function is a workaround for #1125 +# once fixed, it should be removed. +# if tcltk_ops_flag is in PYTHON_CONFIGURE_OPTS, use user provided tcltk +use_custom_tcltk() { + local tcltk_ops="$(get_tcltk_flag_from "$PYTHON_CONFIGURE_OPTS")" + + if [[ -z "$tcltk_ops" ]]; then + return 1 + fi + local tcltk_ops_flag="--with-tcltk-libs=" + # get tcltk libs + local tcltk_libs="${tcltk_ops//$tcltk_ops_flag/}" + # remove tcltk-flag from configure_opts + # this allows for weird input such as + # --with-tcltk-libs=' -L/custom-tcl-tk/lib -ltcl8.6 -ltk8.4 ' + PYTHON_CONFIGURE_OPTS="${PYTHON_CONFIGURE_OPTS//"$tcltk_ops_flag"/}" + PYTHON_CONFIGURE_OPTS="${PYTHON_CONFIGURE_OPTS//$tcltk_libs/}" + + # remove quotes, because there mess up compilations + PYTHON_CONFIGURE_OPTS="${PYTHON_CONFIGURE_OPTS//"''"/}" + PYTHON_CONFIGURE_OPTS="${PYTHON_CONFIGURE_OPTS//'""'/}" + + echo "python-build: use tcl-tk from \$PYTHON_CONFIGURE_OPTS" + # echo "PYTHON_CONFIGURE_OPTS=${PYTHON_CONFIGURE_OPTS}" + package_option python configure --with-tcltk-libs="${tcltk_libs}" + # IFS="$OLDIFS" +} + +# FIXME: this function is a workaround for #1125 +# once fixed, it should be removed. +# Get tcltk-flag and options from `$1` +# expects one argument containing a string of configure opts, eg. `PYTHON_CONFIGURE_OPTS` +# returns tcl_tk flag or an empty string if nothing was found. +get_tcltk_flag_from() { + IFS=$'\n' + # parse input string into array + local opts_arr=( $(xargs -n1 <<<"$1") ) + + # iterate through `opts_arr`, break if `--with-tcltk-libs=` was found. + for opts in ${opts_arr[@]}; do + # `--with-tcltk-libs=` must be the prefix. + if [[ "$opts" == "--with-tcltk-libs="* ]]; then + # return + echo "$opts" + break + fi + done + + IFS="$OLDIFS" +} + +# Since 3.12, CPython can add DWARF debug information in MacOS +# using Apple's nonstandard way, `dsymutil', that creates a "dSYM bundle" +# that's supposed to be installed alongside executables +# (https://github.com/python/cpython/issues/95973). +use_dsymutil() { + if [[ -n "$PYTHON_BUILD_CONFIGURE_WITH_DSYMUTIL" ]] && is_mac; then + package_option python configure --with-dsymutil + fi +} + +use_free_threading() { + if [[ -n "$PYTHON_BUILD_FREE_THREADING" ]]; then + package_option python configure --disable-gil + fi +} + +build_package_enable_shared() { + package_option python configure --enable-shared +} + +build_package_auto_tcltk() { + if is_mac && [ ! -d /usr/include/X11 ]; then + if [ -d /opt/X11/include ]; then + if [[ "$CPPFLAGS" != *-I/opt/X11/include* ]]; then + export CPPFLAGS="-I/opt/X11/include${CPPFLAGS:+ $CPPFLAGS}" + fi + else + package_option python configure --without-tk + fi + fi +} + +package_is_python() { + case "$1" in + Python-* | jython-* | pypy-* | pypy[0-9].+([0-9])-* | stackless-* ) + return 0 + ;; + esac + return 1 +} + +apply_patch() { + local package_name="$1" + local patchfile + patchfile="$(mktemp "${TMP}/python-patch.XXXXXX")" + cat "${2:--}" >"$patchfile" + + local striplevel=0 + grep -q '^diff --git a/' "$patchfile" && striplevel=1 + patch -p$striplevel --force -i "$patchfile" +} + + +build_package_symlink_version_suffix() { + if [[ "${PYTHON_CONFIGURE_OPTS_ARRAY[*]} $CONFIGURE_OPTS $PYTHON_CONFIGURE_OPTS" == *"--enable-framework"* ]]; then + if [ -e "${PREFIX_PATH}/bin" ]; then + # Always create `bin` as symlink to framework path if the version was built with `--enable-framework` (#590) + rm -rf "${PREFIX_PATH}/bin.orig" + mv -f "${PREFIX_PATH}/bin" "${PREFIX_PATH}/bin.orig" + fi + # Only symlinks are installed in ${PREFIX_PATH}/bin + ln -fs "${PREFIX_PATH}/Library/Frameworks/Python.framework/Versions/Current/bin" "${PREFIX_PATH}/bin" + fi + + # Not create symlinks on `altinstall` (#255) + if [[ "$PYTHON_MAKE_INSTALL_TARGET" != *"altinstall"* ]]; then + shopt -s nullglob + local version_bin="$(ls -1 "${PREFIX_PATH}/bin/python"* | grep '[0-9]$' | sort | tail -1)" + suffix="$(basename "${version_bin}" | sed -e 's/^python//')" + if [ -n "${suffix}" ]; then + local file link + for file in "${PREFIX_PATH}/bin"/*; do + unset link + case "${file}" in + */"python${suffix}-config" ) + # Symlink `pythonX.Y-config` to `python-config` if `python-config` is missing (#296) + link="${file%/*}/python-config" + ;; + */*"-${suffix}" ) + link="${file%%-${suffix}}" + ;; + */*"${suffix}" ) + link="${file%%${suffix}}" + ;; + esac + if [ -n "$link" ] && [ ! -e "$link" ]; then + ( cd "${file%/*}" && ln -fs "${file##*/}" "${link##*/}" ) + fi + done + fi + shopt -u nullglob + fi +} + +verify_python() { + build_package_symlink_version_suffix + + if [ ! -x "${PYTHON_BIN}" ]; then + { colorize 1 "ERROR" + echo ": invalid Python executable: ${PYTHON_BIN}" + echo + echo "The python-build could not find proper executable of Python after successful build." + echo "Please open an issue for future improvements." + echo "https://github.com/pyenv/pyenv/issues" + return 1 + } >&3 + fi +} + +try_python_module() { + if ! "$PYTHON_BIN" -c "import $1"; then + { colorize 1 "WARNING" + echo ": The Python $1 extension was not compiled${3:+ $3}. Missing the ${2:-$1}?" + return 0 + } >&3 + fi +} + +verify_python_module() { + if ! "$PYTHON_BIN" -c "import $1"; then + { colorize 1 "ERROR" + echo ": The Python $1 extension was not compiled. Missing the ${2:-$1}?" + echo + echo "Please consult to the Wiki page to fix the problem." + echo "https://github.com/pyenv/pyenv/wiki/Common-build-problems" + echo + return 1 + } >&3 + fi +} + +# Post-install check for Python 2.1.x +build_package_verify_py21() { + verify_python "${2:-python2.1}" + try_python_module "readline" "GNU readline lib" + verify_python_module "binascii" "binascii" + # fixme: zlib doesn't link correctly on 64-bit Linux, due to being in + # /usr/x86_64-linux-gnu instead of /usr/lib + try_python_module "zlib" "zlib" + try_python_module "bz2" "bzip2 lib" +} + +# Post-install check for Python 2.2.x +build_package_verify_py22() { + verify_python "${2:-python2.2}" + try_python_module "readline" "GNU readline lib" + verify_python_module "binascii" "binascii" + # fixme: zlib doesn't link correctly on 64-bit Linux, due to being in + # /usr/x86_64-linux-gnu instead of /usr/lib + try_python_module "zlib" "zlib" + try_python_module "bz2" "bzip2 lib" +} + +# Post-install check for Python 2.3.x +build_package_verify_py23() { + verify_python "${2:-python2.3}" + try_python_module "readline" "GNU readline lib" + verify_python_module "binascii" "binascii" + # fixme: zlib doesn't link correctly on 64-bit Linux, due to being in + # /usr/x86_64-linux-gnu instead of /usr/lib + try_python_module "zlib" "zlib" + try_python_module "bz2" "bzip2 lib" +} + +# Post-install check for Python 2.4.x +build_package_verify_py24() { + verify_python "${2:-2.4}" + try_python_module "readline" "GNU readline lib" + verify_python_module "zlib" "zlib" + try_python_module "bz2" "bzip2 lib" +} + +# Post-install check for Python 2.5.x +build_package_verify_py25() { + build_package_verify_py24 "$1" "${2:-2.5}" + try_python_module "sqlite3" "SQLite3 lib" +} + +# Post-install check for Python 2.6.x +build_package_verify_py26() { + build_package_verify_py25 "$1" "${2:-2.6}" + verify_python_module "ssl" "OpenSSL lib" +} + +# Post-install check for Python 2.7.x +build_package_verify_py27() { + build_package_verify_py26 "$1" "${2:-2.7}" +} + +# Post-install check for Python 3.0.x +build_package_verify_py30() { + verify_python "${2:-3.0}" + try_python_module "bz2" "bzip2 lib" + try_python_module "curses" "ncurses lib" + try_python_module "ctypes" "libffi lib" + try_python_module "readline" "GNU readline lib" + verify_python_module "ssl" "OpenSSL lib" + try_python_module "sqlite3" "SQLite3 lib" + if [[ -n $DISPLAY ]]; then + try_python_module "tkinter" "Tk toolkit" "and GUI subsystem has been detected" + fi + verify_python_module "zlib" "zlib" +} + +# Post-install check for Python 3.1.x +build_package_verify_py31() { + build_package_verify_py30 "$1" "${2:-3.1}" +} + +# Post-install check for Python 3.2.x +build_package_verify_py32() { + build_package_verify_py31 "$1" "${2:-3.2}" +} + +# Post-install check for Python 3.3.x +build_package_verify_py33() { + build_package_verify_py32 "$1" "${2:-3.3}" + try_python_module "lzma" "lzma lib" +} + +# Post-install check for Python 3.4.x +build_package_verify_py34() { + build_package_verify_py33 "$1" "${2:-3.4}" +} + +# Post-install check for Python 3.5.x +build_package_verify_py35() { + build_package_verify_py34 "$1" "${2:-3.5}" +} + +# Post-install check for Python 3.6.x +build_package_verify_py36() { + build_package_verify_py35 "$1" "${2:-3.6}" +} + +# Post-install check for Python 3.7.x +build_package_verify_py37() { + build_package_verify_py36 "$1" "${2:-3.7}" +} + +# Post-install check for Python 3.8.x +build_package_verify_py38() { + build_package_verify_py37 "$1" "${2:-3.8}" +} + +# Post-install check for Python 3.9.x +build_package_verify_py39() { + build_package_verify_py38 "$1" "${2:-3.9}" +} + +# Post-install check for Python 3.10.x +build_package_verify_py310() { + build_package_verify_py39 "$1" "${2:-3.10}" +} + +# Post-install check for Python 3.11.x +build_package_verify_py311() { + build_package_verify_py310 "$1" "${2:-3.11}" +} + +# Post-install check for Python 3.12.x +build_package_verify_py312() { + build_package_verify_py311 "$1" "${2:-3.12}" +} + +# Post-install check for Python 3.13.x +build_package_verify_py313() { + build_package_verify_py312 "$1" "${2:-3.13}" +} + +# Post-install check for Python 3.14.x +build_package_verify_py314() { + build_package_verify_py313 "$1" "${2:-3.14}" +} + +# Post-install check for Python 3.15.x +build_package_verify_py315() { + build_package_verify_py314 "$1" "${2:-3.15}" +} + +# Post-install check for Python 3.x rolling release scripts +# XXX: Will need splitting into project-specific ones if there emerge +# multiple rolling-release scripts with different checks needed +build_package_verify_py3_latest() { + build_package_verify_py311 "$1" "3" +} + +# Copy Tools/gdb/libpython.py to pythonX.Y-gdb.py (#1190) +build_package_copy_python_gdb() { + if [ -e "$BUILD_PATH/$1/Tools/gdb/libpython.py" ]; then + local version_re='-([0-9]\.[0-9]+)' + [[ "$1" =~ $version_re ]] + local python_bin="$PREFIX_PATH/bin/python${BASH_REMATCH[1]}" + cp "$BUILD_PATH/$1/Tools/gdb/libpython.py" "$python_bin-gdb.py" + fi +} + +build_package_ez_setup() { + local ez_setup="ez_setup.py" + rm -f "${ez_setup}" + { if [ "${EZ_SETUP+defined}" ] && [ -f "${EZ_SETUP}" ]; then + echo "Installing setuptools from ${EZ_SETUP}..." 1>&2 + cat "${EZ_SETUP}" + else + [ -n "${EZ_SETUP_URL}" ] + echo "Installing setuptools from ${EZ_SETUP_URL}..." 1>&2 + http get "${EZ_SETUP_URL}" + fi + } 1> "${ez_setup}" + "${PYTHON_BIN}" "${ez_setup}" ${EZ_SETUP_OPTS} 1>&4 2>&1 || { + echo "error: failed to install setuptools via ez_setup.py" >&2 + return 1 + } + build_package_symlink_version_suffix +} + +build_package_get_pip() { + local get_pip="get-pip.py" + rm -f "${get_pip}" + { if [ "${GET_PIP+defined}" ] && [ -f "${GET_PIP}" ]; then + echo "Installing pip from ${GET_PIP}..." 1>&2 + cat "${GET_PIP}" + else + [ -n "${GET_PIP_URL}" ] + echo "Installing pip from ${GET_PIP_URL}..." 1>&2 + http get "${GET_PIP_URL}" + fi + } 1> "${get_pip}" + "${PYTHON_BIN}" -s "${get_pip}" ${GET_PIP_OPTS} 1>&4 2>&1 || { + echo "error: failed to install pip via get-pip.py" >&2 + return 1 + } + build_package_symlink_version_suffix +} + +# Pip <21 (in 2.7 and derivatives like PyPy-2.7) doesn't support -I +build_package_ensurepip_lt21() { + build_package_ensurepip lt21 +} + +build_package_ensurepip() { + local mode="$1" + local ensurepip_opts + # Install as `--altinstall` if the Python is installed as `altinstall` (#255) + if [[ "$PYTHON_MAKE_INSTALL_TARGET" == *"altinstall"* ]]; then + ensurepip_opts="--altinstall" + fi + local python_opts="-I" + if [[ $mode == "lt21" ]]; then python_opts="-s"; fi + + # FIXME: `--altinstall` with `get-pip.py` + "$PYTHON_BIN" $python_opts -m ensurepip ${ensurepip_opts} 1>/dev/null 2>&1 || build_package_get_pip "$@" || return 1 + build_package_symlink_version_suffix +} + +version() { + local git_revision + # Read the revision from git if the remote points to "python-build" repository + if GIT_DIR="$PYTHON_BUILD_INSTALL_PREFIX/../../.git" git remote -v 2>/dev/null | grep -q /pyenv; then + git_revision="$(GIT_DIR="$PYTHON_BUILD_INSTALL_PREFIX/../../.git" git describe --tags HEAD 2>/dev/null || true)" + git_revision="${git_revision#v}" + fi + echo "python-build ${git_revision:-$PYTHON_BUILD_VERSION}" +} + +usage() { + sed -ne '/^#/!q;s/.\{1,2\}//;1,2d;p' < "$0" + [ -z "$1" ] || exit "$1" +} + +list_definitions() { + { for DEFINITION_DIR in "${PYTHON_BUILD_DEFINITIONS[@]}"; do + [ -d "$DEFINITION_DIR" ] && ls "$DEFINITION_DIR" | grep -xv patches + done + } | sort_versions | uniq +} + +sort_versions() { + sed 'h; s/[+-]/./g; s/.p\([[:digit:]]\)/.z.\1/; s/$/.z/; G; s/\n/ /' | \ + LC_ALL=C sort -t. -k 1,1 -k 2,2n -k 3,3n -k 4,4n -k 5,5n | awk '{print $2}' +} + + +unset VERBOSE +unset KEEP_BUILD_PATH +unset HAS_PATCH +unset DEBUG +unset IPV4 +unset IPV6 + +PYTHON_BUILD_INSTALL_PREFIX="$(abs_dirname "$0")/.." + +IFS=: PYTHON_BUILD_DEFINITIONS=($PYTHON_BUILD_DEFINITIONS ${PYTHON_BUILD_ROOT:-$PYTHON_BUILD_INSTALL_PREFIX}/share/python-build) +IFS="$OLDIFS" + +parse_options "$@" + +for option in "${OPTIONS[@]}"; do + case "$option" in + "h" | "help" ) + version + echo + usage 0 + ;; + "definitions" ) + list_definitions + exit 0 + ;; + "k" | "keep" ) + KEEP_BUILD_PATH=true + ;; + "v" | "verbose" ) + VERBOSE=true + ;; + "p" | "patch" ) + HAS_STDIN_PATCH=true + ;; + "g" | "debug" ) + DEBUG=true + # Disable optimization (#808) + PYTHON_CFLAGS="-O0 ${PYTHON_CFLAGS}" + ;; + "4" | "ipv4") + IPV4=true + ;; + "6" | "ipv6") + IPV6=true + ;; + "version" ) + version + exit 0 + ;; + esac +done + +[ "${#ARGUMENTS[@]}" -eq 2 ] || usage 1 >&2 + +DEFINITION_PATH="${ARGUMENTS[0]}" +if [ -z "$DEFINITION_PATH" ]; then + usage 1 >&2 +elif [ ! -f "$DEFINITION_PATH" ]; then + for DEFINITION_DIR in "${PYTHON_BUILD_DEFINITIONS[@]}"; do + if [ -f "${DEFINITION_DIR}/${DEFINITION_PATH}" ]; then + DEFINITION_PATH="${DEFINITION_DIR}/${DEFINITION_PATH}" + break + fi + done + + if [ ! -f "$DEFINITION_PATH" ]; then + echo "python-build: definition not found: ${DEFINITION_PATH}" >&2 + exit 2 + fi +fi + +PREFIX_PATH="${ARGUMENTS[1]}" +if [ -z "$PREFIX_PATH" ]; then + usage 1 >&2 +elif [ "${PREFIX_PATH#/}" = "$PREFIX_PATH" ]; then + PREFIX_PATH="${PWD}/${PREFIX_PATH}" +fi + +if [ -z "$TMPDIR" ]; then + TMP="/tmp" +else + TMP="${TMPDIR%/}" +fi + +# Check if TMPDIR is accessible and can hold executables. +tmp_executable="${TMP}/python-build-test.$$" +noexec="" +if mkdir -p "$TMP" && touch "$tmp_executable" 2>/dev/null; then + cat > "$tmp_executable" <<-EOF + #!${BASH} + exit 0 + EOF + chmod +x "$tmp_executable" +else + echo "python-build: TMPDIR=$TMP is set to a non-accessible location" >&2 + exit 1 +fi +"$tmp_executable" 2>/dev/null || noexec=1 +rm -f "$tmp_executable" +if [ -n "$noexec" ]; then + echo "python-build: TMPDIR=$TMP cannot hold executables (partition possibly mounted with \`noexec\`)" >&2 + exit 1 +fi + +if [ -z "$MAKE" ]; then + if [ "FreeBSD" = "${_PYTHON_BUILD_CACHE_UNAME_S:=$(uname -s)}" ]; then + if [ "$(echo $1 | sed 's/-.*$//')" = "jruby" ]; then + export MAKE="gmake" + else + # var assignment inside $() does not propagate due to being in subshell + : "${_PYTHON_BUILD_CACHE_UNAME_R:=$(uname -r)}" + if [ "$(echo "$_PYTHON_BUILD_CACHE_UNAME_R" | sed 's/[^[:digit:]].*//')" -lt 10 ]; then + export MAKE="gmake" + else + export MAKE="make" + fi + fi + else + export MAKE="make" + fi +fi + +if [ -n "$PYTHON_BUILD_CACHE_PATH" ] && [ -d "$PYTHON_BUILD_CACHE_PATH" ]; then + PYTHON_BUILD_CACHE_PATH="${PYTHON_BUILD_CACHE_PATH%/}" +else + unset PYTHON_BUILD_CACHE_PATH +fi + +if [ -z "$PYTHON_BUILD_MIRROR_URL" ]; then + PYTHON_BUILD_MIRROR_URL="https://pyenv.github.io/pythons" + PYTHON_BUILD_DEFAULT_MIRROR=1 +else + PYTHON_BUILD_MIRROR_URL="${PYTHON_BUILD_MIRROR_URL%/}" + PYTHON_BUILD_DEFAULT_MIRROR= +fi + +if [ -n "$PYTHON_BUILD_SKIP_MIRROR" ]; then + unset PYTHON_BUILD_MIRROR_URL +fi + +if ! has_checksum_support compute_sha2 && ! [ -n "$PYTHON_BUILD_MIRROR_URL_SKIP_CHECKSUM" ] ; then + unset PYTHON_BUILD_MIRROR_URL +fi + +ARIA2_OPTS="${PYTHON_BUILD_ARIA2_OPTS} ${IPV4+--disable-ipv6=true} ${IPV6+--disable-ipv6=false}" +CURL_OPTS="${PYTHON_BUILD_CURL_OPTS} ${IPV4+--ipv4} ${IPV6+--ipv6}" +WGET_OPTS="${PYTHON_BUILD_WGET_OPTS} ${IPV4+--inet4-only} ${IPV6+--inet6-only}" + +# Add an option to build a debug version of Python (#11) +if [ -n "$DEBUG" ]; then + package_option python configure --with-pydebug +fi + +if [[ "$CONFIGURE_OPTS $PYTHON_CONFIGURE_OPTS" != *"--enable-framework"* && "$CONFIGURE_OPTS $PYTHON_CONFIGURE_OPTS" != *"--disable-shared"* ]]; then + package_option python configure --enable-shared +fi + +# python-build: Specify `--libdir` on configure to fix build on openSUSE (#36) +package_option python configure --libdir="${PREFIX_PATH}/lib" + +# python-build: Set `RPATH` if `--enable-shared` was given (#65, #66, #82) +if [[ "$CONFIGURE_OPTS $PYTHON_CONFIGURE_OPTS ${PYTHON_CONFIGURE_OPTS_ARRAY[@]}" == *"--enable-shared"* ]]; then + # The ld on Darwin embeds the full paths to each dylib by default + if [[ "$LDFLAGS" != *"-rpath="* ]] ; then + prepend_ldflags_libs "-Wl,-rpath,${PREFIX_PATH}/lib" + fi +fi + +# python-build: Set `RPATH` if --shared` was given for PyPy (#244) +if [[ "$PYPY_OPTS" == *"--shared"* ]]; then + prepend_ldflags_libs "-Wl,-rpath=${PREFIX_PATH}/lib" +fi + +# Add support for framework installation (`--enable-framework`) of CPython (#55, #99) +if [[ "$CONFIGURE_OPTS $PYTHON_CONFIGURE_OPTS" == *"--enable-framework"* ]]; then + if ! is_mac; then + echo "python-build: framework installation is not supported outside of MacOS." >&2 + exit 1 + fi + create_framework_dirs() { + local version="$(echo "$1" | sed -E 's/^[^0-9]*([0-9]+\.[0-9]+).*$/\1/')" + mkdir -p "${PREFIX_PATH}/Library/Frameworks/Python.framework/Versions/${version}" + ( cd "${PREFIX_PATH}/Library/Frameworks/Python.framework/Versions" && ln -fs "${version}" "Current") + local path + for path in include lib share; do + mkdir -p "${PREFIX_PATH}/Library/Frameworks/Python.framework/Versions/Current/${path}" + ln -fs "${PREFIX_PATH}/Library/Frameworks/Python.framework/Versions/Current/${path}" "${PREFIX_PATH}/${path}" + done + } + create_framework_dirs "${DEFINITION_PATH##*/}" + # the `/Library/Frameworks` suffix makes CPython build install apps under prefix rather than into /Applications (#1003) + package_option python configure --enable-framework="${PREFIX_PATH}/Library/Frameworks" + + #FIXME: doesn't properly handle paths with spaces. Fix by parsing *OPTS into arrays. + CONFIGURE_OPTS="${CONFIGURE_OPTS//--enable-framework?(=*([^ ]))?( )/}"; + CONFIGURE_OPTS="${CONFIGURE_OPTS% }" + PYTHON_CONFIGURE_OPTS="${PYTHON_CONFIGURE_OPTS//--enable-framework?(=*([^ ]))?( )/}"; + PYTHON_CONFIGURE_OPTS="${PYTHON_CONFIGURE_OPTS% }" +fi + +# Build against universal SDK +if [[ "$CONFIGURE_OPTS $PYTHON_CONFIGURE_OPTS" == *"--enable-universalsdk"* ]]; then + if ! is_mac; then + echo "python-build: universal installation is not supported outside of MacOS." >&2 + exit 1 + fi + package_option python configure --enable-universalsdk=/ + #FIXME: doesn't properly handle paths with spaces. Fix by parsing *OPTS into arrays. + CONFIGURE_OPTS="${CONFIGURE_OPTS//--enable-universalsdk?(=*([^ ]))?( )/}" + CONFIGURE_OPTS="${CONFIGURE_OPTS% }" + PYTHON_CONFIGURE_OPTS="${PYTHON_CONFIGURE_OPTS//--enable-universalsdk?(=*([^ ]))?( )/}" + PYTHON_CONFIGURE_OPTS="${PYTHON_CONFIGURE_OPTS% }" + + if [[ "$CONFIGURE_OPTS $PYTHON_CONFIGURE_OPTS" != *"--with-universal-archs"* ]]; then + # in CPython's configure.ac, --with-universal-archs defaults to 'intel' which means i386 + x86_64 + # since 2.7.5 and 3.3.0 -- i.e. in all non-EOL versions + # Apple Silicon cannot build these, in it, it rather makes sense to default to Universal2 binaries + if [[ $(arch) == "arm64" ]]; then + package_option python configure --with-universal-archs=universal2 + fi + fi +fi + +# Compile with `--enable-unicode=ucs4` by default (#257) +if [[ "$PYTHON_CONFIGURE_OPTS" != *"--enable-unicode="* ]]; then + if ! is_mac; then + # Skip specifying `--enable-unicode` for CPython 3.3+ (#912) + case "${DEFINITION_PATH##*/}" in + "2."* | \ + "3.0" | "3.0."* | "3.0-"* | \ + "3.1" | "3.1."* | "3.1-"* | \ + "3.2" | "3.2."* | "3.2-"* ) + package_option python configure --enable-unicode=ucs4 + ;; + esac + fi +fi + +# Unset `PIP_REQUIRE_VENV` during build (#216) +unset PIP_REQUIRE_VENV +unset PIP_REQUIRE_VIRTUALENV + +# pydistutils.cfg may corrupt install location of Python libraries (#35, #111) +if [ -e "$HOME/.pydistutils.cfg" ]; then + { colorize 1 "WARNING" + echo ": Please make sure you remove any previous custom paths from your $HOME/.pydistutils.cfg file." + } >&2 +fi + +# Download specified version of ez_setup.py/get-pip.py (#202) +if [ -z "${EZ_SETUP_URL}" ]; then + if [ -n "${SETUPTOOLS_VERSION}" ]; then + EZ_SETUP_URL="https://bitbucket.org/pypa/setuptools/raw/${SETUPTOOLS_VERSION}/ez_setup.py" + unset SETUPTOOLS_VERSION + else + EZ_SETUP_URL="https://bootstrap.pypa.io/ez_setup.py" + fi +fi +if [ -z "${GET_PIP_URL}" ]; then + if [ -n "${PIP_VERSION}" ]; then + { colorize 1 "WARNING" + echo ": Setting PIP_VERSION=${PIP_VERSION} is no longer supported and may cause failures during the install process." + } 1>&2 + GET_PIP_URL="https://raw.githubusercontent.com/pypa/pip/${PIP_VERSION}/contrib/get-pip.py" + # Unset `PIP_VERSION` from environment before invoking `get-pip.py` to deal with "ValueError: invalid truth value" (pypa/pip#4528) + unset PIP_VERSION + else + # Use custom get-pip URL based on the target version (#1127) + case "${DEFINITION_PATH##*/}" in + 2.6 | 2.6.* ) + GET_PIP_URL="https://bootstrap.pypa.io/pip/2.6/get-pip.py" + ;; + 2.7 | 2.7.* | pypy2.7 | pypy2.7-* ) + GET_PIP_URL="https://bootstrap.pypa.io/pip/2.7/get-pip.py" + ;; + 3.2 | 3.2.* ) + GET_PIP_URL="https://bootstrap.pypa.io/pip/3.2/get-pip.py" + ;; + 3.3 | 3.3.* ) + GET_PIP_URL="https://bootstrap.pypa.io/pip/3.3/get-pip.py" + ;; + 3.4 | 3.4.* ) + GET_PIP_URL="https://bootstrap.pypa.io/pip/3.4/get-pip.py" + ;; + 3.5 | 3.5.* | pypy3.5 | pypy3.5-* ) + GET_PIP_URL="https://bootstrap.pypa.io/pip/3.5/get-pip.py" + ;; + 3.6 | 3.6.* | pypy3.6 | pypy3.6-* ) + GET_PIP_URL="https://bootstrap.pypa.io/pip/3.6/get-pip.py" + ;; + 3.7 | 3.7.* | pypy3.7 | pypy3.7-* ) + GET_PIP_URL="https://bootstrap.pypa.io/pip/3.7/get-pip.py" + ;; + 3.8 | 3.8.* | pypy3.8 | pypy3.8-* | pyston* ) + GET_PIP_URL="https://bootstrap.pypa.io/pip/3.8/get-pip.py" + ;; + * ) + GET_PIP_URL="https://bootstrap.pypa.io/get-pip.py" + ;; + esac + fi +fi + +# Set MACOSX_DEPLOYMENT_TARGET from the product version of OS X (#219, #220) +if is_mac; then + if [ -z "${MACOSX_DEPLOYMENT_TARGET}" ]; then + MACOS_VERSION="${_PYTHON_BUILD_CACHE_SW_VERS:=$(sw_vers -productVersion)}" + MACOS_VERSION_ARRAY=(${MACOS_VERSION//\./ }) + if [ "${#MACOS_VERSION_ARRAY[@]}" -ge 2 ]; then + export MACOSX_DEPLOYMENT_TARGET="${MACOS_VERSION_ARRAY[0]}.${MACOS_VERSION_ARRAY[1]}" + fi + fi +fi + +python_bin_suffix() { + local version_name version_info + case "$1" in + 2.* | 3.* ) + version_name="$1" + version_name="${version_name%-dev}" + version_name="${version_name%-rc*}" + version_name="${version_name%rc*}" + version_name="${version_name%%*([^0-9])}" + version_info=(${version_name//./ }) + echo "${version_info[0]}.${version_info[1]}" + ;; + stackless-2.* | stackless-3.* ) + version_name="${1#stackless-}" + version_name="${version_name%-dev}" + version_name="${version_name%-rc*}" + version_name="${version_name%rc*}" + version_info=(${version_name//./ }) + echo "${version_info[0]}.${version_info[1]}" + ;; + esac +} + +SEED="$(date "+%Y%m%d%H%M%S").$$" +LOG_PATH="${TMP}/python-build.${SEED}.log" +PYTHON_BIN="${PREFIX_PATH}/bin/python$(python_bin_suffix "${DEFINITION_PATH##*/}")" +CWD="$(pwd)" + +if [ -z "$PYTHON_BUILD_BUILD_PATH" ]; then + BUILD_PATH="${TMP}/python-build.${SEED}" +else + BUILD_PATH="$PYTHON_BUILD_BUILD_PATH" +fi + +exec 4<> "$LOG_PATH" # open the log file at fd 4 +if [ -n "$VERBOSE" ]; then + tail -f "$LOG_PATH" & + TAIL_PID=$! + trap "kill $TAIL_PID" SIGINT SIGTERM EXIT +fi + +prepend_ldflags_libs "-L${PREFIX_PATH}/lib" +export CPPFLAGS="-I${PREFIX_PATH}/include${CPPFLAGS:+ $CPPFLAGS}" + +unset PYTHONHOME +unset PYTHONPATH + +trap build_failed ERR +mkdir -p "$BUILD_PATH" +source "$DEFINITION_PATH" +[ -z "${KEEP_BUILD_PATH}" ] && rm -fr "$BUILD_PATH" +trap - ERR |