Repository navigation
223 lines (219 loc) · 10.6 KB
/
Copy pathcpp.yml
File metadata and controls
223 lines (219 loc) · 10.6 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
name: Native C++ build
on:
push:
branches: [master, cplusplus]
tags: ['v*']
pull_request:
branches: [master, cplusplus]
permissions:
contents: write # only release job needs this, to create the GitHub Release and upload assets
jobs:
build-and-test:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest, macos-latest, windows-2022]
runs-on: ${{ matrix.os }}
# Backstop for a hang outside ctest's own --timeout (e.g. mid-build, or
# a package/upload step) - a normal run finishes in well under 10
# minutes on any of the three OSes, so this only ever fires on a
# genuinely wedged job instead of burning the default multi-hour limit.
timeout-minutes: 30
steps:
- uses: actions/checkout@v4
# Not the fix for the DLL_PROCESS_DETACH deadlock below (fastExit()
# in tests/fast_exit.hpp is) - kept anyway as cheap, harmless
# insurance against unrelated Defender-induced slowness on freshly-
# built, unsigned .exe's. $env:TEMP (Windows' own temp dir, e.g.
# C:\Users\runneradmin\AppData\Local\Temp) is a DIFFERENT root than
# GITHUB_WORKSPACE/the MSYS2 install dir below and was missing here -
# QTemporaryDir/std::filesystem::temp_directory_path() (the Reproject
# tab's own tests among them) write their real, GDAL-produced .nc
# output there, and real-time scanning of a freshly-closed netCDF/
# HDF5 file (chunked+compressed, unlike the plain test fixtures) is a
# documented source of exactly this kind of runner-only stall - a
# worker process that had already finished all its actual GDAL work
# and simply never returned from closing the output file. The worker
# and test executables themselves are also added to ExclusionProcess
# for the same reason, on top of the path exclusion.
- name: Exclude workspace from Windows Defender (Windows)
if: runner.os == 'Windows'
shell: pwsh
continue-on-error: true
run: |
Add-MpPreference -ExclusionPath "$env:GITHUB_WORKSPACE"
Add-MpPreference -ExclusionPath "D:\a\_temp\msys64"
Add-MpPreference -ExclusionPath "$env:TEMP"
Add-MpPreference -ExclusionProcess "c++.exe","cc1plus.exe","ctest.exe","ninja.exe","wrftools_reproject_worker.exe","wrftools_ui_tests.exe","wrftools_core_tests.exe","wrftools_widget_tests.exe"
# libnetcdf-dev/netcdf/mingw-w64-x86_64-netcdf (below): NetcdfFile's
# (netcdf_file.hpp/.cpp) direct netCDF-C linkage for the w2w LCZ port
# - see CMakeLists.txt's pkg_check_modules(NETCDF ...) and
# PORT_W2W.MD Stage 0. Each package also pulls in its own HDF5
# dependency automatically via the OS package manager - no separate
# HDF5 install step needed on any of the three platforms.
# ubuntugis-unstable PPA: Ubuntu 24.04's own libgdal-dev is 3.8.4,
# older than the 3.9 CMakeLists.txt requires (OGRSpatialReference::
# exportToCF1(), used by reproject.cpp's CF grid-mapping construction,
# landed in GDAL 3.9.0) - the PPA carries 3.11.x for noble. Added
# before the plain apt-get install below, not as a separate pinned
# package, so apt just resolves libgdal-dev (and its libproj/libgeos/
# etc. dependencies) to the PPA's newer versions on its own.
- name: Install Linux dependencies
if: runner.os == 'Linux'
run: |
sudo add-apt-repository -y ppa:ubuntugis/ubuntugis-unstable
sudo apt-get update
sudo apt-get install -y cmake ninja-build g++ qt6-base-dev libgdal-dev libproj-dev libnetcdf-dev pkg-config catch2 patchelf
- name: Install macOS dependencies
if: runner.os == 'macOS'
run: brew install cmake ninja qt gdal proj netcdf pkg-config catch2 dylibbundler
# MSYS2/MinGW64 rather than MSVC+vcpkg: its package repo already has
# prebuilt Qt6/GDAL/PROJ/netCDF/Catch2 (matching the apt/brew jobs' approach
# of using the OS's own package manager instead of building
# dependencies from source), and its GCC accepts the same
# -Wall/-Wextra/-Wpedantic flags CMakeLists.txt already sets
# unconditionally - MSVC's cl.exe does not take those.
- name: Set up MSYS2 (Windows)
if: runner.os == 'Windows'
uses: msys2/setup-msys2@v2
with:
msystem: MINGW64
update: true
install: >-
mingw-w64-x86_64-toolchain
mingw-w64-x86_64-cmake
mingw-w64-x86_64-ninja
mingw-w64-x86_64-qt6-base
mingw-w64-x86_64-gdal
mingw-w64-x86_64-proj
mingw-w64-x86_64-libtiff
mingw-w64-x86_64-libgeotiff
mingw-w64-x86_64-netcdf
mingw-w64-x86_64-pkgconf
mingw-w64-x86_64-catch
zip
- name: Configure Linux
if: runner.os == 'Linux'
run: cmake -S . -B build-cpp -G Ninja -DCMAKE_BUILD_TYPE=Debug
- name: Configure macOS
if: runner.os == 'macOS'
run: cmake -S . -B build-cpp -G Ninja -DCMAKE_BUILD_TYPE=Debug -DCMAKE_PREFIX_PATH="$(brew --prefix qt)"
- name: Configure Windows
if: runner.os == 'Windows'
shell: msys2 {0}
run: cmake -S . -B build-cpp -G Ninja -DCMAKE_BUILD_TYPE=Debug
# Linux/macOS share these two (default shell); Windows needs its own
# copies with shell: msys2 {0} - the `shell:` field's expression
# evaluator does not expose the `runner` context (unlike `if:`), so a
# single `shell: ${{ runner.os == ... }}` step is rejected outright as
# an invalid workflow file before any job even starts.
- name: Build
if: runner.os != 'Windows'
run: cmake --build build-cpp
- name: Build (Windows)
if: runner.os == 'Windows'
shell: msys2 {0}
run: cmake --build build-cpp
# --timeout caps each individual ctest entry - wrftools_ui_tests is
# the slowest single one (it's one add_test() wrapping the whole
# Catch2 binary, not per-case catch_discover_tests - see
# CMakeLists.txt), since the Reproject tab's UI tests do real GDAL
# work and one of them launches wrftools_reproject_worker as a genuine
# child QProcess. 120s is generous headroom on Linux/macOS (~95s
# there) while still turning an actual hang into a clear failure
# instead of silently consuming the job's multi-hour default timeout.
- name: Test
if: runner.os != 'Windows'
run: ctest --test-dir build-cpp --output-on-failure --timeout 120
# Windows gets a higher ceiling than Linux/macOS: process spawn + DLL
# load (Qt/GDAL/netCDF/PROJ, all freshly loaded, no warm page cache)
# is markedly slower on a Windows CI runner, and wrftools_ui_tests
# already measured at ~115s there even while its own subprocess-based
# reprojection test was still hitting its internal wait deadline (see
# waitWhileRunning(ReprojectForm&) in ui_tests.cpp) rather than
# actually finishing - 120s left no margin at all once that deadline
# was raised to let it actually complete.
- name: Test (Windows)
if: runner.os == 'Windows'
shell: msys2 {0}
# 240, not 120: Windows CI is measurably slower for GDAL-heavy work
# - confirmed by CI, not guessed. The full LCZ pipeline test alone
# measured over 180s but under 240s there; wrftools_ui_tests (one
# add_test(), not per-case catch_discover_tests) measured ~115s on
# top of that even before accounting for the Reproject worker's own
# subprocess test, which used to hang indefinitely on Windows for
# an unrelated reason - see reproject_worker.cpp's fastExit(), now
# fixed. This timeout is just ordinary Windows-vs-Linux/macOS
# slack, not a workaround for that bug.
run: ctest --test-dir build-cpp --output-on-failure --timeout 240
# Packaged separately from the Debug build/test above (its own fresh
# Release, BUILD_TESTING=OFF configure+build) - only reached once
# tests have actually passed, matching what build-portable-cpp.sh/
# build-portable-macos.sh already do when run by hand.
- name: Package portable Linux bundle
if: runner.os == 'Linux'
run: ./build-portable-cpp.sh
# Wraps the same dist/wrftools-cpp/ bundle above into a single-file
# AppImage - see build-portable-appimage.sh's own header comment.
# Only needs curl (already on the runner image) beyond what the
# bundle step above already installed.
- name: Package Linux AppImage
if: runner.os == 'Linux'
run: ./build-portable-appimage.sh
- name: Package portable macOS app
if: runner.os == 'macOS'
run: ./build-portable-macos.sh
- name: Package portable Windows bundle
if: runner.os == 'Windows'
shell: msys2 {0}
run: ./build-portable-windows.sh
- name: Upload Linux artifact
if: runner.os == 'Linux'
uses: actions/upload-artifact@v4
with:
name: wrftools-linux
path: dist/wrftools-cpp/
- name: Upload Linux AppImage artifact
if: runner.os == 'Linux'
uses: actions/upload-artifact@v4
with:
name: wrftools-linux-appimage
path: dist/wrftools-x86_64.AppImage
- name: Upload macOS artifact
if: runner.os == 'macOS'
uses: actions/upload-artifact@v4
with:
name: wrftools-macos
path: dist/wrftools-macos.zip
- name: Upload Windows artifact
if: runner.os == 'Windows'
uses: actions/upload-artifact@v4
with:
name: wrftools-windows
path: dist/wrftools-windows.zip
release:
needs: build-and-test
if: startsWith(github.ref, 'refs/tags/v')
runs-on: ubuntu-latest
steps:
- name: Download all platform artifacts
uses: actions/download-artifact@v4
with:
path: artifacts
# Only the Linux artifact is uploaded as a bare directory (the
# macOS/Windows packaging scripts already produce a single .zip each,
# so those artifacts download as one file) - zip it here so all three
# release assets are a single downloadable file apiece.
- name: Zip the Linux artifact
run: |
cd artifacts/wrftools-linux
zip -r ../wrftools-linux.zip .
- name: Create GitHub Release
uses: softprops/action-gh-release@v2
with:
files: |
artifacts/wrftools-linux.zip
artifacts/wrftools-linux-appimage/wrftools-x86_64.AppImage
artifacts/wrftools-macos/wrftools-macos.zip
artifacts/wrftools-windows/wrftools-windows.zip
generate_release_notes: true