-
Notifications
You must be signed in to change notification settings - Fork 0
183 lines (168 loc) · 8.27 KB
/
Copy pathci.yml
File metadata and controls
183 lines (168 loc) · 8.27 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
# Build every member on BOTH toolchains, and check what a green compile would
# not: that the generator is ours, that the sonames are canonical, that the two
# libraries do not overlap, and that every module produced an interface.
name: ci
on:
push:
branches: [main]
tags: ['v*']
pull_request:
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
# Both, because the module wrappers are where the two compilers differ
# most: a 300-entry `using ::name;` export block is exactly the shape
# that finds a disagreement about what may be named in an export.
toolchain: [default, llvm]
name: build (${{ matrix.toolchain }})
steps:
- uses: actions/checkout@v4
# Installed the way a user does, through xlings, rather than by
# unpacking an mcpp release: these packages depend on the ECOSYSTEM
# (`xim:mesa`'s GBM discovery row, the toolchains), and a pinned mcpp
# tarball carries a frozen snapshot of it. Testing against the current
# ecosystem is the point.
#
# XLINGS_NON_INTERACTIVE is what makes the installer usable here. Without
# it the script takes its `curl | bash` branch — `xlings self install <
# /dev/tty` — and a runner has a /dev/tty that is readable but not
# connected, so it dies with "No such device or address" before anything
# is installed.
- name: Install xlings + mcpp
env:
XLINGS_NON_INTERACTIVE: "1"
run: |
curl -fsSL https://d2learn.org/xlings-install.sh | bash
echo "$HOME/.xlings/bin" >> "$GITHUB_PATH"
"$HOME/.xlings/bin/xlings" --version
"$HOME/.xlings/bin/xlings" install mcpp
echo "$HOME/.xlings/subos/default/bin" >> "$GITHUB_PATH"
- name: Select toolchain
if: matrix.toolchain != 'default'
run: |
mcpp toolchain install ${{ matrix.toolchain }}
mcpp toolchain default ${{ matrix.toolchain }}
mcpp toolchain list
- name: Build the workspace
run: |
mcpp --version
mcpp build --workspace
- name: The macro mappings actually run
run: mcpp test -p mcpp/util
# Artifacts are located by searching the tree rather than by assuming
# `mcpp/<member>/target/...`: where a workspace build puts its output is
# mcpp's business and has moved before. On a miss the step prints what it
# DID find, so the next failure is diagnosable from the log alone.
- name: wayland-scanner is ours, and is 1.26.0
run: |
scanner=$(find . -name wayland-scanner -type f -perm -u+x | head -1)
if [ -z "$scanner" ]; then
echo "::error::no wayland-scanner binary anywhere in the tree"
find . -path ./upstream -prune -o -name 'target' -type d -print
exit 1
fi
echo "found: $scanner"
"$scanner" --version
"$scanner" --version | grep -qx 'wayland-scanner 1.26.0'
- name: the generated protocol code came from THIS scanner
run: |
scanner=$(find . -name wayland-scanner -type f -perm -u+x | head -1)
"$scanner" -s public-code upstream/protocol/wayland.xml /tmp/wayland-protocol.c
head -1 /tmp/wayland-protocol.c
grep -q 'Generated by wayland-scanner 1.26.0' /tmp/wayland-protocol.c
- name: both libraries carry the canonical SONAMEs
run: |
for pair in "client:libwayland-client.so.0" "server:libwayland-server.so.0"; do
member=${pair%%:*}; want=${pair#*:}
so=$(find . -name "${want%.0}" -type f | head -1)
test -n "$so" || { echo "$member: no library built"; exit 1; }
got=$(readelf -d "$so" | sed -n 's/.*SONAME.*\[\(.*\)\]/\1/p')
echo "$member -> $got"
test "$got" = "$want" || { echo "expected $want"; exit 1; }
done
- name: the two libraries do not overlap
run: |
# Mesa's libEGL_mesa has DT_NEEDED on both; if one carried the other's
# API the process would bind to whichever loaded first.
c=$(find . -name libwayland-client.so -type f | head -1)
s=$(find . -name libwayland-server.so -type f | head -1)
readelf --dyn-syms -W "$c" | grep -q ' wl_display_connect' || exit 1
readelf --dyn-syms -W "$c" | grep -q ' wl_display_create' && { echo "client leaked the server API"; exit 1; }
readelf --dyn-syms -W "$s" | grep -q ' wl_display_create' || exit 1
readelf --dyn-syms -W "$s" | grep -q ' wl_display_connect' && { echo "server leaked the client API"; exit 1; }
echo "client and server APIs are disjoint"
- name: mcpp/generated/ matches what the scanner produces
run: |
# The generated protocol code is checked in because it is the
# package's PUBLIC interface (wayland-client.h includes it), so a
# build-time include dir cannot carry it. Checked in means it can
# drift; this is what stops it.
scanner=$(find . -name wayland-scanner -type f -perm -u+x | head -1)
X=upstream/protocol/wayland.xml
mkdir -p /tmp/regen
"$scanner" -s public-code "$X" /tmp/regen/wayland-protocol.c
for side in client server; do
"$scanner" -s $side-header "$X" /tmp/regen/wayland-$side-protocol.h
"$scanner" -s $side-header -c "$X" /tmp/regen/wayland-$side-protocol-core.h
done
for f in /tmp/regen/*; do
n=$(basename "$f")
if ! diff -q "$f" "mcpp/generated/$n" >/dev/null; then
echo "::error file=mcpp/generated/$n::out of date — regenerate it (see mcpp/generated/README.md)"
diff "$f" "mcpp/generated/$n" | head -20
exit 1
fi
done
echo "generated code matches wayland.xml and this scanner"
- name: the module wrappers match the generator
run: |
# The .cppm files and the -module.h copies are generated from the
# public headers. Checked in, so they can drift; this stops it.
python3 mcpp/tools/genmod.py .
if ! git diff --quiet; then
echo "::error::module wrappers are out of date — run mcpp/tools/genmod.py ."
git diff --stat
exit 1
fi
echo "module wrappers match"
- name: every module produced an interface
run: |
for m in wayland.client wayland.server wayland.util; do
find . \( -name "$m.gcm" -o -name "$m.pcm" \) | head -1 | grep -q . \
|| { echo "::error::$m has no module interface"; find . -name '*.gcm' -o -name '*.pcm'; exit 1; }
echo "$m ok"
done
echo "wayland.client, wayland.server and wayland.util all have interfaces"
upstream:
# `upstream/` must be the release tarball, byte for byte.
#
# Checked by COMPARING, not by building: this repository builds one way,
# through mcpp, and keeping a second build system alive just to assert
# something would be a second thing to maintain and a second thing to
# disagree with the first. Comparing is also the stronger check — meson
# succeeding proves the tree still builds, not that nothing was edited.
name: upstream/ is the release tarball, unmodified
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: diff upstream/ against wayland 1.26.0
run: |
curl -L -fsS -o wayland.tar.xz \
"https://gitlab.freedesktop.org/wayland/wayland/-/releases/1.26.0/downloads/wayland-1.26.0.tar.xz"
echo "64176eaa46e4969903e286f8e5ef8331affc17fdf03ac9b58381d2b23162b7a3 wayland.tar.xz" | sha256sum -c -
mkdir -p /tmp/pristine
tar -xJf wayland.tar.xz -C /tmp/pristine
# .gitignore lives at the repo root here, not inside upstream/ — it is
# this repository's, covering mcpp's build output. It is the one
# expected difference.
if diff -r --exclude=.gitignore /tmp/pristine/wayland-1.26.0 upstream; then
echo "upstream/ is pristine"
else
echo "::error::upstream/ differs from the wayland 1.26.0 release tarball."
echo "Everything this fork adds belongs under mcpp/."
exit 1
fi