CLI Reference
The wirespec compiler is invoked from the command line:
wirespec <command> [options]wirespec compile
Compiles one or more .wspec files to the target language.
Usage:
wirespec compile <file> [options]Options:
| Flag | Description |
|---|---|
-o, --output DIR | Output directory for generated files (default: build) |
-t, --target c|rust | Target language (default: c). Use rust to generate a .rs file instead of .h/.c. |
-I, --include-path DIR | Additional search path for resolving imports (repeatable) |
--recursive | Compile all transitive dependencies discovered via imports |
--fuzz | Generate a libFuzzer harness alongside the normal output (C target only) |
Examples:
Compile a single file:
wirespec compile examples/quic/varint.wspec -o build/Compile with import resolution across a directory tree:
wirespec compile examples/quic/frames.wspec -I examples/ --recursive -o build/Compile to Rust:
wirespec compile examples/quic/varint.wspec -t rust -o build/Compile and generate a libFuzzer harness:
wirespec compile examples/quic/frames.wspec -t c --fuzz -o build/Output files:
For a module named quic.frames compiled to C (the default), the following files are emitted in the output directory:
| File | Contents |
|---|---|
quic_frames.h | Struct/enum type declarations, function prototypes |
quic_frames.c | Parse, serialize, and serialized_len implementations |
fuzz_quic_frames.c | libFuzzer harness (only with --fuzz) |
When --recursive is used, each transitive dependency gets its own pair of .h/.c files.
For -t rust, a single .rs file is emitted:
| File | Contents |
|---|---|
quic_varint.rs | Rust structs, parse, serialize, and serialized_len implementations |
The generated Rust code uses the wirespec-rt crate for Cursor, Writer, and Error types.
wirespec check
Type-checks a .wspec file without generating output. Useful for CI and editor integration.
Usage:
wirespec check <file>The check command only takes an input file — no -I or other flags are supported.
Example:
wirespec check examples/quic/frames.wspecOn success, prints ok: <path> to stderr and exits with code 0. On failure, prints diagnostics to stderr and exits non-zero:
error: undefined type 'VarItn'
--> examples/quic/frames.wspec:34:42
|
34 | frame QuicFrame = match frame_type: VarItn {
| ^^^^^^
= in frame 'QuicFrame'
hint: did you mean 'VarInt'?Fuzz Build Workflow
Generate and build a libFuzzer harness:
# Step 1: Compile with --fuzz
wirespec compile examples/quic/frames.wspec -t c --fuzz -o build/
# Step 2: Build the fuzzer with sanitizers
cd build
clang -fsanitize=fuzzer,address,undefined \
-o fuzz_frames \
quic_frames.c fuzz_quic_frames.c \
-I../runtime
# Step 3: Run a timed smoke pass
./fuzz_frames -max_total_time=10
# Step 4: Run against a seed corpus (if available)
./fuzz_frames fuzz/corpus/quic_frames/ -max_total_time=60The generated harness calls _parse() on arbitrary input and verifies that parse → serialize → parse round-trips produce identical results (when parse succeeds).
Import Search Path Resolution
When a .wspec file contains an import statement, the compiler searches for the imported module in the following order:
- The directory containing the importing file.
- Any directory specified with
-I/--include-path, in the order given.
Module quic.varint resolves to a file named quic/varint.wspec (or quic/varint.wspec) — dots become path separators — relative to each search root.
Example:
examples/
quic/
varint.wspec # module quic.varint
frames.wspec # import quic.varint.VarIntwirespec compile examples/quic/frames.wspec -I examples/ -o build/With -I examples/, the import quic.varint resolves to examples/quic/varint.wspec.
Exit Codes
| Code | Meaning |
|---|---|
0 | Success |
1 | Compile error (parse, type check, or codegen failure) |