diff --git a/plugins/python-build/bin/python-build b/plugins/python-build/bin/python-build index b8b1b922..812a4581 100755 --- a/plugins/python-build/bin/python-build +++ b/plugins/python-build/bin/python-build @@ -128,13 +128,39 @@ can_use_homebrew() { } [[ -n "$PYTHON_BUILD_USE_HOMEBREW" ]] && return 0 [[ -n "$PYTHON_BUILD_SKIP_HOMEBREW" ]] && return 1 - is_mac && return 0 + is_mac && command -v brew &>/dev/null && 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 } +can_use_macports() { + [[ -n "$PYTHON_BUILD_USE_MACPORTS" && -n "$PYTHON_BUILD_SKIP_MACPORTS" ]] && { + echo "error: mutually exclusive environment variables PYTHON_BUILD_USE_MACPORTS and PYTHON_BUILD_SKIP_MACPORTS are set" >&3 + exit 1 + } + [[ -n "$PYTHON_BUILD_USE_MACPORTS" ]] && return 0 + [[ -n "$PYTHON_BUILD_SKIP_MACPORTS" ]] && return 1 + command -v port &>/dev/null && return 0 + return 1 +} + +is_homebrew_preferred() { + can_use_homebrew || return 1 + [ -n "$PYTHON_BUILD_USE_HOMEBREW" ] && return 0 + local brew_path port_path path paths + command -v port &>/dev/null && port_path=$(dirname "$(command -v port)") + [ -z "$port_path" ] && return 0 + [ -n "$PYTHON_BUILD_USE_MACPORTS" ] && return 1 + command -v brew &>/dev/null && brew_path=$(dirname "$(command -v brew)") + [ -z "$brew_path" ] && return 1 + # Homebrew and MacPorts found in PATH + # find out what to use based on the PATH order + [[ $PATH == *$brew_path*":"*$port_path* ]] && return 0 + return 1 +} + # 9.1 -> 901 # 10.9 -> 1009 # 10.10 -> 1010 @@ -815,14 +841,28 @@ build_package_standard_build() { 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 + if is_homebrew_preferred; then + use_homebrew || true + use_custom_tcltk || use_homebrew_tcltk || true + use_homebrew_readline || 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 + elif can_use_macports; then + use_macports || true + use_custom_tcltk || true + use_macports_readline || true + use_macports_ncurses || true + if is_mac -ge 1014; then + use_xcode_sdk_zlib || use_macports_zlib || true + else + use_macports_zlib || true + fi else - use_homebrew_zlib || true + use_freebsd_pkg || true fi use_dsymutil || true use_free_threading || true @@ -1438,9 +1478,24 @@ use_homebrew() { fi } +use_macports() { + can_use_macports || return 1 + local port_location="$(command -v port)" + if [ -n "$port_location" ]; then + local prefix="${port_location%/bin/port}" + export CPPFLAGS="${CPPFLAGS:+$CPPFLAGS }-I${prefix}/include" + append_ldflags_libs "-L${prefix}/lib -Wl,-rpath,${prefix}/lib" + fi +} + needs_yaml() { - ! configured_with_package_dir "python" "yaml.h" && - ! use_homebrew_yaml + if ! configured_with_package_dir "python" "yaml.h"; then + if is_homebrew_preferred; then + use_homebrew_yaml && return 1 + elif can_use_macports; then + use_macports_yaml && return 1 + fi + fi } use_homebrew_yaml() { @@ -1455,6 +1510,21 @@ use_homebrew_yaml() { fi } +use_macports_yaml() { + can_use_macports || return 1 + local prefix="$(port -q location libyaml 2>/dev/null || true)" + if [ -n "$prefix" ]; then + local libdir="$prefix/opt/local" + if [ -d "$libdir" ]; then + echo "python-build: use libyaml from MacPorts" + export CPPFLAGS="-I$libdir/include${CPPFLAGS:+ $CPPFLAGS}" + export LDFLAGS="-L$libdir/lib${LDFLAGS:+ ${LDFLAGS% }}" + fi + else + return 1 + fi +} + use_freebsd_pkg() { # check if FreeBSD if [ "FreeBSD" = "${_PYTHON_BUILD_CACHE_UNAME_S:=$(uname -s)}" ]; then @@ -1488,9 +1558,13 @@ use_freebsd_pkg() { 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 + if is_mac && ! configured_with_package_dir "python" "readline/rlconf.h"; then + if is_homebrew_preferred; then + use_homebrew_readline && return 1 + elif can_use_macports; then + use_macports_readline && return 1 + fi + fi } use_homebrew_readline() { @@ -1507,6 +1581,23 @@ use_homebrew_readline() { fi } +use_macports_readline() { + can_use_macports || return 1 + if ! configured_with_package_dir "python" "readline/rlconf.h"; then + local prefix="$(port -q location readline 2>/dev/null || true)" + if [ -n "$prefix" ]; then + local libdir="$prefix/opt/local" + if [ -d "$libdir" ]; then + echo "python-build: use readline from MacPorts" + export CPPFLAGS="-I$libdir/include${CPPFLAGS:+ $CPPFLAGS}" + export LDFLAGS="-L$libdir/lib${LDFLAGS:+ $LDFLAGS}" + fi + else + return 1 + fi + fi +} + use_homebrew_ncurses() { can_use_homebrew || return 1 local libdir="$(brew --prefix ncurses 2>/dev/null || true)" @@ -1519,6 +1610,21 @@ use_homebrew_ncurses() { fi } +use_macports_ncurses() { + can_use_macports || return 1 + local prefix="$(port -q location ncurses 2>/dev/null || true)" + if [[ -n "$prefix" ]]; then + local libdir="$prefix/opt/local" + if [ -d "$libdir" ]; then + echo "python-build: use ncurses from MacPorts" + export CPPFLAGS="-I$libdir/include${CPPFLAGS:+ $CPPFLAGS}" + export LDFLAGS="-L$libdir/lib${LDFLAGS:+ $LDFLAGS}" + fi + 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}" @@ -1548,8 +1654,13 @@ build_package_mac_readline() { 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 + if [[ $openssl_version = "OpenSSL 0.9.8"?* || $openssl_version = "LibreSSL"* ]]; then + if is_homebrew_preferred; then + use_homebrew_openssl && return 1 + elif can_use_macports; then + use_macports_openssl && return 1 + fi + fi } use_homebrew_openssl() { @@ -1574,6 +1685,31 @@ use_homebrew_openssl() { return 1 } +use_macports_openssl() { + can_use_macports || return 1 + command -v port >/dev/null || return 1 + for openssl in ${PYTHON_BUILD_HOMEBREW_OPENSSL_FORMULA:-openssl}; do + local ssldir="$(port -q location "${openssl}" 2>/dev/null || true)" + if [ -n "$ssldir" ]; then + ssldir="${ssldir}/opt/local" + if [ -d "$ssldir" ]; then + echo "python-build: use ${openssl} from MacPorts" + 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 + 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" @@ -1687,6 +1823,21 @@ use_xcode_sdk_zlib() { fi } +use_macports_zlib() { + can_use_macports || return 1 + local prefix="$(port -q location zlib 2>/dev/null || true)" + if [[ -n "$prefix" ]]; then + local libdir="$prefix/opt/local" + if [[ -d "$libdir" ]]; then + echo "python-build: use zlib from MacPorts" + export CPPFLAGS="-I$prefix/include ${CPPFLAGS}" + export LDFLAGS="-L$prefix/lib ${LDFLAGS}" + fi + else + return 1 + fi +} + use_homebrew_tcltk() { can_use_homebrew || return 1 # Since https://github.com/Homebrew/homebrew-core/commit/f10e88617b41555193c22fdcba6109fe82155ee2 (10.11.2024), diff --git a/plugins/python-build/test/build.bats b/plugins/python-build/test/build.bats index b0b054cf..f1b29957 100644 --- a/plugins/python-build/test/build.bats +++ b/plugins/python-build/test/build.bats @@ -188,6 +188,135 @@ make install OUT } +@test "Homebrew is used when brew is before port in PATH" { + cached_tarball "Python-3.6.2" + + BREW_PREFIX="$TMP/homebrew-prefix" + mkdir -p "$BREW_PREFIX/bin" + PORT_PREFIX="$TMP/macports-prefix" + mkdir -p "$PORT_PREFIX/bin" + + for i in {1..9}; do stub uname '-s : echo Darwin'; done + for i in {1..2}; do stub sw_vers '-productVersion : echo 1010'; done + stub brew "--prefix : echo '$BREW_PREFIX'" + for i in {1..5}; do stub brew false; done + stub_make_install + export PATH="$BREW_PREFIX/bin:$PORT_PREFIX/bin:$PATH" + + run_inline_definition < "${TMP}/definitions/2.7.8-test" mkdir -p "${TMP}/other" echo false > "${TMP}/other/2.7.8-test" - run bin/python-build "2.7.8-test" "${TMP}/install" + run python-build "2.7.8-test" "${TMP}/install" assert_success "" }