Repository navigation
MacBinaries #116
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # Builds the macOS viewer library and its self-contained runtime bundle. There is no Mac on this | |
| # desk, so the runner is the build machine -- there is no hand-built fallback for this platform. | |
| # Windows is still built by hand (deps/build.bat). Linux has both: LinuxBinaries.yml is the CI | |
| # route, and deps/build.sh under WSL stays as the backup, producing the same two archives. | |
| # | |
| # TWO ARCHITECTURES, TWO JOBS. Homebrew bottles are per-arch and Qt/VTK are not universal binaries, | |
| # so arm64 and x86_64 are separate builds producing separate assets. GitHub retired macos-13 in | |
| # December 2025; macos-15-intel is the standard Intel runner label that replaces it. | |
| # | |
| # BUILD ON THE OLDEST OS YOU SUPPORT. Homebrew bottles are poured per macOS release, so a bundle | |
| # staged on a newer macOS may not load on an older one. The runner labels below are therefore an | |
| # explicit deployment choice, not incidental -- do not change them to macos-latest without meaning | |
| # to move that target as GitHub updates the alias. | |
| # | |
| # THE TWO ARCHES DO NOT REACH THE SAME FLOOR, and the reason is GitHub's runner catalogue, not us: | |
| # arm64 -- macos-14 is the OLDEST standard image still offered, so the bundle's floor is 14.x. | |
| # x86_64 -- the only standard Intel labels are macos-15-intel and macos-26-intel. There is NO | |
| # free macOS 14 Intel runner (macos-14-large is a LARGER, billed runner), so this leg | |
| # stays on 15 and its bundle's real floor is 15.x, whatever deps/CMakeLists.txt | |
| # declares. Our own objects carry the declared 14.0 minimum; the Homebrew VTK/Qt/TBB | |
| # dylibs staged beside them carry the floor of the release their bottle was poured for, | |
| # and that is the binding one. | |
| # Lowering the Intel floor needs either a billed larger runner or Qt+VTK built from source. Do not | |
| # "fix" the asymmetry by pointing x86_64 at a label that is not in the standard free set. | |
| # | |
| # NOTHING IS PUBLISHED AUTOMATICALLY. A push builds and verifies, and leaves the archives as | |
| # workflow artifacts. Uploading to a release happens only on a manual run that explicitly asks for | |
| # it, because a release asset is user-facing: `rolling` re-uploads the small library archive to the | |
| # fixed dll-latest tag (the daily cadence), `full` also re-uploads the ~200 MB bundle to the tag | |
| # pinned in deps/RUNTIME_VERSION (the rare one -- see the two-cadence contract at the top of | |
| # deps/build.jl). | |
| name: MacBinaries | |
| on: | |
| push: | |
| branches: [master] | |
| paths: | |
| - 'deps/src/**' | |
| - 'deps/CMakeLists.txt' | |
| - 'deps/cmake/**' | |
| - 'deps/build_mac.sh' | |
| - '.github/workflows/MacBinaries.yml' | |
| pull_request: | |
| paths: | |
| - 'deps/src/**' | |
| - 'deps/CMakeLists.txt' | |
| - 'deps/cmake/**' | |
| - 'deps/build_mac.sh' | |
| workflow_dispatch: | |
| inputs: | |
| publish: | |
| description: 'What to upload to GitHub Releases' | |
| type: choice | |
| default: 'none' | |
| options: ['none', 'rolling', 'full'] | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: ${{ startsWith(github.ref, 'refs/pull/') }} | |
| jobs: | |
| build: | |
| name: macOS ${{ matrix.arch }} | |
| runs-on: ${{ matrix.os }} | |
| timeout-minutes: 90 | |
| permissions: | |
| contents: write # needed only by the publish step; harmless otherwise | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - os: macos-14 # Apple Silicon -- oldest standard arm64 image; sets the 14.x floor | |
| arch: arm64 | |
| julia_arch: aarch64 | |
| - os: macos-15-intel # no free macOS 14 Intel runner exists; see the header | |
| arch: x86_64 | |
| julia_arch: x64 | |
| steps: | |
| - uses: actions/checkout@v6 | |
| # NOT a job-level `env:`. The job-level env context is evaluated before a runner is picked, so | |
| # `runner.*` is unavailable there and GitHub rejects the whole file with "Unrecognized | |
| # named-value: 'runner'" -- the workflow then never runs at all, and never reports why. | |
| # $RUNNER_TEMP is the plain environment variable, always set on the runner itself. | |
| - name: Stage directory | |
| run: echo "IGMT_MACOS_STAGE=$RUNNER_TEMP/igmt" >> "$GITHUB_ENV" | |
| # `vtk` is already built with Qt6 (-DVTK_GROUP_ENABLE_Qt=YES) -- the `--with-qt` option that | |
| # older documentation mentions was removed from Homebrew in 2019 and is a hard error today. | |
| # It pulls qtbase+qtdeclarative only, so qttools (which provides Qt6::UiTools, used by every | |
| # runtime-loaded .ui dialog) and tbb have to be named explicitly. | |
| - name: Install dependencies | |
| run: brew install vtk qttools tbb ninja | |
| - name: Build + stage the bundle | |
| run: bash deps/build_mac.sh | |
| # The real test of a relocated bundle: does dyld actually load it somewhere other than where | |
| # it was staged, with no Homebrew paths left to fall back on? A compile that succeeded proves | |
| # nothing about install names or the ad-hoc signature (on arm64 a bad signature is a hard | |
| # load failure, not a warning). No window is created here -- dlopen + dlsym only -- so this | |
| # works on a runner with no display. | |
| - uses: julia-actions/setup-julia@v3 | |
| with: | |
| version: '1.11' | |
| arch: ${{ matrix.julia_arch }} | |
| - name: Smoke-test the relocated library | |
| run: | | |
| set -euo pipefail | |
| probe="${RUNNER_TEMP}/probe" | |
| mkdir -p "$probe" | |
| tar -xzf "${IGMT_MACOS_STAGE}/iGMT-macos-${{ matrix.arch }}-full.tar.gz" -C "$probe" | |
| julia -e ' | |
| using Libdl | |
| lib = joinpath(ENV["PROBE"], "deps", "build", "libgmtvtk.dylib") | |
| h = Libdl.dlopen(lib) | |
| p = Libdl.dlsym(h, :gmtvtk_abi_version) | |
| println("ABI generation: ", ccall(p, Cint, ())) | |
| ' | |
| env: | |
| PROBE: ${{ runner.temp }}/probe | |
| - uses: actions/upload-artifact@v4 | |
| with: | |
| name: gmtvtk-macos-${{ matrix.arch }} | |
| path: ${{ runner.temp }}/igmt/*.tar.gz | |
| if-no-files-found: error | |
| # Manual runs only, and only when the run explicitly asked for it. `--clobber` is the point of | |
| # the rolling asset: one fixed tag whose file is replaced in place, never a new tag per build. | |
| - name: Publish | |
| if: github.event_name == 'workflow_dispatch' && inputs.publish != 'none' | |
| env: | |
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | |
| ARCH: ${{ matrix.arch }} | |
| PUBLISH: ${{ inputs.publish }} | |
| run: | | |
| set -euo pipefail | |
| gh release upload dll-latest "${IGMT_MACOS_STAGE}/gmtvtk-macos-${ARCH}.tar.gz" --clobber | |
| if [[ $PUBLISH == full ]]; then | |
| tag=$(tr -d '[:space:]' < deps/RUNTIME_VERSION) | |
| gh release upload "$tag" "${IGMT_MACOS_STAGE}/iGMT-macos-${ARCH}-full.tar.gz" --clobber | |
| fi |