Spec M14 — project driver and mc.toml
Goal: a developer with only the mc binary builds a project by running mc build in its directory.
Everything lives in src/*.mc (stage0 untouched). The single-file CLI (mc in.mc -o out.o,
--exe, --backend=, --dump-*) keeps working unchanged.
CLI #
mc build [DIR] [--config FILE]— DIR defaults to.; config defaults toDIR/mc.toml. Errors name the config file withline:col.mc buildprints one line per step (compile main.mc -> build/app.o,link ...) and exits 1 on the first failure with the tool's stderr passed through.
mc.toml (subset of TOML, deterministic order of keys as written) #
[project]
name = "api"
entry = "main.mc" # relative to the TOML directory
out = "build/api" # relative to the TOML directory; parent dirs created
kind = "exe" # exe | obj
[target]
os = "macos" # macos | linux | windows (M14 implements macos only; others -> clear error)
arch = "aarch64"
[compiler] # optional: build a taught compiler first, then use it for `entry`
modules = ["oop.mc"] # each is #include'd after the compiler core; user_init must be defined by one of them
out = "build/mc-api" # default build/mc-<name>
[linker] # optional; when absent on macos, kind=exe uses the built-in macho-exe backend
cmd = "ld"
args = ["-o", "{out}", "{obj}", "-lSystem", "-syslibroot", "{sdk}", "-arch", "arm64", "{libs}"]
[libs] # named libraries; on macos a dylib path bound by ordinal, elsewhere passed to the linker
sqlite3 = "/usr/lib/libsqlite3.dylib"
[externs] # symbol or prefix* -> lib name; unlisted externs default to libSystem
"sqlite3_*" = "sqlite3"
[include]
paths = ["lib"] # extra search roots for #include "x" after the includer's directory
- Parser (
src/toml.mc): tables[a.b], arrays of tables[[x]](parsed, kept for later),key = valuewith basic strings (escapes\" \\ \n \t), integers, booleans, arrays of strings or integers (multi-line allowed), comments#, bare and quoted keys. Anything else is an error with line:col. Result: a flat table of(path, value)in source order plustoml_get(path),toml_get_array(path, i),toml_count(path);tomldumpdriver (src/tomldump.mc) prints it. [externs]feeds the same table#dylibuses (extern_lib_add); ordinals are assigned to[libs]in the order they appear.#dylibin source still works and takes precedence for its own externs.{out} {obj} {libs} {sdk}placeholders in[linker].args;{sdk}runsxcrun --show-sdk-pathlazily (only when used). The linker is spawned withposix_spawn+waitpid(libSystem externs added tolib/sys.mc); non-zero exit propagates.
Tests #
tests/toml/*.tomlwith*.expectdumps;scripts/check-toml.shcomparestomldumpoutput; a few malformed files with expectedfile:line:colerrors.examples/api/mc.toml:mc build examples/apibuilds the taught compiler, thenbuild/api, andexamples/api/test.shpasses against it. The Makefile keeps working as an alternative.make checkgreen; golden rewritten once with the empty--dump-asmdiff shown.
Out of scope (M15/M16) #
#include <name> from the bundle, #embed, foreign targets ([target].os != macos is a clear error).