-
Notifications
You must be signed in to change notification settings - Fork 0
212 lines (193 loc) · 9.5 KB
/
Copy pathci.yml
File metadata and controls
212 lines (193 loc) · 9.5 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
name: CI
# What this workflow asserts.
#
# conformance the suite in the specification package runs against this
# implementation and every observation holds, under all three
# of this environment's toolchains
# surface the exported names are exactly the fifty-one the
# specification lists
# independence the objects reference no C runtime symbol
#
# This environment has two application binary interfaces and three toolchains
# that reach them, and an implementation that built under one of the three would
# not be an implementation for this environment. So all three are built: the two
# that produce the environment's own ABI, and the one that produces the other.
on:
push:
branches: [main]
pull_request:
workflow_dispatch:
env:
MCPP_VERSION: 2026.8.24.6
XLINGS_VERSION: v2026.8.17.2
XLINGS_NON_INTERACTIVE: '1'
jobs:
# ---------------------------------------------------------------------------
# On the system itself.
conformance:
name: conformance (${{ matrix.name }})
runs-on: windows-2022
timeout-minutes: 60
strategy:
fail-fast: false
matrix:
include:
- { name: 'llvm, msvc ABI', toolchain: 'llvm@20.1.7', target: '' }
- { name: 'msvc', toolchain: 'msvc@system', target: '' }
- { name: 'gcc, gnu CRT', toolchain: 'gcc@16.1.0', target: 'x86_64-windows-gnu' }
defaults:
run:
shell: bash
steps:
- uses: actions/checkout@v4
# The specification is checked out at the branch under test where it has
# one, so that this run asserts what it is for: that the specification as
# written there and this implementation as written here agree today.
- name: The specification
run: |
git clone --quiet https://github.com/mcpplibs/openkal.git .spec
branch='${{ github.head_ref || github.ref_name }}'
if git -C .spec rev-parse --verify --quiet "origin/$branch" > /dev/null; then
git -C .spec checkout --quiet "origin/$branch"
echo "the specification is at $branch"
else
echo "the specification has no $branch; its default branch is used"
fi
- name: Install xlings
shell: pwsh
run: |
irm https://d2learn.org/xlings-install.ps1.txt | iex
"$env:USERPROFILE\.xlings\subos\current\bin" | Out-File -FilePath $env:GITHUB_PATH -Encoding utf8 -Append
- name: Install mcpp
run: |
xlings update
xlings install "mcpp@$MCPP_VERSION" -y -g
mcpp --version
mcpp self config --mirror GLOBAL
- name: Select the toolchain
run: |
spec='${{ matrix.toolchain }}'
case "$spec" in
msvc*) mcpp toolchain default msvc ;;
*) mcpp toolchain install "${spec%@*}" "${spec#*@}"
mcpp toolchain default "$spec" ;;
esac
mcpp toolchain list
- name: Every interface, every kind of examination
run: |
extra=''
[ -n '${{ matrix.target }}' ] && extra='--target ${{ matrix.target }}'
bash .spec/tools/run-conformance.sh openkal-windows . full $extra
# ---------------------------------------------------------------------------
# From a system that is not this one.
#
# The same package, produced by a cross build and run under an implementation
# of this environment's interfaces rather than on the environment. It is here
# for two reasons: it is where the exported names can be examined with tools
# that read this environment's object format and are not on it, and a package
# that only builds on the system it targets is a package a contributor on any
# other system cannot work on.
cross:
name: cross build, run under wine, and examine the objects
runs-on: ubuntu-24.04
timeout-minutes: 60
steps:
- uses: actions/checkout@v4
- name: The specification
run: |
git clone --quiet https://github.com/mcpplibs/openkal.git .spec
branch='${{ github.head_ref || github.ref_name }}'
if git -C .spec rev-parse --verify --quiet "origin/$branch" > /dev/null; then
git -C .spec checkout --quiet "origin/$branch"
fi
- name: Install wine
run: |
sudo dpkg --add-architecture i386
sudo apt-get update -qq
# Which package carries it and what the program is called differ
# between distributions and between releases of one, so both are
# tried and the name that exists is the one used. A script that names
# one of them fails with "command not found" after a successful
# install, which reads as a missing package rather than a renamed
# program.
sudo apt-get install -y --no-install-recommends wine wine64 > /dev/null 2>&1 \
|| sudo apt-get install -y --no-install-recommends wine > /dev/null
runner="$(command -v wine || command -v wine64)"
test -n "$runner" || { echo "no wine was installed" >&2; exit 1; }
"$runner" --version
echo "OPENKAL_CONFORMANCE_RUNNER=$runner" >> "$GITHUB_ENV"
- name: Install xlings
run: |
curl -fsSL https://raw.githubusercontent.com/openxlings/xlings/main/tools/other/quick_install.sh \
| bash -s "$XLINGS_VERSION"
echo "$HOME/.xlings/subos/current/bin" >> "$GITHUB_PATH"
- name: Install mcpp
run: |
xlings update
xlings install "mcpp@$MCPP_VERSION" -y -g
mcpp self config --mirror GLOBAL
- name: Every interface, every kind of examination
env:
WINEDEBUG: '-all'
run: |
bash .spec/tools/run-conformance.sh openkal-windows . full \
--target x86_64-windows-gnu
- name: The exported surface is complete and contains nothing else
run: |
# Clause 9.3. The list and the checker come from the specification
# rather than from a copy kept here, so that the comparison has one
# source. --complete because this implementation claims every
# interface: a name it fails to export is a failure, not an interface
# it declines to provide.
rm -rf target && mcpp build --target x86_64-windows-gnu
objs="$(find target -path '*/obj/*' -name '*.o' ! -name '*.m.o' | tr '\n' ' ')"
test -n "$objs" || { echo "no objects were found" >&2; exit 1; }
bash .spec/tools/check-surface.sh --complete .spec/SURFACE.txt $objs
# The property this implementation exists to have. A program above openkal
# may supply a C runtime of its own; an implementation that reached for
# this environment's would have its calls resolve to the program's, and
# the program's would resolve back here.
- name: The objects reference no C runtime symbol
run: |
rm -rf target && mcpp build --features standalone --target x86_64-windows-gnu
objs="$(find target -path '*/obj/*' -name '*.o' ! -name '*.m.o')"
test -n "$objs" || { echo "no objects were found; the check would pass vacuously" >&2; exit 1; }
# The permitted set, and why each entry is in it.
#
# __imp_* this environment's own interfaces, reached through
# the import table. They are the environment, not a C runtime.
# Nt*, Rtl* the object manager, likewise.
# WaitOnAddress, WakeByAddress* the suspension primitive, which
# this environment publishes without an import stub.
# memcpy, memmove, memset, memcmp a compiler emits calls to these
# from ordinary loops. They compute rather than call, so none of
# them can re-enter this implementation.
# __libc_start_main, main the hand-over, undefined here by
# construction.
# kal_*, _ZN3okw* the interface and this package.
# __chkstk_ms, __udivti3, ... the compiler's own support
# routines, which are in the compiler's library and not in a C
# runtime.
permitted='^(__imp_[A-Za-z0-9_]+|Nt[A-Za-z]+|Rtl[A-Za-z]+|WaitOnAddress|WakeByAddress(All|Single)|memcpy|memmove|memset|memcmp|__libc_start_main|main|kal_[a-z_]+|_ZN3okw.*|_*chkstk[a-z_]*|__udiv[a-z0-9]*|__umod[a-z0-9]*|__divti3|__modti3|_GLOBAL_OFFSET_TABLE_)$'
bad=0
for s in $(nm --undefined-only $objs | awk '{print $2}' | sort -u); do
[ -n "$s" ] || continue
printf '%s\n' "$s" | grep -qE "$permitted" || {
echo "the implementation references a symbol it must not: $s" >&2
bad=1
}
done
test "$bad" -eq 0
echo "the implementation references no C runtime symbol"
# A checker is only useful if it fails when it should.
- name: The independence check detects a dependence
run: |
printf 'extern "C" int puts(const char*);\nextern "C" void okw_probe(void) { puts("x"); }\n' > src/probe.cpp
rm -rf target && mcpp build --features standalone --target x86_64-windows-gnu
objs="$(find target -path '*/obj/*' -name '*.o' ! -name '*.m.o')"
if ! nm --undefined-only $objs | awk '{print $2}' | grep -qx puts; then
echo "the probe did not produce the reference it was written to produce" >&2
rm -f src/probe.cpp; exit 1
fi
rm -f src/probe.cpp
echo "a dependence upon a C runtime is visible to the check"