# 010 — Driver & CLI - **Status:** Draft - **Normative language:** `MUST`, `MUST NOT`, `SHOULD`, `SHOULD NOT`, and `MAY` are to be interpreted as described in RFC 2119. ## 1. Purpose libVCT splits orchestration across two layers. The driver (`vct.driver`) is the library-level orchestrator: it takes emitted C translation units, invokes the system C compiler, and collects object files. The CLI (`vct.cli`) is a thin wrapper that parses command-line flags into a `Config`, drives the whole pipeline, formats diagnostics, and sets exit codes. The CLI holds no optimizer state and adds no compilation logic of its own. ## 2. Scope This file specifies the driver/CLI role split, the pipeline order, the full flag surface, the exact C compiler invocation, compiler discovery and probing, error handling, determinism, `-mangled` mode, and object-file emission and merging. The compiler-facing backends are specified in [008 — C Backend](008-c-backend.md) and [009 — LLVM Backend](009-llvm-backend.md). Diagnostics, remarks, and exit codes are specified in [011 — Diagnostics](011-diagnostics.md). ## 3. Definitions | Term | Meaning | |---|---| | `Config` | One struct holding opt level, target, budgets, pass toggles, warning policy, compiler selection, and mode. | | TU | Translation unit: one emitted C file. | | `cc` | The discovered system C compiler. | | APE | Actually Portable Executable, the output of cosmopolitan tooling. | | Fat LTO object | An object that carries both native machine code and LTO bitcode. | | Response file | A file listing arguments for a linker or compiler, referenced by `@file`. | ## 4. Model `vct.cli` is GC-allocated and cold-path only. It converts `argv` into a `Config`, runs the pipeline, forwards every diagnostic to the configured consumer, and returns an exit code. `vct.driver` owns process invocation. Any embedder that has already constructed a `Config` can call the driver directly and skip the CLI entirely. The driver also owns the `-llvm` path, which returns textual LLVM IR and never touches `cc`, and the `-mangled` path, which switches to the cosmopolitan toolchain. ## 5. Normative requirements ### 5.1 Role split **R1.** `vct.cli` MUST be a thin wrapper. It MUST NOT contain optimization, lowering, or backend logic, and it MUST NOT hold optimizer state. **R2.** `vct.cli` MUST be a pure function from `argv` to `Config` plus pipeline invocation. The library entry point MUST accept a `Config`; programmatic callers MUST be able to bypass the CLI. **R3.** `vct.driver` MUST own all invocation of the system C compiler. **R4.** `vct.cli` MUST be GC-allocated and MUST be usable on the cold path only. ### 5.2 Pipeline **R5.** The default pipeline order MUST be: read input, then HIR optimization if enabled, then lowering, then VIR optimization if enabled, then the C backend, then the driver. ``` read input -> (HIR opt if enabled) -> lower -> (VIR opt if enabled) -> backend.c -> driver -> .o ``` **R6.** `-S` MUST stop after C emission and MUST NOT invoke `cc`. **R7.** `-emit-llvm` and `-llvm` MUST stop after LLVM IR emission and MUST NOT invoke `cc`. ### 5.3 Flag surface **R8.** The CLI MUST accept the flags listed in Table 1. **Table 1. v1 flag surface** | Group | Flags | Meaning | |---|---|---| | Optimize | `-O0` `-O1` `-O2` `-O3` `-Ofast` `-Oz` | Optimization level. | | Target | `-march=`, `-mcpu=`, `-target ` | Target selection; `-march`/`-mcpu` forward to `cc` as cflags. | | Modes | `-S`, `-emit-llvm`, `-llvm`, `-mangled` | Stop point or alternate mode. | | Toolchain | `-cc=`, `-cflags="..."`, `-j`, `-save-temps` | Compiler selection, extra flags, parallelism, temp retention. | | LTO | `-flto[=full\|thin]`, `-ffat-lto-objects` | Link-time optimization control. | | Debug | `-g`, `--dump-hir`, `--dump-vir`, `--verify`, `--time-passes`, `--stats` | Debug output and instrumentation. | | Output | `-o ` | Output path. | | Warnings | `-Wall`, `-Werror`, `-Wextra`, `-Wno-error[=]`, `-w` | Warning policy. | | Diagnostics | `--remarks`, `--diagnostics=json` | Remark and diagnostic channel selection. | | Pass toggles | `-f`, `-fno-` | Enable or disable an individual pass. | **R9.** `-Wall`, `-Werror`, and `-Wextra` MUST be on by default. A bare `-Wno-error` MUST disable every promotion, `-Wno-error=` MUST disable the promotion of that category, and `-w` MUST silence warnings. **R10.** `-Werror` MUST apply to the C source that libVCT generates, not only to frontend input. **R11.** Every pass MUST be exposed as both `-f` and `-fno-`. ### 5.4 C compiler invocation **R12.** For each emitted TU, the driver MUST invoke the compiler as: ``` cc -std=c17 -c -o -Wall -Werror -Wextra ``` where `` is `-g` when debug is enabled, and `` is the LTO flag when LTO is requested. **R13.** The driver MUST run one compiler process per TU, with concurrency bounded by `-j`. **R14.** The driver MUST discover the compiler via the `$CC` environment variable first, then by searching `PATH`, unless `-cc=` forces a selection. **R15.** The driver MUST probe the discovered compiler's version and dialect exactly once per run. The probed dialect MUST drive the backend's choice of pragmas and builtins (see [008 — C Backend](008-c-backend.md)). **R16.** The driver MUST NOT pass `-march`/`-mcpu` values to `cc` that the probed compiler does not accept; it MUST diagnose an unsupported target value. ### 5.5 Error handling **R17.** The driver MUST capture the compiler's stderr. **R18.** The driver MUST use the `#line` directives emitted by the C backend (see [008 — C Backend](008-c-backend.md)) to map C compiler errors back to VIR and frontend source positions, then re-emit them through the diagnostics service (see [011 — Diagnostics](011-diagnostics.md)). **R19.** A compiler failure MUST produce a diagnostic and MUST cause a nonzero exit. **R20.** The driver MUST NOT discard compiler diagnostics silently. ### 5.6 Determinism **R21.** The driver MUST order TUs and flags deterministically. For a fixed `Config` and input, the sequence of compiler invocations and their argument order MUST be identical across runs and independent of thread count. **R22.** The driver MUST place temporary files under a GC-managed temporary directory. **R23.** The temporary directory MUST be cleaned up after the run unless `-save-temps` is given. ### 5.7 `-mangled` mode **R24.** `-mangled` MUST switch the toolchain to `cosmocc` and the cosmopolitan libc. **R25.** `-mangled` MUST produce an Actually Portable Executable. **R26.** `-mangled` is the one mode in which libVCT links. In every other mode libVCT produces object files and leaves linking to the caller (see [000 — Overview](000-overview.md)). ### 5.8 Object emission and merging **R27.** In the default path, the driver MUST produce object files only. It MUST NOT link a final executable. **R28.** When a single `-o` path is requested and the module produced multiple per-function objects, the driver MUST merge them with a relocatable link (`ld -r -o .o ...`). **R29.** The driver MUST emit, for the caller, a recommended link line or response file listing the produced objects and any needed libraries. ## 6. Invariants - **I1.** A fixed `Config` and input produce byte-identical outputs and an identical sequence of compiler invocations. - **I2.** `vct.cli` holds no optimizer state. - **I3.** The `-llvm` path never spawns `cc`. - **I4.** The temporary directory is removed unless `-save-temps` is set. - **I5.** Flag assembly order is stable. - **I6.** Every captured compiler error is re-emitted through the diagnostics service. - **I7.** `-mangled` is the only mode that links. ## 7. Examples Default compile of a single source to an object: ``` vct -O2 -march=native -cc=clang -j8 -o out.o input.vir ``` Stop after emitting C, without invoking `cc`: ``` vct -O2 -S -o out.c input.vir ``` Emit textual LLVM IR instead of C: ``` vct -O3 -emit-llvm -target x86_64-unknown-linux-gnu -o out.ll input.vir ``` Produce a portable executable: ``` vct -O2 -mangled -o app.com input.vir ``` ## 8. Cross-references - [000 — Overview](000-overview.md) for determinism and the no-linking rule. - [001 — Architecture](001-architecture.md) for module boundaries. - [002 — Traits](002-traits.md) for the trait vocabulary. - [007 — VIR Optimizer](007-vir-optimizer.md) for pass toggles and the pipeline. - [008 — C Backend](008-c-backend.md) for `#line` and compiler dialect use. - [009 — LLVM Backend](009-llvm-backend.md) for `-target` and the `-llvm` path. - [011 — Diagnostics](011-diagnostics.md) for diagnostics, remarks, and exit codes. - [013 — Build & Packaging](013-build-packaging.md) for `Config` and the C API.