]> git.ipfire.org Git - thirdparty/psycopg.git/commitdiff
ci(macos): build libpq instead of using Homebrew libraries
authorDaniele Varrazzo <daniele.varrazzo@gmail.com>
Sun, 5 Jan 2025 23:48:36 +0000 (00:48 +0100)
committerDaniele Varrazzo <daniele.varrazzo@gmail.com>
Tue, 14 Jan 2025 18:30:49 +0000 (19:30 +0100)
This avoids problems with MACOSX_DEPLOYMENT_TARGET drifting in builders
(see #858).

Largely contributed by @bwoodsend in https://github.com/psycopg/psycopg2/pull/1755.

.github/workflows/packages-bin.yml
tools/build/build_libpq.sh
tools/build/wheel_macos_before_all.sh [new file with mode: 0755]

index 6102be1074c6732542b8bec51e939a9a56c2454b..6bf7f1ffb4648e72da30839cd715b50d4e7f7110 100644 (file)
@@ -5,20 +5,20 @@ on:
   schedule:
     - cron: '28 7 * * sun'
 
+env:
+  # Latest release: https://www.postgresql.org/ftp/source/
+  LIBPQ_VERSION: "17.0"
+  # Latest release: https://www.openssl.org/source/
+  # Note: 3.3.2 is broken:
+  # https://github.com/openssl/openssl/issues/25366
+  OPENSSL_VERSION: "3.3.1"
+
 jobs:
 
   linux:  # {{{
     runs-on: ubuntu-latest
     if: true
 
-    env:
-      # Latest release: https://www.postgresql.org/ftp/source/
-      LIBPQ_VERSION: "17.0"
-      # Latest release: https://www.openssl.org/source/
-      # Note: 3.3.2 is broken:
-      # https://github.com/openssl/openssl/issues/25366
-      OPENSSL_VERSION: "3.3.1"
-
     strategy:
       fail-fast: false
       matrix:
@@ -97,89 +97,29 @@ jobs:
 
   # }}}
 
-  macos-14:  # {{{
-    runs-on: macos-14
+  macos:  # {{{
+    runs-on: macos-latest
     if: true
 
     strategy:
       fail-fast: false
       matrix:
-        arch: [arm64]
-        pyver: [cp310, cp311, cp312, cp313]
-
-    env:
-      PG_VERSION: "17"
+        arch: [x86_64, arm64]
+        pyver: [cp38, cp39, cp310, cp311, cp312, cp313]
 
     steps:
-      - uses: actions/checkout@v4
-
-      - name: Create the binary package source tree
-        run: python3 ./tools/build/copy_to_binary.py
-
-      - name: Install PostgreSQL on the runner
-        # As of 2024-09-28 postgresql@17 reports an error but it's available
-        # So in a few days we might be able to drop it.
-        run: |
-          brew update
-          brew install gnu-sed postgresql@${PG_VERSION}
-
-      - name: Start PostgreSQL service
-        run: brew services start postgresql@${PG_VERSION}
-
-      - name: Build wheels
-        uses: pypa/cibuildwheel@v2.22.0
-        with:
-          package-dir: psycopg_binary
-        env:
-          CIBW_BUILD: ${{matrix.pyver}}-macosx_${{matrix.arch}}
-          CIBW_ARCHS_MACOS: ${{matrix.arch}}
-          CIBW_TEST_REQUIRES: ./psycopg[test] ./psycopg_pool
-          CIBW_TEST_COMMAND: >-
-            pytest {project}/tests -m 'not slow and not flakey' --color yes
-          CIBW_ENVIRONMENT: >-
-            MACOSX_DEPLOYMENT_TARGET=14.0
-            PSYCOPG_IMPL=binary
-            PSYCOPG_TEST_DSN='dbname=postgres'
-            PATH="/opt/homebrew/opt/postgresql@${PG_VERSION}/bin:$PATH"
-            PSYCOPG_TEST_WANT_LIBPQ_BUILD=">= ${PG_VERSION}"
-            PSYCOPG_TEST_WANT_LIBPQ_IMPORT=">= ${PG_VERSION}"
+      - name: Checkout repos
+        uses: actions/checkout@v4
 
-      - uses: actions/upload-artifact@v4
+      - name: Cache libpq build
+        uses: actions/cache@v4
         with:
-          name: macos-14-${{matrix.pyver}}-macosx_${{matrix.arch}}
-          path: ./wheelhouse/*.whl
-
-
-  # }}}
-
-  macos-13:  # {{{
-    runs-on: macos-13
-    if: true
-
-    strategy:
-      fail-fast: false
-      matrix:
-        # These archs require an Apple M1 runner: [arm64, universal2]
-        arch: [x86_64]
-        pyver: [cp38, cp39, cp310, cp311, cp312, cp313]
-
-    env:
-      PG_VERSION: "17"
-
-    steps:
-      - uses: actions/checkout@v4
+          path: /tmp/libpq.build
+          key: libpq-${{ env.LIBPQ_VERSION }}-macos-${{ matrix.arch }}
 
       - name: Create the binary package source tree
         run: python3 ./tools/build/copy_to_binary.py
 
-      - name: Install PostgreSQL on the runner
-        run: |
-          brew update
-          brew install gnu-sed postgresql@${PG_VERSION}
-
-      - name: Start PostgreSQL service
-        run: brew services start postgresql@${PG_VERSION}
-
       - name: Build wheels
         uses: pypa/cibuildwheel@v2.22.0
         with:
@@ -187,20 +127,24 @@ jobs:
         env:
           CIBW_BUILD: ${{matrix.pyver}}-macosx_${{matrix.arch}}
           CIBW_ARCHS_MACOS: ${{matrix.arch}}
+          MACOSX_ARCHITECTURE: ${{matrix.arch}}
+          CIBW_BEFORE_ALL_MACOS: ./tools/build/wheel_macos_before_all.sh
           CIBW_TEST_REQUIRES: ./psycopg[test] ./psycopg_pool
           CIBW_TEST_COMMAND: >-
             pytest {project}/tests -m 'not slow and not flakey' --color yes
           CIBW_ENVIRONMENT: >-
-            MACOSX_DEPLOYMENT_TARGET=13.0
+            PG_VERSION=17
             PSYCOPG_IMPL=binary
             PSYCOPG_TEST_DSN='dbname=postgres'
-            PATH="/usr/local/opt/postgresql@${PG_VERSION}/bin:$PATH"
-            PSYCOPG_TEST_WANT_LIBPQ_BUILD=">= ${PG_VERSION}"
-            PSYCOPG_TEST_WANT_LIBPQ_IMPORT=">= ${PG_VERSION}"
+            LIBPQ_BUILD_PREFIX=/tmp/libpq.build
+            PATH="$LIBPQ_BUILD_PREFIX/bin:$PATH"
+            PSYCOPG_TEST_WANT_LIBPQ_BUILD=">= ${{env.LIBPQ_VERSION}}"
+            PSYCOPG_TEST_WANT_LIBPQ_IMPORT=">= ${{env.LIBPQ_VERSION}}"
 
-      - uses: actions/upload-artifact@v4
+      - name: Upload artifacts
+        uses: actions/upload-artifact@v4
         with:
-          name: macos-13-${{matrix.pyver}}-macosx_${{matrix.arch}}
+          name: macos-${{matrix.pyver}}-${{matrix.arch}}
           path: ./wheelhouse/*.whl
 
 
@@ -276,12 +220,11 @@ jobs:
 
   # }}}
 
-  merge:
+  merge:  # {{{
     runs-on: ubuntu-latest
     needs:
       - linux
-      - macos-14
-      - macos-13
+      - macos
       - windows
     steps:
       - name: Merge Artifacts
@@ -289,3 +232,5 @@ jobs:
         with:
           name: psycopg-binary-artifact
           delete-merged: true
+
+  # }}}
index 5fe98e986da59fb819f6d71cc56d52e3b26dd4ce..c3711210b1523c2bdcf3fe8b9fa97fda43571d90 100755 (executable)
@@ -1,12 +1,15 @@
 #!/bin/bash
 
-# Build a modern version of libpq and depending libs from source on Centos 5
+# Build a modern version of libpq and depending libs from source on Centos 5, Alpine or macOS
 
 set -euo pipefail
 
 postgres_version="${LIBPQ_VERSION}"
 openssl_version="${OPENSSL_VERSION}"
 
+# Latest release: https://kerberos.org/dist/
+krb5_version="1.21.3"
+
 # Latest release: https://openldap.org/software/download/
 ldap_version="2.6.8"
 
@@ -15,13 +18,28 @@ sasl_version="2.1.28"
 
 export LIBPQ_BUILD_PREFIX=${LIBPQ_BUILD_PREFIX:-/tmp/libpq.build}
 
-if [[ -f "${LIBPQ_BUILD_PREFIX}/lib/libpq.so" ]]; then
+case "$(uname)" in
+    Darwin)
+        ID=macos
+        library_suffix=dylib
+        ;;
+
+    Linux)
+        source /etc/os-release
+        library_suffix=so
+        ;;
+
+    *)
+        echo "$0: unexpected Operating system: '$(uname)'" >&2
+        exit 1
+        ;;
+esac
+
+if [[ -f "${LIBPQ_BUILD_PREFIX}/lib/libpq.${library_suffix}" ]]; then
     echo "libpq already available: build skipped" >&2
     exit 0
 fi
 
-source /etc/os-release
-
 case "$ID" in
     centos)
         yum update -y
@@ -34,13 +52,46 @@ case "$ID" in
             openssl-dev tzdata zlib-dev
         ;;
 
+    macos)
+        brew install automake m4 libtool
+        # If available, libpq seemingly insists on linking against homebrew's
+        # openssl no matter what so remove it. Since homebrew's curl depends on
+        # it, force use of system curl.
+        brew uninstall --force --ignore-dependencies openssl gettext curl
+        if [ -z "${MACOSX_ARCHITECTURE:-}" ]; then
+            MACOSX_ARCHITECTURE="$(uname -m)"
+        fi
+        # Set the deployment target to be <= to that of the oldest supported Python version.
+        # e.g. https://www.python.org/downloads/release/python-380/
+        if [ "$MACOSX_ARCHITECTURE" == "x86_64" ]; then
+            export MACOSX_DEPLOYMENT_TARGET=10.9
+        else
+            export MACOSX_DEPLOYMENT_TARGET=11.0
+        fi
+        ;;
+
     *)
         echo "$0: unexpected Linux distribution: '$ID'" >&2
         exit 1
         ;;
 esac
 
-if [ "$ID" == "centos" ]; then
+
+if [ "$ID" == "macos" ]; then
+    make_configure_standard_flags=( \
+        --prefix=${LIBPQ_BUILD_PREFIX} \
+        "CPPFLAGS=-I${LIBPQ_BUILD_PREFIX}/include/ -arch $MACOSX_ARCHITECTURE" \
+        "LDFLAGS=-L${LIBPQ_BUILD_PREFIX}/lib -arch $MACOSX_ARCHITECTURE" \
+    )
+else
+    make_configure_standard_flags=( \
+        --prefix=${LIBPQ_BUILD_PREFIX} \
+        CPPFLAGS=-I${LIBPQ_BUILD_PREFIX}/include/ \
+        "LDFLAGS=-L${LIBPQ_BUILD_PREFIX}/lib -L${LIBPQ_BUILD_PREFIX}/lib64" \
+    )
+fi
+
+if [ "$ID" == "centos" ] || [ "$ID" == "macos" ]; then
   if [[ ! -f "${LIBPQ_BUILD_PREFIX}/openssl.cnf" ]]; then
 
     # Build openssl if needed
@@ -53,8 +104,14 @@ if [ "$ID" == "centos" ]; then
 
         pushd "${openssl_dir}"
 
-        ./config --prefix=${LIBPQ_BUILD_PREFIX} --openssldir=${LIBPQ_BUILD_PREFIX} \
-            zlib -fPIC shared
+        options=(--prefix=${LIBPQ_BUILD_PREFIX} --openssldir=${LIBPQ_BUILD_PREFIX} \
+            zlib -fPIC shared)
+        if [ -z "${MACOSX_ARCHITECTURE:-}" ]; then
+            ./config $options
+        else
+            ./configure "darwin64-$MACOSX_ARCHITECTURE-cc" $options
+        fi
+
         make depend
         make
     else
@@ -69,8 +126,29 @@ if [ "$ID" == "centos" ]; then
 fi
 
 
-if [ "$ID" == "centos" ]; then
-  if [[ ! -f "${LIBPQ_BUILD_PREFIX}/lib/libsasl2.so" ]]; then
+if [ "$ID" == "macos" ]; then
+
+    # Build kerberos if needed
+    krb5_dir="krb5-${krb5_version}/src"
+    if [ ! -d "${krb5_dir}" ]; then
+        curl -fsSL "https://kerberos.org/dist/krb5/${krb5_version%.*}/krb5-${krb5_version}.tar.gz" \
+            | tar xzf -
+
+        pushd "${krb5_dir}"
+        ./configure "${make_configure_standard_flags[@]}"
+        make
+    else
+        pushd "${krb5_dir}"
+    fi
+
+    make install
+    popd
+
+fi
+
+
+if [ "$ID" == "centos" ] || [ "$ID" == "macos" ]; then
+  if [[ ! -f "${LIBPQ_BUILD_PREFIX}/lib/libsasl2.${library_suffix}" ]]; then
 
     # Build libsasl2 if needed
     # The system package (cyrus-sasl-devel) causes an amazing error on i686:
@@ -86,8 +164,7 @@ if [ "$ID" == "centos" ]; then
         pushd "${sasl_dir}"
 
         autoreconf -i
-        ./configure --prefix=${LIBPQ_BUILD_PREFIX} \
-            CPPFLAGS=-I${LIBPQ_BUILD_PREFIX}/include/ LDFLAGS=-L${LIBPQ_BUILD_PREFIX}/lib
+        ./configure "${make_configure_standard_flags[@]}" --disable-macos-framework
         make
     else
         pushd "${sasl_dir}"
@@ -103,8 +180,8 @@ if [ "$ID" == "centos" ]; then
 fi
 
 
-if [ "$ID" == "centos" ]; then
-  if [[ ! -f "${LIBPQ_BUILD_PREFIX}/lib/libldap.so" ]]; then
+if [ "$ID" == "centos" ] || [ "$ID" == "macos" ]; then
+  if [[ ! -f "${LIBPQ_BUILD_PREFIX}/lib/libldap.${library_suffix}" ]]; then
 
     # Build openldap if needed
     ldap_tag="${ldap_version}"
@@ -116,8 +193,7 @@ if [ "$ID" == "centos" ]; then
 
         pushd "${ldap_dir}"
 
-        ./configure --prefix=${LIBPQ_BUILD_PREFIX} --enable-backends=no --enable-null \
-            CPPFLAGS=-I${LIBPQ_BUILD_PREFIX}/include/ LDFLAGS=-L${LIBPQ_BUILD_PREFIX}/lib
+        ./configure "${make_configure_standard_flags[@]}" --enable-backends=no --enable-null
 
         make depend
         make -C libraries/liblutil/
@@ -131,7 +207,7 @@ if [ "$ID" == "centos" ]; then
     make -C libraries/liblber/ install
     make -C libraries/libldap/ install
     make -C include/ install
-    chmod +x ${LIBPQ_BUILD_PREFIX}/lib/{libldap,liblber}*.so*
+    chmod +x ${LIBPQ_BUILD_PREFIX}/lib/{libldap,liblber}*.${library_suffix}*
     popd
 
   fi
@@ -148,19 +224,19 @@ if [ ! -d "${postgres_dir}" ]; then
 
     pushd "${postgres_dir}"
 
-    # Match the default unix socket dir default with what defined on Ubuntu and
-    # Red Hat, which seems the most common location
-    sed -i 's|#define DEFAULT_PGSOCKET_DIR .*'\
+    if [ "$ID" != "macos" ]; then
+        # Match the default unix socket dir default with what defined on Ubuntu and
+        # Red Hat, which seems the most common location
+        sed -i 's|#define DEFAULT_PGSOCKET_DIR .*'\
 '|#define DEFAULT_PGSOCKET_DIR "/var/run/postgresql"|' \
-        src/include/pg_config_manual.h
+            src/include/pg_config_manual.h
+    fi
 
     export LD_LIBRARY_PATH="${LIBPQ_BUILD_PREFIX}/lib:${LIBPQ_BUILD_PREFIX}/lib64"
 
-    ./configure --prefix=${LIBPQ_BUILD_PREFIX} --sysconfdir=/etc/postgresql-common \
-        --without-readline --without-icu \
+    ./configure "${make_configure_standard_flags[@]}" --sysconfdir=/etc/postgresql-common \
         --with-gssapi --with-openssl --with-pam --with-ldap \
-        CPPFLAGS=-I${LIBPQ_BUILD_PREFIX}/include/ \
-        LDFLAGS="-L${LIBPQ_BUILD_PREFIX}/lib -L${LIBPQ_BUILD_PREFIX}/lib64"
+        --without-readline --without-icu
     make -C src/interfaces/libpq
     make -C src/bin/pg_config
     make -C src/include
@@ -174,4 +250,4 @@ make -C src/bin/pg_config install
 make -C src/include install
 popd
 
-find ${LIBPQ_BUILD_PREFIX} -name \*.so.\* -type f -exec strip --strip-unneeded {} \;
+find ${LIBPQ_BUILD_PREFIX} -name \*.${library_suffix}.\* -type f -exec strip --strip-unneeded {} \;
diff --git a/tools/build/wheel_macos_before_all.sh b/tools/build/wheel_macos_before_all.sh
new file mode 100755 (executable)
index 0000000..e3fb2f4
--- /dev/null
@@ -0,0 +1,34 @@
+#!/bin/bash
+
+# Configure the environment needed to build wheel packages on Mac OS.
+# This script is designed to be used by cibuildwheel as CIBW_BEFORE_ALL_MACOS
+#
+# The PG_VERSION env var must be set to a Postgres major version (e.g. 16).
+
+set -euo pipefail
+
+dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+prjdir="$( cd "${dir}/../.." && pwd )"
+
+# Build dependency libraries
+"${prjdir}/tools/build/build_libpq.sh"
+
+# Show dependency tree
+otool -L /tmp/libpq.build/lib/*.dylib
+
+brew install gnu-sed postgresql@${PG_VERSION}
+brew link --overwrite postgresql@${PG_VERSION}
+
+# Start the database for testing
+brew services start postgresql@${PG_VERSION}
+
+# Wait for postgres to come up
+for i in $(seq 10 -1 0); do
+  eval pg_isready && break
+  if [ $i == 0 ]; then
+      echo "PostgreSQL service not ready, giving up"
+      exit 1
+  fi
+  echo "PostgreSQL service not ready, waiting a bit, attempts left: $i"
+  sleep 5
+done