Worked Example: Production Simulator¶
Page Maps¶
graph LR
family["Reproducible Research"]
program["Deep Dive Make"]
section["Determinism Debugging Self Testing"]
page["Worked Example: Production Simulator"]
capstone["Capstone evidence"]
family --> program --> section --> page
page -.applies in.-> capstone
flowchart LR
orient["Orient on the page map"] --> read["Read the main claim and examples"]
read --> inspect["Inspect the related code, proof, or capstone surface"]
inspect --> verify["Run or review the verification path"]
verify --> apply["Apply the idea back to the module and capstone"]
This file gathers the module into one teaching build.
Layout¶
project/
Makefile
mk/
common.mk
objects.mk
stamps.mk
macros.mk
rules_eval.mk
src/
main.c
dynamic/
dyn1.c
dyn2.c
include/
util.h
scripts/
gen_dynamic_h.py
tests/
run.sh
This simulator matters because it combines deterministic discovery, generation,
selftesting, and an optional eval surface in one place you can actually inspect.
A graph view of the simulator¶
flowchart TD
all["all"] --> app["app"]
app --> main["build/src/main.o"]
app --> util["build/src/util.o"]
app --> dyn1["build/src/dynamic/dyn1.o"]
app --> dyn2["build/src/dynamic/dyn2.o"]
main --> hdr["build/include/dynamic.h"]
main --> flags["build/flags.stamp"]
util --> flags
dyn1 --> flags
dyn2 --> flags
This graph is useful because it makes three Module 03 concerns visible at once:
- discovery affects which object targets exist at all
- generated headers must be trustworthy inputs, not fragile side effects
- semantic flags still belong in the object-file contract
What to inspect first¶
Start with these questions:
- which lists are rooted and sorted
- which generated artifacts are published atomically
- which hidden inputs are modeled
- which targets form the public build contract
This worked example is the concrete home for the rest of the module.
Read the simulator in this order¶
Makefilefor public targets and top-level intentmk/common.mkfor stable knobsmk/objects.mkfor rooted and sorted discoverymk/stamps.mkfor modeled hidden inputsmk/macros.mkfor small reusable invariantsmk/rules_eval.mkonly after the core build is already understood
That order matters because it keeps the graph visible before you look at optional abstraction.
Four experiments to run¶
Experiment 1: Prove stable discovery¶
Run the build, inspect which dynamic sources are included, then reason about what would
happen if a new src/dynamic/*.c file appeared. The question is whether the discovery
policy is explicit and deterministic.
Experiment 2: Trace one rebuild properly¶
Run:
Pick one target and write down the exact reason Make rebuilt it.
Experiment 3: Prove the build system with selftest¶
Run:
This should prove convergence, serial/parallel equivalence, runtime correctness, and one meaningful negative case.
Experiment 4: Check that optional eval stays optional¶
Run:
The point is to prove that the core build does not depend on the optional generated demo surface.
What this example should teach you¶
By the time you finish this file, you should be able to point at the simulator and say:
- where determinism is enforced
- where debugging evidence comes from
- where the CI-facing target surface begins
- where selftest proves the build
- where abstraction is kept under control instead of controlling the build