# madc Usage — the CLI ```bash madc [options] [program-args...] ``` madc compiles C/C++-dialect source and, by default, JIT-executes it in process. The same invocation surface emits native objects, executables and shared libraries, renders C11 source, and drives multi-file projects. This page covers the command line; the language itself is documented under [`docs/language/`](language/overview.md). Run `madc --help` for the complete, always-current option list. ## Machine-readable capabilities Tooling can query the compiler without supplying a source file: ```bash madc --capabilities=json ``` The response is a versioned JSON manifest describing the compiler version and target, the accepted `--std=` C/C++ standards, the `-stdlib=` flavors this build serves (`input.stdlib_flavors` — a build host without libc++ builds a libstdc++-only madc), project-mode support, the execution and native-output modes, the CIR emission targets, the introspection surfaces, and the public `libmadc` / C API boundary. The advertised standards and emit targets are derived from the same sources the compiler enforces, so the manifest can never advertise a `--std=` the compiler rejects. A cross-built artifact reports `emit-only` and `jit: false` — the manifest describes that artifact, not the host that queried it. Unknown formats are rejected so a consumer never silently parses a schema it did not ask for. ## Running programs ```bash madc file.mad # compile + JIT-run madc file.mad arg1 arg2 # program args follow the source madc -E file.mad # preprocess only ``` A file whose first line is `#!/usr/bin/env madc` can be `chmod +x`'d and run directly. Top-level statements need no `main()` under the default dialect — madc synthesizes one (script mode). Standard library availability needs no setup: **everything in libc and the active C++ standard library — libstdc++ by default, libc++ under `-stdlib=libc++` — is available**. Include the normal headers and call; madc parses the real installed headers and resolves symbols against the real libraries. There is no curated "built-in function" list to learn. ```c #!/usr/bin/env madc #include #include using namespace std; cout << "hypot(3,4) = " << hypot(3.0, 4.0) << endl; ``` ## Language and preprocessor options | Option | Effect | |--------|--------| | `--std=` | `c89`…`c23`, `gnuNN`, `c++NN`, `gnu++NN`, or `madc` (the dialect; C++ keywords reserved). Without it the source's extension decides, as plain gcc / g++ do: `.c` / `.h` → `gnu17`, `.cpp` / `.cc` / `.cxx` (and the other C++ extensions) → `gnu++17`, `.mad` → `madc`; a source with no recognised extension (a shebang script, stdin) takes the `madc.ini` `std`, else `madc`. A `--project` TU without `-std=` follows the same rule. | | `-stdlib=libstdc++`\|`libc++` | C++ standard-library flavor (clang's spelling). Replaces the C++ include search list, as clang does. | | `-D[=value]` | define a macro | | `-I` | add an include search directory | | `-l` | bind a library (spelled for the target by the module map: `-lm` → `libm.so.6` / `libSystem.B.dylib` / `ucrtbase.dll`; bare names follow `lib.so` / `.dylib` / `.dll`). JIT: opened globally so its symbols resolve. AOT: a `DT_NEEDED` / load command / PE import. See [language/import.md](language/import.md). | | `--import=` | import the module `` ahead of the program, as if its source began with `import ;` (repeatable). With no source it only tries the import, so a launcher can test before it starts: exit 0, or the import error and exit **69** (no other failure of madc's uses it). | | `--module-path=` | search `` for the modules `import` names, after the program's own directory and before madc's module directory (`/lib/madc/modules`); repeatable. A module is `/.so` / `.dylib` / `.dll`. | | `--no-embedded-headers` | disable the baked-in headers; use real system headers only | | `--no-auto-load` | do not act on `import` / `#load` library bindings; link explicitly via `-l` | ## Multi-file projects Projects use the standard `compile_commands.json` (from CMake, `bear`, …): ```bash madc --project compile_commands.json # compile all TUs, link, run madc --project compile_commands.json -o app # emit one native executable madc file.json # .json input implies --project ``` madc never writes cache files beside your project. To skip recompiling on later runs, produce a real artifact explicitly: `-c` per-TU objects (madc runs `.o` files directly as a precompiled cache) or `-o` an AOT executable. madc's own manifest is a JSON object (the shape madcide reads and writes as `.prj.json` beside the launch file; `--project` takes it interchangeably with a `compile_commands.json` array): ```json { "tus": ["main.mad", {"file": "util.c", "std": "c89", "defines": ["NDEBUG"]}], "entry": "main", "output": "app", "kind": "console", "commands": [{"name": "Docs", "cmd": "make -C {project} docs"}] } ``` `tus` is required (a bare string is the file; an object carries `file`, `directory`, `defines`, `include_dirs`, `std`, `stdlib`); `kind` is `console` (the default) or `gui` — a gui program gets the Windows GUI subsystem when built (no console window at start) and, in madcide, runs in its own window; `commands` are the IDE's extra Build rows. Unknown keys pass through untouched. ## Native output (AOT) madc emits native artifacts itself — MIR assembles the ELF/Mach-O image directly, with no external compiler, assembler, or linker: ```bash madc -c file.mad # relocatable object (file.o) madc -o prog file.mad # native executable (PIE by default) madc -shared -o libx.so x.mad # shared object madc -r -o whole.o --project db.json # single whole-program object (ld -r style) madc prog.o # execute .o files as a precompiled cache ``` - `-static-libmadc` packs the madc runtime pieces the program needs into the emitted image, so it runs with no madc library installed (libc/libstdc++ stay dynamic). - An object another toolchain links names madc's runtime as a g++ object names libstdc++: add `-L/lib -lmadc_rt` to that link (a function with cleanups references `__madc_personality`; try/catch and VLAs reference the archive's other entries). - `-pie` / `-no-pie` select the image layout, gcc-style. - `-mwindows` / `-mconsole` (Windows) select the executable's subsystem, mingw-gcc-style: a windowed program allocates no console at start; a `--project` build takes the manifest's `kind` instead. A windowed program that also has console faces (a `--help`, a terminal mode) calls `madc::console_attach()` first: it attaches to the console of the process that started it and points the standard streams the parent left without a handle at it (a redirected stream stays redirected). A command prompt does not wait for a windowed program, so its prompt returns while the program runs. - Emitted executables otherwise locate `libmadc.so` via their `DT_RUNPATH`. ## Rendering and introspection ```bash madc --emit=c11 file.mad # render the program as portable C11 madc --emit=mc11 file.mad # the Mad-enhanced C11 serialization madc --dump-cir file.mad # dump the compiler's cir_node tree madc --dump-source file.mad # reconstruct full-fidelity source madc -dM file.mad # effective macro table (gcc -dM -E) ``` ## Frozen forests (compile once, run without parsing) Parsed state can be frozen into a container and reused — this is how the release binary ships its standard headers pre-parsed: ```bash madc --freeze=prog.frozen prog.mad # parse + translate, freeze (no run) madc --run-frozen=prog.frozen # thaw + run madc --freeze-run prog.mad # round-trip in one step madc --dump-forest=prog.frozen # inspect a container ``` Grove-backed system `#include`s bind from a discovered container by default (`--no-forest-bind` forces live parsing). Discovery order: the binary's own image, the libmadc image, `.forest` / `.forest` sidecars, `$MADC_FOREST`, then the `madc.ini` `forest` key. ## Diagnostics | Option | Effect | |--------|--------| | `-v`, `--verbose` | tokenizer / parser / lowering trace | | `-g` | debug info: gdb can break, step, and inspect the JIT'd program (forces `-O0`) | | `-w` | inhibit all warning messages (gcc `-w`); errors are unaffected | | `-fdiagnostics-color[=auto\|always\|never]`, `-fno-diagnostics-color` | when diagnostics are coloured (gcc's spelling). `auto`, the default, colours only a terminal (`TERM` set and not `dumb`; on Windows a console, switched to VT mode) and never when `NO_COLOR` is set — so `madc file.c 2> log` writes plain text; the bare flag is `always`. A host's captured stream (an embedding, an IDE pane, a test log) is no terminal. | | `--show-stats` | read/lex/parse/c2mir/execute timing and size stats on stderr | | `-O0` … `-O3` | JIT optimization level | ## Configuration file and environment Precedence: **CLI > environment > `madc.ini` > defaults.** The config search takes the first existing file of: `./madc.ini`, `$XDG_CONFIG_HOME/madc/madc.ini` (else `%APPDATA%\madc\madc.ini` on Windows, else `~/.config/madc/madc.ini`), then the system config dir. `--config=` names one explicitly; `--no-config` skips the search (hermetic builds). Recognized keys: `std` (for a source with no recognised extension — `--std` > the extension > `std` > `madc`), `stdlib`, `forest`, `include` (repeatable), `modules` (repeatable: a module to import, as `--import=` imports it — `modules = git`; the command line's `--import` modules import first, and a name both give imports once), `cpu-limit`, `mem-limit` — an unknown key is an error. | Variable | Effect | |----------|--------| | `MADC_CPU_LIMIT=off\|auto\|` | `RLIMIT_CPU` guard; default off, and `auto` is off too (madc runs the program, so no finite default is safe) | | `MADC_MEM_LIMIT=off\|auto\|` | address-space guard (`RLIMIT_AS`, a soft limit); default **off**; `auto` = 4096 MB + 128 MB per `--project` TU (the test runner asks for `auto`); a program that imports a GUI module (`madcwebview`) lifts it at run start; `0` = `off`. The same spellings work for the `madc.ini` keys `mem-limit` / `cpu-limit`. | | `MADC_FOREST=` | frozen forest container for the discovery chain | ## See also - [Language overview](language/overview.md) — the madc dialect: types, script mode, control flow, and the dialect extensions - [Supported C++ features](language/cpp-features.md) — what C++ works today - [Multi-language namespaces](language/overview.md#namespaces) — `php::`, `perl::`, `python::`, `ruby::`, `js::`, `rust::` - [Build and installation](build.md)