# M2make — build-order tutorial `M2make` is a small build front-end for the V3 `M2` compiler and for GNU Modula-2. Given a main source file, it follows `IMPORT`/`FROM` imports, topologically sorts the modules, and runs the compiler in the right order. ```sh M2make [-n] [-v] [-c m2|gm2] [-I dir] [-o out] [--m2bin path] [--shim path] [--extra path] [--m2flag flag] [--dialect pim|iso|gm2] [--separate] main.mod ``` ## Build The portable source is `tools/m2make/M2make.mod`; the OS bridge is `m2make_os.c`. From the repository root: ```sh cd tools/m2make ./build_m2.sh # dogfood build with the V3 M2 compiler ./build_gm2.sh # optional: build with GNU Modula-2 ``` Both produce a `M2make` binary; the dogfood binary is `tools/m2make/b_v3/M2make`. ## One-shot build (default) ```sh tools/m2make/b_v3/M2make \ --m2bin ./compiler/M2 \ --shim runtime/syslib/shim.c \ -o /tmp/prog prog.mod ``` For V3 this runs one M2 session over all `.def`/`.mod` files, then `qbe`, then `cc` with the runtime shim. It gates on M2’s `Parsed correctly` verdict. ## Separate-object build ```sh tools/m2make/b_v3/M2make --separate \ --m2bin ./compiler/M2 \ --shim runtime/syslib/shim.c \ --dialect iso \ -o /tmp/prog prog.mod ``` Each module is compiled with `M2 -c` against the ordered interfaces to `gen_ssa/.o`; the program object contains `main`, library objects contain only their code plus `_init`. All objects are linked with `cc` and the shim. This mode currently rebuilds every object; it does not yet do incremental `.def`-timestamp checks. ## Options - `-n` — dry run: print the build order and command. - `-v` — verbose: report external modules and build order. - `-c m2|gm2` — compiler driver (default `m2`). - `-I dir` — extra search directory (repeatable; the main file’s directory is always searched). - `-o out` — output executable (default: program module name). - `--m2bin path` — M2 driver (default `M2`). - `--shim path` — C runtime shim for V3 mode (default `shim.c`). - `--extra path` — extra C file linked after the shim. - `--m2flag flag` — one extra M2 argument (the fixpoint uses `-legacyopen1d`). - `--dialect pim|iso|gm2` — add `lib/`, `lib/common`, `lib/gm2` and `runtime/syslib` to the search path. Use one dialect per session. - `--separate` — per-module objects instead of one session image. ## Current limits - `--separate` rebuilds every object; stale-object/ABI checks are deferred. - Generic instances are still resolved at client compile time. - The default one-shot mode remains the mode used by the suite, corpus and self-hosting fixpoint. - `M2 -c` itself needs explicit imported interfaces; M2make is the transitive resolver. See `TUTORIAL.md`, `docs/separate-compilation.md`, and `tools/m2make/README.md` for details.