-
-
Notifications
You must be signed in to change notification settings - Fork 32
199 lines (180 loc) · 7.59 KB
/
Copy pathbuild-native.yml
File metadata and controls
199 lines (180 loc) · 7.59 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
name: Build native
# Produces the diffengine_viewer binaries committed under
# src/DiffEngineViewer.{Linux,Mac}/runtimes/{rid}/native, in the head that loads them. There is no
# Windows equivalent: that head renders with WinForms.
#
# They are committed rather than built during a normal build so that a plain
# `dotnet build src --configuration Release` produces a shippable package on any machine, and
# contributors never need a C++ toolchain. Run this whenever native/ changes.
on:
push:
paths:
- 'native/**'
- '.github/workflows/build-native.yml'
pull_request:
paths:
- 'native/**'
workflow_dispatch:
inputs:
commit:
description: 'Open a PR with the rebuilt binaries'
type: boolean
default: true
concurrency:
group: build-native-${{ github.ref }}
cancel-in-progress: true
jobs:
build:
name: ${{ matrix.rid }}
runs-on: ${{ matrix.os }}
timeout-minutes: 45
strategy:
fail-fast: false
matrix:
include:
# No Windows entries. That head renders with WinForms and loads no native library.
- rid: linux-x64
os: ubuntu-24.04
- rid: linux-arm64
os: ubuntu-24.04-arm
# One universal binary covers both macOS RIDs; it is copied into each below.
- rid: osx
os: macos-14
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Install build dependencies
if: runner.os == 'Linux'
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
cmake ninja-build \
libx11-dev libxrandr-dev libxi-dev libxcursor-dev libxinerama-dev \
libgl1-mesa-dev libglu1-mesa-dev libwayland-dev libxkbcommon-dev
- name: Configure
if: matrix.rid != 'osx'
run: cmake -S native -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
- name: Build
if: matrix.rid != 'osx'
run: cmake --build build --config Release
# macOS draws with AppKit and Core Text rather than raylib and ImGui, so it is a Swift
# package rather than a CMake project. Both --arch flags in one invocation produce a
# universal binary, so there is no separate lipo step.
#
# Nothing of the Swift runtime is shipped: it has been part of macOS since 10.14.4, which is
# why this dylib is a fraction of the size of the one it replaced.
- name: Build
if: matrix.rid == 'osx'
run: swift build -c release --arch arm64 --arch x86_64 --package-path native/swift
- name: Collect
shell: bash
run: |
# Laid out as src/{head}/runtimes/{rid}/native, so the propose job below can merge every
# artifact straight into src and the binaries land in the head that loads them.
collect() {
mkdir -p "artifacts/$1/runtimes/$2/native"
cp "$3" "artifacts/$1/runtimes/$2/native/"
}
case "${{ matrix.rid }}" in
linux-*)
strip build/libdiffengine_viewer.so
collect DiffEngineViewer.Linux "${{ matrix.rid }}" build/libdiffengine_viewer.so
;;
osx)
# swift build leaves a per architecture dylib in more than one place, so taking the
# first one found gives a single slice binary that loads on half the Macs in the
# world. Every candidate is checked, and if none is already universal they are
# merged, so the only thing that can be collected is a fat binary.
# The dSYM contains a DWARF file of the same name which is also universal, so the
# arch check below would happily accept it and ship debug symbols as the library.
candidates=$(find native/swift/.build -name libdiffengine_viewer.dylib -not -path '*.dSYM/*')
if [ -z "$candidates" ]; then
echo "::error::swift build produced no libdiffengine_viewer.dylib"
exit 1
fi
echo "$candidates" | while read -r candidate; do
echo "$candidate: $(lipo -archs "$candidate" 2>/dev/null)"
done
dylib=""
for candidate in $candidates; do
archs=$(lipo -archs "$candidate" 2>/dev/null || echo "")
if [[ "$archs" == *x86_64* && "$archs" == *arm64* ]]; then
dylib="$candidate"
break
fi
done
if [ -z "$dylib" ]; then
dylib=universal/libdiffengine_viewer.dylib
mkdir -p universal
# shellcheck disable=SC2086
lipo -create $candidates -output "$dylib"
fi
archs=$(lipo -archs "$dylib")
echo "collecting $dylib: $archs"
for arch in x86_64 arm64; do
case " $archs " in
*" $arch "*) ;;
*) echo "::error::$dylib is missing the $arch slice"; exit 1 ;;
esac
done
strip -x "$dylib"
# The dylib is universal, so both macOS RIDs get the same file.
collect DiffEngineViewer.Mac osx-x64 "$dylib"
collect DiffEngineViewer.Mac osx-arm64 "$dylib"
;;
esac
ls -lhR artifacts
- name: Upload
uses: actions/upload-artifact@v4
with:
name: native-${{ matrix.rid }}
path: artifacts/
retention-days: 7
propose:
name: propose update
needs: build
# Also on push, not just manual dispatch. workflow_dispatch does not appear in the Actions UI
# until the workflow is on the default branch, so on a feature branch a push is the only way
# to trigger this, and leaving the binaries as bare artifacts to copy by hand is worse.
#
# Branches only. Never on pull_request, which would mean opening a PR from a PR, and never on
# a tag: a tag checkout is a detached HEAD with no base branch to target, and proposing a
# binaries PR against a release tag is meaningless anyway.
if: >-
github.event_name != 'pull_request' &&
startsWith(github.ref, 'refs/heads/') &&
(github.event_name != 'workflow_dispatch' || inputs.commit)
runs-on: ubuntu-latest
permissions:
contents: write
pull-requests: write
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Download
uses: actions/download-artifact@v4
with:
pattern: native-*
merge-multiple: true
path: src
- name: Show what changed
run: |
ls -lhR src/DiffEngineViewer.Linux/runtimes src/DiffEngineViewer.Mac/runtimes
git status --short
# A PR rather than a direct push: these are binaries, so the diff is not reviewable and the
# change deserves an explicit approval.
- name: Open pull request
uses: peter-evans/create-pull-request@v7
with:
# Scoped to the triggering branch, which is also the base, so a rebuild on a feature
# branch does not collide with one on main.
branch: native-binaries-${{ github.ref_name }}
title: 'Rebuild native renderer binaries'
commit-message: 'Rebuild native renderer binaries'
body: |
Rebuilt `diffengine_viewer` from `native/` for the four RIDs that load one.
Windows is not among them: that head renders with WinForms.
Produced by the `build-native` workflow from ${{ github.sha }}.
add-paths: |
src/DiffEngineViewer.Linux/runtimes
src/DiffEngineViewer.Mac/runtimes