Repository navigation
Expand file tree
/
Copy pathMakefile
More file actions
255 lines (224 loc) · 12.3 KB
/
Copy pathMakefile
File metadata and controls
255 lines (224 loc) · 12.3 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
# exav: build, test, and the daily prebuilt-database pipeline.
#
# `make exavdb` is the intended production flow: fetch the ClamAV signatures with
# Cisco's own updater, then compile a prebuilt `.exavdb` that CLI instances load
# directly (a near-instant, low-memory cold start). Building the full main+daily
# set needs about 2 GB of RAM.
CARGO ?= cargo
EXAV ?= ./target/release/exav
DBDIR ?= exav-db
EXAVDB ?= exav.exavdb
.DEFAULT_GOAL := build
.PHONY: build release test test-native test-yara-diff test-wasm test-js test-viewer test-www test-helm wasm-sizes lint fmt msrv av-audit miri publish-check publish fuzz db exavdb cache daily clean www-dev www-build help
## build: compile the release binary
build release:
$(CARGO) build --release
## test: EVERY test exav owns: native feature matrix, wasm32, the WASM bindings'
## JS suites, the viewer's and the docs build. The one command to run
## before pushing. Needs `wasmtime` (test-wasm), wasm-bindgen-cli
## (test-viewer) and node (test-js, test-viewer, test-www); the
## sub-targets below run each part alone.
##
## Excludes fuzzing and the two DIFFERENTIAL harnesses, which check exav
## against another engine rather than against its own contract:
## `scripts/difftest.sh` and `make test-yara-diff`.
##
## For the fast inner loop use `cargo test` directly, but note it is a
## SUBSET: feature-gated test files compile to zero tests without their
## feature and report green having checked nothing.
test:
$(MAKE) test-native
$(MAKE) test-wasm
$(MAKE) test-js
$(MAKE) test-viewer
$(MAKE) test-www
## test-native: the full native test matrix (every feature pass CI runs, no wasm).
## Mirrors the `test` job in .github/workflows/ci.yml; keep in sync.
test-native:
$(CARGO) test --workspace
# The CLI as shipped: a `--workspace` build unifies features across crates,
# so it can hide an exav-core feature that `exav` itself does not forward.
$(CARGO) test -p exav --features http
$(CARGO) test -p exav-core --features http
$(CARGO) test -p exav-unpack --features checksums
$(CARGO) test -p exav-unpack --no-default-features --features all-formats
$(CARGO) test -p exav-core --features unstable-internals
# Minimal build: compiles the `cfg(not(feature = ...))` fallbacks every other
# pass hides: the paths that must report unsupported rather than clean.
$(CARGO) test -p exav-core --no-default-features
$(CARGO) test -p exav-unpack --no-default-features
$(CARGO) test -p exav-imagehash --no-default-features
# Each format feature on its own: a whole feature set can hide a format
# that only compiles because another one brought its dependency in.
scripts/check-features.sh
# ALZ and EGG carry their own bzip2 and LZMA decoders, which must work
# without the `bzip2` and `lzip` features.
$(CARGO) test -p exav-unpack --no-default-features --features alz,egg --test all -- alz egg
# Crash containment, which only runs when a decoder can be asked to fail.
# Without this pass the tests that check it skip themselves and the whole
# question goes unasked. A scanner that dies on crafted input and exits 0
# is indistinguishable, to a pipeline reading `$$?`, from a clean scan.
$(CARGO) test -p exav-unpack --features testing-faults panic_containment
$(CARGO) test -p exav --features testing-faults --test decoder_crash
# DWG and DXF, behind exav-render's `dwg` feature, which no other crate of
# the workspace turns on; and alone, as @exav/viewer's DWG module builds it.
$(CARGO) test -p exav-render --features dwg
$(CARGO) test -p exav-render --no-default-features --features dwg
# IFC and STL, behind `ifc` and `stl`, as @exav/viewer's model module
# builds them.
$(CARGO) test -p exav-render --no-default-features --features ifc,stl
## test-yara-diff: the yara-x A/B differential harness. Compiles the SAME rules
## with both engines and asserts equal matching-rule sets. NOT
## part of `make test`, for the same reason the clamav harness
## (scripts/difftest.sh) isn't: a differential test
## measures exav against another engine, so it can go red because
## the OTHER engine changed. That is a research signal, not a
## merge gate, and it does not belong on the path a contributor
## runs before pushing.
##
## yara-x is invoked as the `yr` BINARY, not linked as a crate.
## As a dependency it drags in ~83 extra crates, 21 of them
## cranelift/wasmtime; exav's own build contains no JIT backend
## at all, and a crate in the graph can reach a shipped artifact
## in a way a program on PATH cannot.
##
## Install the oracle with `cargo install yara-x-cli`, or point
## EXAV_DEBUG_YR_BIN at a build. WITHOUT it the tests SKIP and report
## green having checked nothing, so read the output, not just
## the exit code. Run it when you touch the YARA engine.
test-yara-diff:
$(CARGO) test -p exav-core --test yara_difftest --test yara_coverage_difftest -- --nocapture
## test-js: the exav-unpack-wasm JavaScript suites: vitest units plus the
## playwright browser e2e against a freshly built pkg/. This is the
## published npm package's public API; no cargo test reaches it.
test-js:
./scripts/test-js.sh
## test-viewer: @exav/viewer: its wasm modules built from the current source,
## vitest units (pdf.js's image decoders against the package's
## among them), then the package built and checked as `npm publish`
## would upload it, the sink and wasm-import gates, and the demo
## built for production and driven in headless Chromium under its
## Content-Security-Policy, its sandboxed frame in Chromium,
## Firefox and WebKit. The
## archive plugin's peer, exav-unpack-wasm's pkg/, is rebuilt from
## the current source too. Needs wasm-bindgen-cli at the version
## crates/exav-viewer pins.
test-viewer:
./scripts/test-viewer.sh
## test-www: type-check and build the exav.org docs site (broken links, bad
## frontmatter, sidebar entries pointing at deleted pages).
test-www:
./scripts/test-www.sh
## test-helm: render-check the Helm chart (render guards, hardening settings,
## packaging). Needs `helm` on PATH, no cluster. CI runs `ct lint`
## in addition. See scripts/test-helm.sh.
test-helm:
./scripts/test-helm.sh
## test-wasm: run the extractor unit tests on 32-bit wasm32-wasip1 under wasmtime
## (catches integer/capacity-overflow bugs a 64-bit host hides).
## Needs `wasmtime` on PATH (or $$WASMTIME). See scripts/test-wasm.sh.
test-wasm:
./scripts/test-wasm.sh
## wasm-sizes: per-format exav-unpack WASM size table (how big is a min extractor)
wasm-sizes:
./scripts/wasm-format-sizes.sh
## lint: the clippy passes and rustfmt check CI runs (.github/workflows/ci.yml)
lint:
$(CARGO) fmt --all --check
$(CARGO) clippy --all-targets --features exav-core/http -- -D warnings
$(CARGO) clippy -p exav-core --all-targets --features unstable-internals -- -D warnings
$(CARGO) clippy -p exav-render --all-targets --features dwg -- -D warnings
$(CARGO) clippy -p exav-render --all-targets --no-default-features --features ifc,stl -- -D warnings
## fmt: format the code
fmt:
$(CARGO) fmt
## msrv: build the workspace on the `rust-version` floor declared in Cargo.toml.
## CI runs this, so a version nobody verifies drifts upward the
## first time someone uses a newer feature, silently breaking anyone who
## pinned the toolchain we promised.
## `rustup run` rather than `cargo +VERSION`: the `+toolchain` prefix is a
## rustup *shim* feature, so it fails with "no such command" whenever
## $(CARGO) is a real cargo binary instead of the shim.
msrv:
@v=$$(sed -n 's/^rust-version = "\(.*\)"/\1/p' Cargo.toml | head -1); \
rustup toolchain install $$v --profile minimal >/dev/null 2>&1 || true; \
echo "checking MSRV $$v"; rustup run $$v cargo check --workspace --all-targets
## av-audit: scan the tracked tree with a real engine and signature set, to catch
## a committed fixture that other people's scanners will detect. Run it
## when fixtures change, not on every release: it needs `clamscan` and
## a signature directory ($(DBDIR), via `make db`), neither of which is
## present on most machines, so as a release gate it would skip
## exactly where it mattered. An independent engine on purpose: asking
## exav whether exav's own tree is clean answers the wrong question.
av-audit:
@command -v clamscan >/dev/null 2>&1 || \
{ echo "av-audit needs clamscan (apt install clamav / brew install clamav)"; exit 1; }
@[ -d $(DBDIR) ] || { echo "av-audit needs $(DBDIR); run 'make db'"; exit 1; }
@echo "scanning $$(git ls-files | wc -l | tr -d ' ') tracked files with $(DBDIR)"
@hits=$$(git ls-files -z | xargs -0 clamscan -d $(DBDIR) --no-summary 2>/dev/null \
| grep -v ': OK$$' || true); \
if [ -n "$$hits" ]; then echo "$$hits"; \
echo "-> mask these (see crates/exav-unpack/tests/fixtures/README.md)"; exit 1; \
fi; \
echo "no detections"
## miri: run the container-walking tests of exav-unpack under Miri, which checks
## the `unsafe` inside dependencies (memchr, the compression and crypto
## crates) along real code paths. Needs a nightly toolchain with the
## component: `rustup toolchain install nightly --component miri`.
## A subset, chosen by test-name filter in MIRI_TESTS: Miri runs code
## orders of magnitude slower, and the decoder round-trip tests alone take
## hours. Its own target dir, so it never invalidates the normal build.
MIRI_TESTS ?= formats::zip formats::cpio formats::tar formats::iso formats::partition formats::cab
miri:
CARGO_TARGET_DIR=target/miri rustup run nightly cargo miri test -p exav-unpack --lib -- $(MIRI_TESTS)
## fuzz: smoke-build the fuzz targets
fuzz:
cd fuzz && $(CARGO) build
## db: download the ClamAV signature DB into $(DBDIR) with Cisco's cvdupdate
db:
@command -v cvd >/dev/null 2>&1 || pip3 install --user cvdupdate || \
pip3 install --user --break-system-packages cvdupdate
cvd config set --dbdir $(DBDIR)
cvd update
## exavdb: download fresh signatures and compile the prebuilt database ($(EXAVDB))
exavdb: build db
$(EXAV) -d $(DBDIR) --build-db $(EXAVDB)
## cache: deprecated alias for `make exavdb`
cache: exavdb
## daily: alias for `make exavdb`; run from cron to refresh the distributed database
daily: exavdb
## clean: remove build artifacts (keeps $(DBDIR) and $(EXAVDB))
clean:
$(CARGO) clean
## www-dev: run the exav.org docs site (Astro Starlight) dev server (www/)
www-dev:
cd www && ([ -d node_modules ] || npm install) && npm run dev
## www-build: build the static exav.org docs site into www/dist
www-build:
cd www && ([ -d node_modules ] || npm install) && npm run build
# Both delegate to scripts/release.sh, which owns the publish order and the
# pre-publish gate. One list, in one place: the order is the crate graph and a
# crate cannot go up before the crates it depends on exist on the registry, so a
# list that drifts fails partway and leaves some crates at the new version and
# some not, and a published version can be yanked but never replaced or reused,
# so a botched run burns that version number permanently.
## publish-check: run the pre-publish gate and dry-run every crate, publishing nothing
publish-check:
./scripts/release.sh --dry-run
## publish: gate, stop for review, then publish every crate in dependency order
publish:
./scripts/release.sh
# The npm package is published from the CRATE directory, never from `pkg/`.
# `wasm-pack` writes its own `package.json` into `pkg/`, so running `npm publish`
# in there ships that one instead: different `files`, different `main`, and none
# of the metadata. Only the tracked manifest describes what should go out, and
# this target is what pins the choice.
## npm-publish-check: pack the npm bindings without publishing, and list contents
npm-publish-check:
cd crates/exav-unpack-wasm && npm pack --dry-run
## npm-publish: build and publish the WASM bindings to npm
npm-publish:
cd crates/exav-unpack-wasm && npm publish
## help: list targets
help:
@grep -E '^## ' $(MAKEFILE_LIST) | sed 's/^## / /'