mk-rs-core 0.2.3

mk-rust core: lexer, parser, DAG builder, scheduler
Documentation

plan9 mk build-tool core library.

mk-core is a faithful Rust port of Andrew Hume's Plan 9 mk. It reads mkfiles, builds a dependency graph, resolves pattern-based metarules, and dispatches parallel recipe execution through a shell abstraction.

Pipeline

Each build() call runs these stages in sequence, each producing an owned output consumed by the next:

┌─────────────────────────────┐
│   mkfile(s)                  │  user-authored text
└──────────────┬──────────────┘
               │
┌──────────────▼──────────────┐
│  lex::Lexer                 │  char-by-char → token stream
└──────────────┬──────────────┘
               │  TokenStream
┌──────────────▼───────────────────────────┐
│ parse::parse_with_scope(tokens, &mut    │  recursive descent → AST with
│   Scope)                                 │  rule-header vars + assignment
│                                          │  RHS expanded at read-time (F-045)
└──────────────┬───────────────────────────┘
               │  Vec<Stmt> (headers/RHS already expanded;
               │     recipe bodies still literal, expanded at exec time)
┌──────────────▼───────────────────────────┐
│ graph::build_graph(stmts, targets)       │  AST → DAG (metarules, transitive
│                                          │  closure, pruning, cycle detection)
└──────────────┬───────────────────────────┘
               │  Graph
┌──────────────▼───────────────────────────┐
│ graph::stale_nodes(&graph)              │  mtime staleness; virtual targets
│                                          │  unconditionally stale (no file)
└──────────────┬───────────────────────────┘
               │  stale NodeIndex set
┌──────────────▼───────────────────────────┐
│ sched::Engine                            │  parallel DAG walk, NPROC pool,
│                                          │  keep-going (-k), exclusive (E)
└──────────────┬───────────────────────────┘
               │  Job queue
┌──────────────▼───────────────────────────┐
│ recipe::run()                            │  feed recipe to shell; inject
│                                          │  $target/$prereq/$stem env vars
└──────────────┬───────────────────────────┘
               │  exit code
┌──────────────▼───────────────────────────┐
│ BuildOutcome                             │  success, partial (-k), or failure
└──────────────────────────────────────────┘

Variable expansion is split across two stages: rule headers and assignment RHS are expanded at parse-time via the threaded Scope (F-045); recipe bodies are kept literal and $target/$prereq/$stem are injected as environment variables just before shell dispatch.

Module roster

Module Purpose
[lex] Tokenizer — comment stripping, line continuation, backtick regions, quoting
[parse] Recursive-descent parser — rules, assignments, includes, attributes
[graph] DAG builder — metarule application, transitive closure, cycle/staleness checks
[var] Variable system — symbol table, $VAR/${VAR} expansion, namelists
[shell] Shell trait — abstraction for recipe execution (implementations in mk-shell)
[recipe] Recipe glue — env injection, attribute handling, CLI flag dispatch
[sched] Scheduler — parallel DAG traversal, NPROC worker pool, keep-going support
[attr] Attribute bitflags — V/Q/N/U/D/E/P/R/n
[mod@include] Recursive < file includes — child scopes, circular detection
[archive] lib(member) syntax — archive member auto-rule generation
[error] Centralized error types — MkError, LexError, ParseError, …