curl/.github/workflows/macos.yml
Viktor Szakats 60c3d04465
autotools: add support for 'unity' builds, enable in CI
Implement the "unity" builds as known from CMake, but for autotools.
It's limited to `lib` and `src` (CMake also supports it in `tests`).

Enable with: `--enable-unity` (disabled by default)

Unity builds speed up builds significantly. Cygwin and Windows builds in
particular, but the effect is noticeable on most systems. It also allows
discovering unity issues with autotools, benefitting also CMake when
building the same combination. In CI it makes turnaround times quicker.

This closes build performance with CMake. autotools still lags behind
because it builds shared and static libcurl in two, separate passes.
CMake does it in one. Manpage compilation isn't batched, it is in CMake.
After unity and test bundle support the slowest parts of the build are
the configuration phase (which is effectively a tedious, non-parallel,
compilation and/or linking of 300+ tiny programs. The next bottleneck
is compiling individual examples and finally test servers (only slow
with autotools).

The autotools implementation is slightly less efficient than CMake,
because 3 sources are permanently excluded while in CMake this isn't
necessary and solved more efficiently while building libtests. There is
also no 'unity' support for tests, making them a less efficient also.

Enable it in CI for most `configure` jobs. Except in GHA/dist (though
it works fine there too), to use the default config there. Also skip for
the Linux AWC-LC job where it made builds time a few seconds longer
(reason undiscovered.)

Autotools test suite builds compared between master -> `--enable-unity`:
- GHA/Linux: 32s -> 12s
  https://github.com/curl/curl/actions/runs/10705668823/job/29681617374
  https://github.com/curl/curl/actions/runs/10742978889/job/29796766297
- GHA/macOS: 37s -> 10s
  https://github.com/curl/curl/actions/runs/10705668813/job/29681632885
  https://github.com/curl/curl/actions/runs/10742978699/job/29796768875
- GHA/FreeBSD: 15m25 -> 10m58 (full workflow time, ~qemu)
  https://github.com/curl/curl/actions/runs/10705668811/job/29681607915
  https://github.com/curl/curl/actions/runs/10742978937/job/29796766115
- GHA/Cygwin: 3m32 -> 1m21
  https://github.com/curl/curl/actions/runs/10705668809/job/29681609965
  https://github.com/curl/curl/actions/runs/10742978645/job/29796756933
- GHA/MSYS2: 2m42 -> 50s
  https://github.com/curl/curl/actions/runs/10705668808/job/29681621166
  https://github.com/curl/curl/actions/runs/10742978662/job/29799739289
- GHA/mingw-w64: 5m32 -> 1m23
  https://github.com/curl/curl/actions/runs/10705668808/job/29681628787
  https://github.com/curl/curl/actions/runs/10742978662/job/29799741568

Closes #14815
2024-09-20 23:53:33 +02:00

642 lines
31 KiB
YAML

# Copyright (C) Daniel Stenberg, <daniel@haxx.se>, et al.
#
# SPDX-License-Identifier: curl
name: macOS
'on':
push:
branches:
- master
- '*/ci'
paths-ignore:
- '**/*.md'
- '.circleci/**'
- 'appveyor.*'
- 'packages/**'
- 'plan9/**'
- 'projects/**'
- 'winbuild/**'
pull_request:
branches:
- master
paths-ignore:
- '**/*.md'
- '.circleci/**'
- 'appveyor.*'
- 'packages/**'
- 'plan9/**'
- 'projects/**'
- 'winbuild/**'
concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.sha }}
cancel-in-progress: true
permissions: {}
# Deprecated Apple APIs and the macos-version-min value required to avoid
# deprecation warnings with llvm/clang:
#
# - 10.7 Lion (2011) - GSS
# - 10.8 Mountain Lion (2012) - CFURLCreateDataAndPropertiesFromResource (used by curl SecureTransport code)
# - 10.9 Maverick (2013) - LDAP
# - 10.14 Mojave (2018) - SecureTransport
#
# For SecureTransport, curl implements features that require a target
# newer than the 10.8 required by `CFURLCreateDataAndPropertiesFromResource`.
# In this case `-Wno-deprecated-declarations` still comes handy to pacify
# deprecation warnings, though the real solution would be to avoid calling
# that function.
env:
LDFLAGS: -w # suppress 'object file was built for newer macOS version than being linked' warnings
MAKEFLAGS: -j 4
jobs:
autotools:
name: 'AM ${{ matrix.compiler }} ${{ matrix.name }}'
runs-on: 'macos-latest'
timeout-minutes: 60
env:
DEVELOPER_DIR: "/Applications/Xcode${{ matrix.xcode && format('_{0}', matrix.xcode) || '' }}.app/Contents/Developer"
CC: ${{ matrix.compiler }}
CFLAGS: '-mmacosx-version-min=${{ matrix.macos-version-min }}'
strategy:
fail-fast: false
matrix:
include:
- name: '!ssl !debug brotli zstd'
compiler: clang
install: brotli zstd
configure: --without-ssl --enable-websockets --with-brotli --with-zstd
macos-version-min: '10.9'
- name: '!ssl !debug'
compiler: gcc-12
configure: --without-ssl --enable-websockets
macos-version-min: '10.9'
- name: '!ssl'
compiler: clang
configure: --enable-debug --without-ssl --enable-websockets
macos-version-min: '10.9'
- name: '!ssl libssh2 AppleIDN'
compiler: clang
configure: --enable-debug --with-libssh2=$(brew --prefix libssh2) --without-ssl --with-apple-idn --enable-websockets
macos-version-min: '10.9'
- name: 'OpenSSL libssh c-ares'
compiler: clang
install: libssh
configure: --enable-debug --with-libssh --with-openssl=$(brew --prefix openssl) --enable-ares --enable-websockets
macos-version-min: '10.9'
- name: 'OpenSSL libssh'
compiler: llvm@15
install: libssh
configure: --enable-debug --with-libssh --with-openssl=$(brew --prefix openssl) --enable-websockets
macos-version-min: '10.9'
- name: '!ssl c-ares'
compiler: clang
configure: --enable-debug --enable-ares --without-ssl --enable-websockets
macos-version-min: '10.9'
- name: '!ssl HTTP-only'
compiler: clang
configure: |
--enable-debug \
--disable-alt-svc --disable-dict --disable-file --disable-ftp --disable-gopher --disable-imap \
--disable-ldap --disable-pop3 --disable-rtmp --disable-rtsp --disable-scp --disable-sftp \
--disable-shared --disable-smb --disable-smtp --disable-telnet --disable-tftp --disable-unix-sockets \
--without-brotli --without-gssapi --without-libidn2 --without-libpsl --without-librtmp --without-libssh2 \
--without-nghttp2 --without-ntlm-auth --without-ssl --without-zlib --without-zstd
macos-version-min: '10.15' # Catalina (2019)
- name: 'SecureTransport libssh2'
compiler: clang
configure: --enable-debug --with-secure-transport --enable-websockets --with-libssh2=$(brew --prefix libssh2)
macos-version-min: '10.8'
- name: 'SecureTransport libssh2 10.12'
compiler: clang
configure: --enable-debug --with-secure-transport --enable-websockets --with-libssh2=$(brew --prefix libssh2)
macos-version-min: '10.12' # for monotonic timers
cflags: '-Wno-deprecated-declarations'
- name: 'SecureTransport libssh2'
compiler: gcc-12
configure: --enable-debug --with-secure-transport --enable-websockets --with-libssh2=$(brew --prefix libssh2)
macos-version-min: '10.8'
- name: 'LibreSSL +examples'
compiler: clang
install: libressl
configure: --enable-debug --with-openssl=$(brew --prefix libressl) --enable-websockets
macos-version-min: '10.9'
- name: 'OpenSSL'
compiler: clang
configure: --enable-debug --with-openssl=$(brew --prefix openssl) --enable-websockets
macos-version-min: '10.9'
- name: 'OpenSSL event-based'
compiler: clang
configure: --enable-debug --with-openssl=$(brew --prefix openssl) --enable-websockets
macos-version-min: '10.9'
tflags: -e
- name: 'OpenSSL torture !FTP'
compiler: clang
configure: --enable-debug --disable-shared --disable-threaded-resolver --with-openssl=$(brew --prefix openssl) --enable-websockets
tflags: -n -t --shallow=25 !FTP
macos-version-min: '10.9'
- name: 'OpenSSL torture FTP'
compiler: clang
configure: --enable-debug --disable-shared --disable-threaded-resolver --with-openssl=$(brew --prefix openssl) --enable-websockets
tflags: -n -t --shallow=20 FTP
macos-version-min: '10.9'
- name: 'OpenSSL libssh2 !ldap 10.15'
compiler: clang
configure: --enable-debug --disable-ldap --with-openssl=$(brew --prefix openssl) --enable-websockets
macos-version-min: '10.15'
steps:
- name: 'brew install'
# Run this command with retries because of spurious failures seen
# while running the tests, for example
# https://github.com/curl/curl/runs/4095721123?check_suite_focus=true
run: |
echo automake libtool pkg-config libpsl libssh2 nghttp2 stunnel ${{ matrix.install }} | xargs -Ix -n1 echo brew '"x"' > /tmp/Brewfile
while [[ $? == 0 ]]; do for i in 1 2 3; do brew update && brew bundle install --no-lock --file /tmp/Brewfile && break 2 || { echo Error: wait to try again; sleep 10; } done; false Too many retries; done
- name: 'brew unlink openssl'
run: |
if test -d $(brew --prefix)/include/openssl; then
brew unlink openssl
fi
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
- name: 'toolchain versions'
run: |
[[ '${{ matrix.compiler }}' = 'llvm'* ]] && CC="$(brew --prefix ${{ matrix.compiler }})/bin/clang"
[[ '${{ matrix.compiler }}' = 'gcc'* ]] && \
grep -h -r -E -o '.+[0-9.]+\.sdk/' "$(dirname "$("${CC}" -print-libgcc-file-name)")/include-fixed" | sed -E 's/^\t+//g' | tr -d '"' | sort -u || true
which "${CC}"; "${CC}" --version || true
xcodebuild -version || true
xcrun --sdk macosx --show-sdk-path 2>/dev/null || true
xcrun --sdk macosx --show-sdk-version || true
echo '::group::macros predefined'; "${CC}" -dM -E - < /dev/null | sort || true; echo '::endgroup::'
echo '::group::brew packages installed'; ls -l "$(brew --prefix)/opt"; echo '::endgroup::'
- name: 'autoreconf'
run: autoreconf -fi
- name: 'configure'
run: |
[[ '${{ matrix.compiler }}' = 'llvm'* ]] && CC="$(brew --prefix ${{ matrix.compiler }})/bin/clang"
CFLAGS+=' ${{ matrix.cflags }}'
if [[ '${{ matrix.compiler }}' = 'gcc'* ]]; then
libgccdir="$(dirname "$("${CC}" -print-libgcc-file-name)")"
echo '::group::gcc include-fixed details'; find "${libgccdir}/include-fixed" | sort; echo '::endgroup::'
for f in dispatch os AvailabilityInternal.h stdio.h; do
if [ -r "${libgccdir}/include-fixed/${f}" ]; then
echo "Zap gcc hack: '${libgccdir}/include-fixed/${f}'"
mv "${libgccdir}/include-fixed/${f}" "${libgccdir}/include-fixed/${f}-BAK"
fi
done
fi
if [[ '${{ matrix.compiler }}' = 'llvm'* ]]; then
options+=" --target=$(uname -m)-apple-darwin"
CC+=" --target=$(uname -m)-apple-darwin"
fi
if [ '${{ matrix.compiler }}' != 'clang' ]; then
options+=" --with-sysroot=$(xcrun --sdk macosx --show-sdk-path 2>/dev/null)"
CFLAGS+=" --sysroot=$(xcrun --sdk macosx --show-sdk-path 2>/dev/null)"
fi
mkdir bld && cd bld && ../configure --enable-unity --enable-warnings --enable-werror \
--disable-dependency-tracking \
--with-libpsl=$(brew --prefix libpsl) \
${{ matrix.configure }} ${options}
- name: 'configure log'
if: ${{ !cancelled() }}
run: cat bld/config.log || true
- name: 'curl_config.h'
run: |
echo '::group::raw'; cat bld/lib/curl_config.h || true; echo '::endgroup::'
cat bld/lib/curl_config.h | grep -F '#define' | sort || true
- name: 'build-cert'
if: contains(matrix.configure, '--with-secure-transport')
run: |
make -C bld/tests/certs clean-certs
make -C bld/tests/certs build-certs -j1
- name: 'make'
run: make -C bld V=1
- name: 'curl version'
run: bld/src/curl --disable --version
- name: 'make tests'
run: make -C bld V=1 -C tests
- name: 'pip3 install'
run: |
python3 -m venv $HOME/venv
source $HOME/venv/bin/activate
python3 -m pip install impacket
- name: 'run tests'
timeout-minutes: 20
run: |
export TFLAGS='${{ matrix.tflags }} -j10'
TFLAGS+=' ~2037 ~2041' # flaky
if [[ '${{ matrix.compiler }}' = 'gcc'* ]]; then
TFLAGS+=' ~RTSP' # 567 568 569 570 571 572 577 689 3100
TFLAGS+=' ~1156 ~1539' # HTTP Content-Range, Content-Length
if [[ '${{ matrix.configure }}' = *'--with-secure-transport'* ]]; then
TFLAGS+=' ~2100' # 2100:'HTTP GET using DoH' https://github.com/curl/curl/actions/runs/9942146678/job/27462937524#step:15:5059
TFLAGS+=' ~HTTP/2' # 2400 2401 2402 2403 2404 2406, SecureTransport + nghttp2
else
TFLAGS+=' ~2402 ~2404' # non-SecureTransport + nghttp2
fi
fi
if [[ '${{ matrix.configure }}' = *'--with-secure-transport'* ]]; then
TFLAGS+=' ~313' # SecureTransport does not support crl file
TFLAGS+=' ~1631 ~1632' # SecureTransport is not able to shutdown ftp over https gracefully yet
fi
PATH="$HOME/venv/bin:$PATH"
rm -f $HOME/.curlrc
make -C bld V=1 test-ci
- name: 'make examples'
if: ${{ contains(matrix.build.name, '+examples') }}
run: make -C bld V=1 examples
cmake:
name: 'CM ${{ matrix.compiler }} ${{ matrix.build.name }}'
runs-on: 'macos-latest'
timeout-minutes: 10
env:
DEVELOPER_DIR: "/Applications/Xcode${{ matrix.xcode && format('_{0}', matrix.xcode) || '' }}.app/Contents/Developer"
CC: ${{ matrix.compiler }}
strategy:
fail-fast: false
matrix:
compiler: [clang, llvm@15, gcc-12]
build:
- name: 'OpenSSL ws gsasl AppleIDN'
install: gsasl
generate: -DOPENSSL_ROOT_DIR=$(brew --prefix openssl) -DCURL_USE_GSASL=ON -DUSE_APPLE_IDN=ON -DENABLE_WEBSOCKETS=ON
macos-version-min: '10.9'
- name: 'OpenSSL +static libssh'
install: libssh
generate: -DOPENSSL_ROOT_DIR=$(brew --prefix openssl) -DBUILD_STATIC_LIBS=ON -DCURL_USE_LIBSSH2=OFF -DCURL_USE_LIBSSH=ON
macos-version-min: '10.9'
- name: 'SecureTransport ws debug+'
generate: -DCURL_USE_SECTRANSP=ON -DENABLE_WEBSOCKETS=ON -DENABLE_DEBUG=ON -DENABLE_CURLDEBUG=ON
macos-version-min: '10.8'
- name: 'LibreSSL !ldap heimdal c-ares +examples'
install: libressl heimdal
generate: -DOPENSSL_ROOT_DIR=$(brew --prefix libressl) -DENABLE_ARES=ON -DCURL_USE_GSSAPI=ON -DGSS_ROOT_DIR=$(brew --prefix heimdal) -DCURL_DISABLE_LDAP=ON
macos-version-min: '10.15'
- name: 'wolfSSL !ldap brotli zstd'
install: brotli wolfssl zstd
generate: -DCURL_USE_WOLFSSL=ON -DCURL_BROTLI=ON -DCURL_ZSTD=ON -DCURL_DISABLE_LDAP=ON
macos-version-min: '10.15'
- name: 'GnuTLS !ldap krb5'
install: gnutls nettle krb5
generate: -DCURL_USE_GNUTLS=ON -DCURL_USE_OPENSSL=OFF -DCURL_USE_GSSAPI=ON -DGSS_ROOT_DIR=$(brew --prefix krb5) -DCURL_DISABLE_LDAP=ON
macos-version-min: '10.15'
exclude:
- { compiler: llvm@15, build: { macos-version-min: '10.15' } }
- { compiler: llvm@15, build: { macos-version-min: '10.9' } }
steps:
- name: 'brew install'
run: |
echo ninja pkg-config libpsl libssh2 nghttp2 stunnel ${{ matrix.build.install }} | xargs -Ix -n1 echo brew '"x"' > /tmp/Brewfile
while [[ $? == 0 ]]; do for i in 1 2 3; do brew update && brew bundle install --no-lock --file /tmp/Brewfile && break 2 || { echo Error: wait to try again; sleep 10; } done; false Too many retries; done
- name: 'brew unlink openssl'
run: |
if test -d $(brew --prefix)/include/openssl; then
brew unlink openssl
fi
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
- name: 'toolchain versions'
run: |
[[ '${{ matrix.compiler }}' = 'llvm'* ]] && CC="$(brew --prefix ${{ matrix.compiler }})/bin/clang"
[[ '${{ matrix.compiler }}' = 'gcc'* ]] && \
grep -h -r -E -o '.+[0-9.]+\.sdk/' "$(dirname "$("${CC}" -print-libgcc-file-name)")/include-fixed" | sed -E 's/^\t+//g' | tr -d '"' | sort -u || true
which "${CC}"; "${CC}" --version || true
xcodebuild -version || true
xcrun --sdk macosx --show-sdk-path 2>/dev/null || true
xcrun --sdk macosx --show-sdk-version || true
echo '::group::macros predefined'; "${CC}" -dM -E - < /dev/null | sort || true; echo '::endgroup::'
echo '::group::brew packages installed'; ls -l "$(brew --prefix)/opt"; echo '::endgroup::'
- name: 'cmake configure'
run: |
[[ '${{ matrix.compiler }}' = 'llvm'* ]] && CC="$(brew --prefix ${{ matrix.compiler }})/bin/clang"
if [[ '${{ matrix.compiler }}' = 'gcc'* ]]; then
libgccdir="$(dirname "$("${CC}" -print-libgcc-file-name)")"
echo '::group::gcc include-fixed details'; find "${libgccdir}/include-fixed" | sort; echo '::endgroup::'
for f in dispatch os AvailabilityInternal.h stdio.h; do
if [ -r "${libgccdir}/include-fixed/${f}" ]; then
echo "Zap gcc hack: '${libgccdir}/include-fixed/${f}'"
mv "${libgccdir}/include-fixed/${f}" "${libgccdir}/include-fixed/${f}-BAK"
fi
done
fi
cmake -B bld -G Ninja -DCMAKE_UNITY_BUILD=ON -DCURL_WERROR=ON \
-DCMAKE_OSX_DEPLOYMENT_TARGET=${{ matrix.build.macos-version-min }} \
"-DCMAKE_C_COMPILER_TARGET=$(uname -m | sed 's/arm64/aarch64/')-apple-darwin$(uname -r)" \
${{ matrix.build.generate }}
- name: 'configure log'
if: ${{ !cancelled() }}
run: cat bld/CMakeFiles/CMakeConfigureLog.yaml 2>/dev/null || true
- name: 'curl_config.h'
run: |
echo '::group::raw'; cat bld/lib/curl_config.h || true; echo '::endgroup::'
cat bld/lib/curl_config.h | grep -F '#define' | sort || true
- name: 'build-cert'
if: contains(matrix.build.generate, '-DCURL_USE_SECTRANSP=ON')
run: |
ninja -C bld clean-certs
ninja -C bld build-certs -j 1
- name: 'cmake build'
run: ninja -C bld --verbose
- name: 'curl version'
run: bld/src/curl --disable --version
- name: 'cmake build tests'
run: ninja -C bld testdeps
- name: 'pip3 install'
run: |
python3 -m venv $HOME/venv
source $HOME/venv/bin/activate
python3 -m pip install impacket
- name: 'cmake run tests'
timeout-minutes: 10
run: |
export TFLAGS='${{ matrix.build.tflags }} -j10'
TFLAGS+=' ~2037 ~2041' # flaky
if [[ '${{ matrix.compiler }}' = 'gcc'* ]]; then
TFLAGS+=' ~RTSP' # 567 568 569 570 571 572 577 689 3100
TFLAGS+=' ~1156 ~1539' # HTTP Content-Range, Content-Length
if [[ '${{ matrix.build.generate }}' = *'-DCURL_USE_SECTRANSP=ON'* ]]; then
TFLAGS+=' ~2100' # 2100:'HTTP GET using DoH' https://github.com/curl/curl/actions/runs/9942146678/job/27462937524#step:15:5059
TFLAGS+=' ~HTTP/2' # 2400 2401 2402 2403 2404 2406, SecureTransport + nghttp2
else
TFLAGS+=' ~2402 ~2404' # non-SecureTransport + nghttp2
fi
fi
if [[ '${{ matrix.build.generate }}' = *'-DCURL_USE_SECTRANSP=ON'* ]]; then
TFLAGS+=' ~313' # SecureTransport does not support crl file
TFLAGS+=' ~1631 ~1632' # SecureTransport is not able to shutdown ftp over https gracefully yet
fi
PATH="$HOME/venv/bin:$PATH"
rm -f $HOME/.curlrc
ninja -C bld test-ci
- name: 'cmake build examples'
if: ${{ contains(matrix.name, '+examples') }}
run: make -C bld VERBOSE=1
combinations: # Test buildability with host OS, Xcode / SDK, compiler, target-OS, SecureTransport/not, built tool, combinations
if: true # Set to `true` to enable this test matrix. It runs quickly.
name: "${{ matrix.build == 'cmake' && 'CM' || 'AM' }} ${{ matrix.compiler }} ${{ matrix.image }} ${{ matrix.xcode }} ${{ matrix.config }}"
runs-on: ${{ matrix.image }}
timeout-minutes: 30
env:
DEVELOPER_DIR: "/Applications/Xcode${{ matrix.xcode && format('_{0}', matrix.xcode) || '' }}.app/Contents/Developer"
CC: ${{ matrix.compiler }}
strategy:
fail-fast: false
matrix:
config: [SecureTransport] # also: OpenSSL
compiler: [gcc-12, gcc-13, gcc-14, llvm@15, clang]
# Xcode support matrix as of 2024-07, with default macOS SDK versions and OS names, years:
# * = default Xcode on the runner.
# macos-12: 13.1, 13.2.1, 13.3.1, 13.4.1, 14.0.1, 14.1,*14.2
# macos-13: 14.1, 14.2, 14.3.1,*15.0.1, 15.1, 15.2
# macos-14: 14.3.1, 15.0.1, 15.1, 15.2, 15.3,*15.4, 16.0
# macOSSDK: 12.0, 12.1, 12.3, 12.3, 12.3, 13.0, 13.1, 13.3, 14.0, 14.2, 14.2, 14.4, 14.5, 15.0
# Monterey (2021) Ventura (2022) Sonoma (2023) Sequoia (2024)
# https://github.com/actions/runner-images/tree/main/images/macos
# https://en.wikipedia.org/wiki/MacOS_version_history
image: [macos-12, macos-13, macos-14]
# Can skip these to reduce jobs:
# 13.1, 13.2.1 are fairly old.
# 13.3.1, 14.0.1 have the same default macOS SDK as 13.4.1 and identical test results.
# 15.1 has the same default macOS SDK as 15.2 and identical test result.
# 14.1, 15.4 not revealing new fallouts.
#xcode: ['13.1', '13.2.1', '13.3.1', '13.4.1', '14.0.1', '14.1', '14.2', '14.3.1', '15.0.1', '15.1', '15.2', '15.3', '15.4', '16.0'] # all Xcode
#xcode: ['13.1', '13.2.1', '13.4.1', '14.1', '14.2', '14.3.1', '15.0.1', '15.2', '15.3', '15.4', '16.0'] # all SDK
#xcode: ['13.4.1', '14.2', '14.3.1', '15.0.1', '15.2', '15.3', '16.0'] # coverage
xcode: [''] # default Xcodes
macos-version-min: ['10.8']
build: [autotools, cmake]
exclude:
# Combinations uncovered by runner images:
- { image: macos-12, xcode: '14.3.1' }
- { image: macos-12, xcode: '15.0.1' }
- { image: macos-12, xcode: '15.1' }
- { image: macos-12, xcode: '15.2' }
- { image: macos-12, xcode: '15.3' }
- { image: macos-12, xcode: '15.4' }
- { image: macos-12, xcode: '16.0' }
- { image: macos-13, xcode: '13.1' }
- { image: macos-13, xcode: '13.2.1' }
- { image: macos-13, xcode: '13.3.1' }
- { image: macos-13, xcode: '13.4.1' }
- { image: macos-13, xcode: '14.0.1' }
- { image: macos-13, xcode: '15.3' }
- { image: macos-13, xcode: '15.4' }
- { image: macos-13, xcode: '16.0' }
- { image: macos-14, xcode: '13.1' }
- { image: macos-14, xcode: '13.2.1' }
- { image: macos-14, xcode: '13.3.1' }
- { image: macos-14, xcode: '13.4.1' }
- { image: macos-14, xcode: '14.0.1' }
- { image: macos-14, xcode: '14.1' }
- { image: macos-14, xcode: '14.2' }
# Reduce build combinations, by dropping less interesting ones
- { compiler: gcc-12, config: SecureTransport }
- { compiler: gcc-13, build: cmake }
- { compiler: gcc-13, image: macos-13 }
- { compiler: gcc-14, config: SecureTransport }
steps:
- name: 'install autotools'
if: ${{ matrix.build == 'autotools' }}
run: |
echo automake libtool | xargs -Ix -n1 echo brew '"x"' > /tmp/Brewfile
while [[ $? == 0 ]]; do for i in 1 2 3; do brew update && brew bundle install --no-lock --file /tmp/Brewfile && break 2 || { echo Error: wait to try again; sleep 10; } done; false Too many retries; done
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
- name: 'toolchain versions'
run: |
[[ '${{ matrix.compiler }}' = 'llvm'* ]] && CC="$(brew --prefix ${{ matrix.compiler }})/bin/clang"
[[ '${{ matrix.compiler }}' = 'gcc'* ]] && \
grep -h -r -E -o '.+[0-9.]+\.sdk/' "$(dirname "$("${CC}" -print-libgcc-file-name)")/include-fixed" | sed -E 's/^\t+//g' | tr -d '"' | sort -u || true
which "${CC}"; "${CC}" --version || true
xcodebuild -version || true
xcrun --sdk macosx --show-sdk-path 2>/dev/null || true
xcrun --sdk macosx --show-sdk-version || true
echo '::group::macros predefined'; "${CC}" -dM -E - < /dev/null | sort || true; echo '::endgroup::'
echo '::group::brew packages preinstalled'; ls -l "$(brew --prefix)/opt"; echo '::endgroup::'
- name: 'autoreconf'
if: ${{ matrix.build == 'autotools' }}
run: autoreconf -fi
- name: 'configure / ${{ matrix.build }}'
run: |
[[ '${{ matrix.compiler }}' = 'llvm'* ]] && CC="$(brew --prefix ${{ matrix.compiler }})/bin/clang"
# gcc ships with an `include-fixed` header set, which overrides SDK
# headers with the intent of making them compatible with gcc. The
# source for these headers is:
# https://github.com/gcc-mirror/gcc/tree/master/fixincludes
# with extra Apple-specific patches applied from here for Homebrew:
# https://github.com/iains/gcc-12-branch
#
# They pass through a generator phase at build-time which seems to
# pick the SDK installed on the build machine (maintained by the
# Homebrew project in our case) and patches it according to a set
# of rules in `inclhack.def`.
#
# Homebrew builds and ships different binaries for different macOS
# versions and CPUs, built on machines using the same OS version as
# the target one. Each of these machines have a particular version
# of Apple CommandLineTools with a default SDK version installed with
# them.
#
# Then this binary gets installed onto the end-user machine,
# matching the OS version at the time of installation.
#
# The problem with this approach is that the SDK version picked up
# at gcc build-time has a high chance of being or becoming out of
# sync with actual SDK installed on the end-user machine. This
# can happen after upgrading the OS, Xcode, selecting an SDK version
# manually, or other reasons.
#
# When the SDK versions do not match, the gcc hacks, instead of
# improving compatibility the SDK, are actively _breaking_
# compatibility, in an unexpected, hard to diagnose way.
#
# The SDK version used for gcc-hacks is not advertised. We can
# extract the major SDK version from the generated gcc-hack header
# files, assuming someone knows what to look for and where.
#
# Basically it also means that the same `gcc-N` Homebrew package
# behaves differently depending on the OS it was built on. Causing
# an explosion of build combination. It may also mean that a minor
# gcc version bump is built against a different SDK version, and due
# to the extra patch for the hack applied by Homebrew, there may
# be extra changes as well.
#
# For GHA runners, it means that the default Xcode + OS combo is
# broken in 8 out of 12 combinations (66%) have an SDK mismatch,
# and 9 fail to build (75%). These are the 3 lucky default
# combinations that worked to build curl:
# macos-14 + Xcode 15.0.1 + gcc-12, gcc-14
#
# Of all possible valid GHA runner, gcc, manually selected Xcode
# combinations, 40% are broken.
#
# Compared to mainline llvm: llvm ships the same binaries regardless
# of build-OS or environent, it contains no SDK-version-specific
# hacks, and has no 3rd party patches. This still leaves some
# occasional issues, but works much closer to expectations.
#
# Some of these hacks are helpful, in particular for fixing this
# issue via math.h:
# /Applications/Xcode_14.3.1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/include/math.h:53:5: error: #error "Unsupported value of
# 53 | # error "Unsupported value of __FLT_EVAL_METHOD__."
#
# Errors seen in available CI combinations:
# error: two or more data types in declaration specifiers # fatal error: AvailabilityInternalLegacy.h: No such file or directory
# gcc-13 + macos-14 + Xcode 14.3.1
# error: two or more data types in declaration specifiers
# gcc-13 + macos-12 + Xcode 14.1, 14.2
# gcc-13 + Xcode 15.0.1, 15.1, 5.2
# error: expected ';' before 'extern'
# gcc-12, gcc-14 + macos-12 + Xcode 14.1, 14.2
# error: unknown type name 'dispatch_queue_t'
# gcc-12 + macos-13 + Xcode 15.0.1, 15.1, 15.2
# error: type defaults to 'int' in declaration of 'DISPATCH_DECL_FACTORY_CLASS_SWIFT' [-Wimplicit-int]
# gcc-14 macos-13 Xcode 15.0.1, 15.1, 15.2
# error: unknown type name 'FILE'
# Xcode 16.0
#
# Unbreak Homebrew gcc builds by moving problematic SDK header overlay
# directories/files out of the way:
if [[ '${{ matrix.compiler }}' = 'gcc'* ]]; then
# E.g.:
# $(brew --prefix)/Cellar/gcc@11/11.4.0/lib/gcc/11/gcc/aarch64-apple-darwin23/11/include-fixed
# $(brew --prefix)/Cellar/gcc@11/11.4.0/lib/gcc/11/gcc/x86_64-apple-darwin21/11/include-fixed
# $(brew --prefix)/Cellar/gcc/14.1.0_1/lib/gcc/14/gcc/x86_64-apple-darwin21/14/include-fixed
libgccdir="$(dirname "$("${CC}" -print-libgcc-file-name)")"
echo '::group::gcc include-fixed details'; find "${libgccdir}/include-fixed" | sort; echo '::endgroup::'
patch_out='dispatch os AvailabilityInternal.h'
patch_out+=' stdio.h' # for Xcode 16 error: unknown type name 'FILE'
for f in ${patch_out}; do
if [ -r "${libgccdir}/include-fixed/${f}" ]; then
echo "Zap gcc hack: '${libgccdir}/include-fixed/${f}'"
mv "${libgccdir}/include-fixed/${f}" "${libgccdir}/include-fixed/${f}-BAK"
fi
done
fi
if [ '${{ matrix.build }}' = 'autotools' ]; then
export CFLAGS
if [[ '${{ matrix.compiler }}' = 'llvm'* ]]; then
options+=" --target=$(uname -m)-apple-darwin"
CC+=" --target=$(uname -m)-apple-darwin"
fi
if [ '${{ matrix.compiler }}' != 'clang' ]; then
options+=" --with-sysroot=$(xcrun --sdk macosx --show-sdk-path 2>/dev/null)"
CFLAGS+=" --sysroot=$(xcrun --sdk macosx --show-sdk-path 2>/dev/null)"
fi
[ '${{ matrix.config }}' = 'OpenSSL' ] && options+=" --with-openssl=$(brew --prefix openssl)"
[ '${{ matrix.config }}' = 'SecureTransport' ] && options+=' --with-secure-transport'
CFLAGS+=' -mmacosx-version-min=${{ matrix.macos-version-min }}'
# would pick up nghttp2, libidn2, but libssh2 is disabled by default
mkdir bld && cd bld && ../configure --enable-unity --enable-warnings --enable-werror \
--disable-dependency-tracking \
--disable-docs --disable-manual \
--without-nghttp2 --without-libidn2 \
--without-libpsl \
${options}
else
[ '${{ matrix.config }}' = 'OpenSSL' ] && options+=' -DCURL_USE_OPENSSL=ON'
[ '${{ matrix.config }}' = 'SecureTransport' ] && options+=' -DCURL_USE_SECTRANSP=ON'
# would pick up nghttp2, libidn2, and libssh2
cmake -B bld -DCMAKE_UNITY_BUILD=ON -DCURL_WERROR=ON \
-DCMAKE_OSX_DEPLOYMENT_TARGET=${{ matrix.macos-version-min }} \
"-DCMAKE_IGNORE_PREFIX_PATH=$(brew --prefix)" \
"-DCMAKE_C_COMPILER_TARGET=$(uname -m | sed 's/arm64/aarch64/')-apple-darwin$(uname -r)" \
-DBUILD_LIBCURL_DOCS=OFF -DBUILD_MISC_DOCS=OFF -DENABLE_CURL_MANUAL=OFF \
-DUSE_NGHTTP2=OFF -DUSE_LIBIDN2=OFF \
-DCURL_USE_LIBPSL=OFF -DCURL_USE_LIBSSH2=OFF \
${options}
fi
- name: 'configure log'
if: ${{ !cancelled() }}
run: cat bld/config.log bld/CMakeFiles/CMakeConfigureLog.yaml 2>/dev/null || true
- name: 'curl_config.h'
run: |
echo '::group::raw'; cat bld/lib/curl_config.h || true; echo '::endgroup::'
cat bld/lib/curl_config.h | grep -F '#define' | sort || true
- name: 'build / ${{ matrix.build }}'
run: make -C bld V=1 VERBOSE=1
- name: 'curl version'
run: bld/src/curl --disable --version