Repository navigation
238 lines (199 loc) · 9.41 KB
/
Copy pathbuild.yml
File metadata and controls
238 lines (199 loc) · 9.41 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
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
name: build
# Builds the tap.python package on macOS and Windows.
# The embedded Python runtime is installed by scripts/install-runtime.*
# before configuring, since the externals link against it.
#
# The host-independent core (core/) is also built and tested on Linux against
# CPython 3.13, plain and under sanitizers — no Max, min-api or runtime install.
# The external and its mock-kernel unit test build on Linux too (Max does not
# run there, but the glue does), embedding the same CPython 3.13.
on:
push:
branches: ["**"]
pull_request:
workflow_dispatch:
# Least privilege: the jobs only read the repository. Third-party actions are pinned by
# commit SHA (the tag each SHA was cut from is noted beside it).
permissions:
contents: read
# A newer push to the same branch or PR supersedes the run in progress.
concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
jobs:
linux-core:
name: linux-core (${{ matrix.name }})
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
include:
- name: release
build_type: Release
sanitize: ""
- name: asan-ubsan
build_type: Debug
sanitize: "address,undefined"
- name: tsan
build_type: Debug
sanitize: "thread"
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: "3.13"
- name: Install the examples' dependencies into the embedded interpreter's prefix
run: 'python -m pip install --require-hashes --only-binary :all: -r scripts/requirements.lock'
# The sanitizer runtimes cannot map their shadow memory with the runner
# kernel's default ASLR entropy ("unexpected memory mapping").
- name: Reduce ASLR entropy for the sanitizers
if: matrix.sanitize != ''
run: sudo sysctl vm.mmap_rnd_bits=28
- name: Configure
run: >
cmake -S core -B build-core
-DCMAKE_BUILD_TYPE=${{ matrix.build_type }}
-DPython3_EXECUTABLE="$(which python)"
-DTAP_PYTHON_SANITIZE="${{ matrix.sanitize }}"
- name: Build
run: cmake --build build-core --parallel
- name: Test
env:
TAP_PYTHON_TEST_REQUIRE_EXAMPLES: "1"
UBSAN_OPTIONS: halt_on_error=1:print_stacktrace=1
TSAN_OPTIONS: halt_on_error=1
run: ctest --test-dir build-core --output-on-failure --parallel 4
linux-max-glue:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
submodules: recursive
- uses: actions/setup-python@a26af69be951a213d495a4c3e4e4022e16d87065 # v5.6.0
with:
python-version: "3.13"
- name: Install the examples' dependencies into the embedded interpreter's prefix
run: 'python -m pip install --require-hashes --only-binary :all: -r scripts/requirements.lock'
- name: Configure
run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DPython3_EXECUTABLE="$(which python)"
- name: Build
run: cmake --build build --parallel
- name: Test
run: ctest --test-dir build --output-on-failure
# The Windows external delay-loads python3xx.dll (plan 4.2), which MSVC allows only while
# the external imports no CPython data symbols. The same headers make the same references
# here, so a regression fails this step by name rather than the Windows link.
- name: Verify the external imports no CPython data symbols
run: |
libpython=$(python -c "import sysconfig; print(sysconfig.get_config_var('LIBDIR') + '/' + sysconfig.get_config_var('LDLIBRARY'))")
scripts/check-data-imports.sh externals/tap.python~.mxl_x86_64 "$libpython"
# The release packaging's license collection (plan 4.6), against this interpreter's own
# install, which is laid out like the macOS runtime and has the locked packages in it.
- name: Collect the licenses a package would ship
run: |
python scripts/assemble-package.py --licenses-only \
--support "$(python -c 'import sys; print(sys.base_prefix)')" --output build/licenses-check
cat build/licenses-check/licenses/README.md
macos:
runs-on: macos-latest
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
submodules: recursive
# The runtime is exactly what the lock files pin, so it is cached on them (and on
# the installer itself); any change to either reinstalls it.
- name: Cache the Python runtime
id: runtime
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: support
key: runtime-macos-universal-${{ hashFiles('scripts/runtime.lock', 'scripts/requirements.lock', 'scripts/install-runtime.sh') }}
- name: Install Python runtime (universal libpython for linking)
if: steps.runtime.outputs.cache-hit != 'true'
run: ./scripts/install-runtime.sh --universal
- name: Configure (universal arm64 + x86_64)
run: cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_ARCHITECTURES="arm64;x86_64"
- name: Build
run: cmake --build build --config Release
- name: Test
run: ctest --test-dir build --output-on-failure
- name: Verify externals are universal
run: |
set -e
ls -la externals
for mxo in externals/*.mxo; do
bin="$mxo/Contents/MacOS/$(basename "$mxo" .mxo)"
echo "== $mxo =="
lipo -info "$bin"
lipo -info "$bin" | grep -q "arm64" && lipo -info "$bin" | grep -q "x86_64" \
|| { echo "ERROR: $bin is not universal"; exit 1; }
done
# max-sdk-base leaves the identifier for Xcode to expand; the object's CMakeLists expands it
- name: Verify the bundle identifier is expanded
run: |
id=$(plutil -extract CFBundleIdentifier raw "externals/tap.python~.mxo/Contents/Info.plist")
echo "CFBundleIdentifier: $id"
[ "$id" = "com.74objects.tap.python-tilde" ] \
|| { echo "ERROR: expected com.74objects.tap.python-tilde"; exit 1; }
- name: Verify libpython resolves via a relative rpath only
run: |
bin="externals/tap.python~.mxo/Contents/MacOS/tap.python~"
otool -L "$bin"
otool -L "$bin" | grep -q "@rpath/libpython" \
|| { echo "ERROR: libpython is not linked via @rpath"; exit 1; }
rpaths=$(otool -l "$bin" | awk '/cmd LC_RPATH/ { getline; getline; print $2 }')
echo "rpaths: $rpaths"
echo "$rpaths" | grep -q "^@loader_path/" \
|| { echo "ERROR: the @loader_path rpath to support/lib is missing"; exit 1; }
if echo "$rpaths" | grep -q "^/"; then
echo "ERROR: an absolute build-machine path is embedded as an rpath"; exit 1
fi
# Weakly linked, so the external loads without a runtime and says what is missing (plan 4.2).
- name: Verify libpython is weakly linked
run: |
bin="externals/tap.python~.mxo/Contents/MacOS/tap.python~"
otool -l "$bin" | grep -A2 "cmd LC_LOAD_WEAK_DYLIB" | tee /dev/stderr | grep -q "@rpath/libpython" \
|| { echo "ERROR: libpython is not weakly linked"; exit 1; }
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: tap-python-macos
path: externals/*.mxo
windows:
runs-on: windows-latest
steps:
- uses: actions/checkout@11d5960a326750d5838078e36cf38b85af677262 # v4.4.0
with:
submodules: recursive
- name: Cache the Python runtime
id: runtime
uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0
with:
path: support
key: runtime-windows-${{ hashFiles('scripts/runtime.lock', 'scripts/requirements.lock', 'scripts/install-runtime.ps1') }}
- name: Install Python runtime
if: steps.runtime.outputs.cache-hit != 'true'
run: powershell -ExecutionPolicy Bypass -File scripts\install-runtime.ps1
- name: Configure
run: cmake -S . -B build -A x64
- name: Build
run: cmake --build build --config Release
- name: Test
run: |
$env:PATH = "$PWD\support;$env:PATH" # so the test binary finds python3xx.dll
ctest --test-dir build --output-on-failure -C Release
- name: List externals
run: dir externals
# Delay-loaded, so the external loads without a runtime and says what is missing (plan 4.2).
- name: Verify python3xx.dll is delay-loaded
shell: pwsh
run: |
$dumpbin = & "${env:ProgramFiles(x86)}\Microsoft Visual Studio\Installer\vswhere.exe" -latest -find "VC\Tools\MSVC\*\bin\Hostx64\x64\dumpbin.exe" | Select-Object -First 1
$deps = & $dumpbin /dependents "externals\tap.python~.mxe64" | Out-String
Write-Output $deps
if ($deps -notmatch "(?s)delay load dependencies:.*python3\d+\.dll") {
Write-Error "python3xx.dll is not delay-loaded"; exit 1
}
- uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: tap-python-windows
path: externals/*.mxe64