forked from copper-project/copper-rs
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathjustfile
More file actions
391 lines (327 loc) · 13.9 KB
/
justfile
File metadata and controls
391 lines (327 loc) · 13.9 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
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
# CI-aligned helpers mirroring .github/workflows/general.yml
BASE_FEATURES := "mock,image,kornia,gst,faer,nalgebra,glam,debug_pane,bincode,log-level-debug"
WINDOWS_BASE_FEATURES := "mock,image,kornia,python,gst,faer,nalgebra,glam,debug_pane,bincode"
export ROOT := `git rev-parse --show-toplevel`
EMBEDDED_EXCLUDES := shell('python3 $1/support/ci/embedded_crates.py excludes', ROOT)
PREK_FMT_FIX_HOOKS := "trailing-whitespace mixed-line-ending"
PREK_FMT_CHECK_HOOKS := "trailing-whitespace check-merge-conflict detect-private-key check-case-conflict check-added-large-files check-yaml check-json check-xml check-symlinks mixed-line-ending"
# Default to the local PR-check workflow.
default:
just pr-check
# Local PR pipeline: format, lint, then tests.
pr-check:
just fmt
just lint
just test
# Formatting, typo, and clippy checks.
lint:
just fmt-check
just typos
just clippy-std
just clippy-nostd
# Formatting and CI-aligned file-hygiene check only
fmt-check: check-format-tools
@cargo +stable fmt --all -- --check
@git ls-files -z '*.toml' | xargs -0 -r env RUST_LOG=warn taplo format --check
@bash -lc 'set -euo pipefail; changed=(); while IFS= read -r -d "" f; do tmp=$(mktemp); cp "$f" "$tmp"; fmtron --input "$tmp" >/dev/null; if ! cmp -s "$f" "$tmp"; then changed+=("$f"); fi; rm -f "$tmp"; done < <(git ls-files -z "*.ron" ":!examples/modular_config_example/motors.ron"); if ((${#changed[@]})); then printf "RON formatting check failed:\n"; printf "%s\n" "${changed[@]}"; exit 1; fi'
@rg --files -g '*.ron.bak' | xargs rm -f
@prek run --all-files {{PREK_FMT_CHECK_HOOKS}}
# Apply formatting plus auto-fixable CI hygiene hooks
fmt: check-format-tools
@cargo +stable fmt --all
@git ls-files -z '*.toml' | xargs -0 -r env RUST_LOG=warn taplo format >/dev/null
@git ls-files -z '*.ron' ':!examples/modular_config_example/motors.ron' | xargs -0 -r -n 1 fmtron --input>/dev/null
@rg --files -g '*.ron.bak' | xargs rm -f
@bash -lc 'set -euo pipefail; prek run --all-files {{PREK_FMT_FIX_HOOKS}} || prek run --all-files {{PREK_FMT_FIX_HOOKS}}'
# Ensure the tools needed by fmt/fmt-check are installed.
check-format-tools:
#!/usr/bin/env bash
set -euo pipefail
missing=0
if ! command -v taplo >/dev/null 2>&1; then
echo "Missing taplo (taplo-cli). Install with: cargo install --locked taplo-cli"
missing=1
fi
if ! command -v fmtron >/dev/null 2>&1; then
echo "Missing fmtron. Install with: cargo install --locked fmtron"
missing=1
fi
if ! command -v prek >/dev/null 2>&1; then
echo "Missing prek. Install with: cargo install --locked prek"
missing=1
fi
if ! command -v rg > /dev/null 2>&1; then
echo "Missing rg. Install with: cargo install --locked rg"
missing=1
fi
if [[ "$missing" -ne 0 ]]; then
exit 1
fi
# Typo check only
typos:
typos -c .config/_typos.toml
# Std clippy checks aligned with reusable unit-test workflow defaults.
clippy-std:
#!/usr/bin/env bash
set -euo pipefail
os="$(uname -s || true)"
features="{{BASE_FEATURES}}"
case "$os" in
Linux*) features="{{BASE_FEATURES}},python" ;;
Darwin*) features="{{BASE_FEATURES}},python" ;;
MINGW*|MSYS*|CYGWIN*|Windows_NT) features="{{WINDOWS_BASE_FEATURES}}" ;;
*) features="{{BASE_FEATURES}}" ;;
esac
features_flag="--features $features"
embedded_excludes="{{EMBEDDED_EXCLUDES}}"
cargo +stable clippy --workspace --all-targets $embedded_excludes -- --deny warnings
cargo +stable clippy --workspace --all-targets $features_flag $embedded_excludes -- --deny warnings
# Run the Unit-Tests job locally via act (debug/ubuntu matrix).
ci:
act -W .github/workflows/general.yml -j Unit-Tests --matrix os:ubuntu-latest --matrix mode:debug -P ubuntu-latest=ghcr.io/catthehacker/ubuntu:act-latest
# Host target detection for cross-platform logreader builds
host_target := `rustc +stable -vV | sed -n 's/host: //p'`
# no_std/embedded clippy checks mirroring the embedded workflow.
clippy-nostd:
cargo +stable clippy --no-default-features
python3 support/ci/embedded_crates.py run --action clippy
cd examples/cu_rp2350_skeleton && cargo +stable clippy --target thumbv8m.main-none-eabihf --bin cu-blinky --features firmware
cd examples/cu_rp2350_skeleton && cargo +stable clippy --no-default-features --features host --bins --target={{host_target}}
# Run std and no_std unit tests.
test:
cargo +stable nextest run --all-targets --workspace {{EMBEDDED_EXCLUDES}}
cargo +stable nextest run --no-default-features
# Run the no_std/embedded CI flow locally.
nostd-ci:
just fmt-check
just typos
cargo +stable build --no-default-features
cargo +stable nextest run --no-default-features
python3 support/ci/embedded_crates.py run --action clippy
python3 support/ci/embedded_crates.py run --action build
cd examples/cu_rp2350_skeleton && cargo +stable clippy --target thumbv8m.main-none-eabihf --bin cu-blinky --features firmware
cd examples/cu_rp2350_skeleton && cargo +stable clippy --no-default-features --features host --bins --target={{host_target}}
cd examples/cu_rp2350_skeleton && cargo +stable build-arm
cd examples/cu_rp2350_skeleton && cargo +stable build --target={{host_target}} --no-default-features --features host --bin blinky-logreader
# Std-specific CI flow (local, CI-aligned). Use mode=release or mode=cuda-release as needed.
std-ci mode="debug":
#!/usr/bin/env bash
set -euo pipefail
just fmt-check
just typos
mode="{{mode}}"
release_flag=""
if [[ "$mode" == "release" || "$mode" == "cuda-release" ]]; then
release_flag="--release"
fi
os="$(uname -s || true)"
features="{{BASE_FEATURES}}"
case "$os" in
Linux*) features="{{BASE_FEATURES}},python" ;;
Darwin*) features="{{BASE_FEATURES}},python" ;;
MINGW*|MSYS*|CYGWIN*|Windows_NT) features="{{WINDOWS_BASE_FEATURES}}" ;;
*) features="{{BASE_FEATURES}}" ;;
esac
if [[ "$mode" == "cuda-release" ]]; then
features="${features},cuda"
fi
features_flag="--features $features"
embedded_excludes="{{EMBEDDED_EXCLUDES}}"
cargo +stable clippy $release_flag --workspace --all-targets $embedded_excludes -- --deny warnings
cargo +stable clippy $release_flag --workspace --all-targets $features_flag $embedded_excludes -- --deny warnings
cargo +stable build $release_flag --workspace --all-targets $features_flag $embedded_excludes
if [[ "$mode" == "debug" ]]; then
cargo +stable test --doc --workspace $embedded_excludes --quiet
fi
cargo +stable nextest run $release_flag --all-targets --workspace $embedded_excludes
cargo +stable nextest run $release_flag --all-targets --workspace $features_flag $embedded_excludes
RAYON_NUM_THREADS=1 COPPER_DETERMINISM_ITERS=256 COPPER_DETERMINISM_DT_TICKS=1000 \
cargo +stable test $release_flag -p cu-caterpillar --features determinism_ci \
-- determinism_record_and_resim --test-threads=1
if [[ "$mode" == "debug" ]]; then
if ! cargo +stable generate --version >/dev/null 2>&1; then
cargo +stable install cargo-generate
fi
(
cd templates
rm -rf test_project test_workspace
cargo +stable generate -p cu_project --name test_project --destination . -d copper_source=local -d copper_root_path=../.. --silent
cargo +stable generate -p cu_full --name test_workspace --destination . -d copper_source=local -d copper_root_path=../.. --silent
)
(
cd templates/test_project
cargo +stable build
)
(
cd templates/test_workspace
cargo +stable build
)
fi
# Proc-macro expansion helpers (cargo-expand).
check-expand:
#!/usr/bin/env bash
set -euo pipefail
if ! cargo +stable expand --version >/dev/null 2>&1; then
echo "Missing cargo-expand. Install with: cargo install cargo-expand"
exit 1
fi
# Inspect expanded output of cu29-deriva in the target
expand-runtime pkg bin features="": check-expand
#!/usr/bin/env bash
# Usage: just expand-runtime pkg=<crate> bin=<bin> [features=feat1,feat2]
set -euo pipefail
features_flag=""
if [[ -n "{{features}}" ]]; then
features_flag="--features {{features}}"
fi
cargo +stable expand -p "{{pkg}}" --bin "{{bin}}" $features_flag
# expand macro of cu29-soa-derive test target
expand-soa test="proctest": check-expand
# Usage: just expand-soa [test=proctest]
cargo +stable expand -p cu29-soa-derive --test "{{test}}"
# Run RTSan on a single app (defaults to cu-caterpillar).
# RTSan reports violations to stderr; tweak RTSAN_OPTIONS if you need to keep running.
rtsan-smoke pkg="cu-caterpillar" bin="cu-caterpillar" args="" options="halt_on_error=false":
#!/usr/bin/env bash
set -euo pipefail
RTSAN_ENABLE=1 RTSAN_OPTIONS="{{options}}" \
cargo run --profile screaming -p "{{pkg}}" --features rtsan --bin "{{bin}}" -- {{args}}
# Project-specific helpers now live in per-directory justfiles under examples/, components/, and support/.
# Build and open the generated wiki + API docs locally.
docs:
#!/usr/bin/env bash
set -euo pipefail
if ! command -v mkdocs >/dev/null; then
echo "mkdocs not found. Install it with: python3 -m pip install --upgrade pip mkdocs" >&2
exit 1
fi
RUSTDOCFLAGS="--enable-index-page -Zunstable-options" cargo +nightly doc --no-deps
python3 support/ci/wiki_site.py
mkdocs build -f build/wiki/mkdocs.yml
mkdir -p build/wiki/site/api
cp -R target/doc/* build/wiki/site/api/
site_path="build/wiki/site/index.html"
if [[ "$(uname -s)" == "Darwin" ]]; then
open "$site_path"
elif command -v xdg-open >/dev/null; then
xdg-open "$site_path"
elif command -v python3 >/dev/null; then
python3 -m webbrowser "file://${PWD}/${site_path}"
else
echo "Open ${site_path} in your browser."
fi
# Partition/format an SD card for Cu29 logging (destroys data).
mkpartition dev:
#!/usr/bin/env bash
set -euo pipefail
DEV="{{dev}}"
[[ -b "$DEV" ]] || { echo "not a block device: $DEV"; exit 1; }
for t in sgdisk mkfs.vfat lsblk wipefs udevadm; do
command -v "$t" >/dev/null || { echo "missing tool: $t"; exit 1; }
done
read -r -p "ERASE ALL DATA on $DEV? type 'YES' to continue: " ans
[[ "$ans" == "YES" ]] || { echo "aborted"; exit 1; }
lsblk -ln "$DEV" -o NAME,MOUNTPOINTS | while read -r name mp; do
[[ -n "${mp:-}" ]] && sudo umount -f "/dev/$name" || true
done
sudo wipefs -a "$DEV" || true
sudo sgdisk --zap-all "$DEV"
CU29_GUID="29A2E0C9-0000-4C75-9229-000000000029"
sudo sgdisk -og "$DEV"
sudo sgdisk \
-n1:1MiB:+1MiB -t1:0700 -c1:"COPPERCFG" \
-n2:0:0 -t2:${CU29_GUID} -c2:"Cu29" \
"$DEV"
sudo partprobe "$DEV" || true
sudo udevadm settle || true
sleep 0.5
if [[ "$DEV" =~ [0-9]$ ]]; then P1="${DEV}p1"; P2="${DEV}p2"; else P1="${DEV}1"; P2="${DEV}2"; fi
[[ -b "$P1" && -b "$P2" ]] || { echo "partition nodes not found: $P1 $P2"; exit 1; }
sudo mkfs.vfat -F 12 -n COPPERCFG "$P1"
mnt=$(mktemp -d)
trap 'sudo umount "$mnt" 2>/dev/null || true; rmdir "$mnt" 2>/dev/null || true' EXIT
sudo mount "$P1" "$mnt"
sudo tee "$mnt/README-COPPER.txt" >/dev/null <<-'TXT'
This SD card uses Copper (Cu29) raw binary logging.
Partition layout (GPT):
- Partition 1 (FAT12, label COPPERCFG): configuration + this notice
- Partition 2 (type GUID 29A2E0C9-0000-4C75-9229-000000000029, label Cu29): Copper raw log storage
To read logs, use the Copper log reader.
Do NOT format or mount partition 2 — it is not a filesystem.
TXT
sync
sudo umount "$mnt"
rmdir "$mnt"
trap - EXIT
lsblk -o NAME,SIZE,TYPE,FSTYPE,PTTYPE,PARTLABEL,PARTTYPE,LABEL "$DEV"
echo "Done. Copper raw partition is $P2 (GPT type ${CU29_GUID}, PARTLABEL=Cu29)."
# Extract the Cu29 raw log partition into a .copper file.
extract-log dev out="logs/embedded_0.copper":
#!/usr/bin/env bash
set -euo pipefail
DEV="{{dev}}"
OUT="{{out}}"
invocation_dir="{{invocation_directory()}}"
[[ -b "$DEV" ]] || { echo "not a block device: $DEV"; exit 1; }
for t in lsblk dd; do
command -v "$t" >/dev/null || { echo "missing tool: $t"; exit 1; }
done
CU29_GUID="29A2E0C9-0000-4C75-9229-000000000029"
dev_type="$(lsblk -no TYPE "$DEV" 2>/dev/null | head -n1 || true)"
PART="$DEV"
if [[ "$dev_type" == "disk" ]]; then
PART="$(lsblk -lnpo NAME,PARTLABEL,PARTTYPE "$DEV" | awk -v guid="$CU29_GUID" '($2=="Cu29") || (toupper($3)==toupper(guid)) {print $1; exit}')"
[[ -n "${PART:-}" ]] || { echo "Cu29 partition not found on $DEV"; exit 1; }
fi
if [[ "$dev_type" == "part" ]]; then
part_label="$(lsblk -no PARTLABEL "$PART" 2>/dev/null | head -n1 || true)"
part_type="$(lsblk -no PARTTYPE "$PART" 2>/dev/null | head -n1 || true)"
part_label="${part_label:-}"
part_type="${part_type:-}"
if [[ "$part_label" != "Cu29" && "${part_type^^}" != "${CU29_GUID}" ]]; then
echo "Warning: $PART does not look like a Cu29 partition (label=$part_label type=$part_type)" >&2
fi
fi
if [[ "$OUT" != /* ]]; then
OUT="${invocation_dir}/${OUT}"
fi
echo "Reading Cu29 partition $PART -> $OUT"
sudo dd if="$PART" of="$OUT" bs=4M status=progress conv=fsync
# Render copperconfig.ron from the current working directory.
dag mission="":
#!/usr/bin/env bash
set -euo pipefail
invocation_dir="{{invocation_directory()}}"
cfg_path="${invocation_dir}/copperconfig.ron"
if [[ ! -f "$cfg_path" ]]; then
echo "No copperconfig.ron found in ${invocation_dir}" >&2
exit 1
fi
cd "{{ROOT}}"
mission_value="{{mission}}"
if [[ -n "$mission_value" ]]; then
cargo run -p cu29-runtime --bin cu29-rendercfg -- --mission "$mission_value" --open "$cfg_path"
else
cargo run -p cu29-runtime --bin cu29-rendercfg -- --open "$cfg_path"
fi
# Helpers for managing git worktrees for different branches.
wt branch:
#!/usr/bin/env bash
set -euo pipefail
name="$(basename "{{branch}}")"
dir="$(realpath ../copper-rs.${name})"
echo "Adding worktree for branch '{{branch}}' at ${dir}"
if [[ -e "${dir}" ]]; then
echo "Worktree already exists at ${dir}"
elif git show-ref --verify --quiet "refs/heads/{{branch}}"; then
git worktree add "${dir}" "{{branch}}"
elif git show-ref --verify --quiet "refs/remotes/origin/{{branch}}"; then
git worktree add -b "{{branch}}" "${dir}" "origin/{{branch}}"
else
git worktree add -b "{{branch}}" "${dir}"
fi
if [[ -n "${ZELLIJ:-}" ]]; then
zellij action new-tab --name "${name}"
zellij action write-chars "cd ${dir};reset"
zellij action write 13
fi