Building a project — ym build#
A project’s documents and scripts depend on each other: the analysis produces forces,
the calcs produce capacities, a script checks utilizations, and the report shows them.
ym build runs all of it in a valid order and skips what is up to date. Nobody lists the
order, and nobody lists any step’s inputs.
ym build # everything that's stale, in dependency order
ym build --all # ignore staleness
ym build 5-validation/beams/calc.yml # this target and whatever it needs
ym build --dry-run # print the plan and why each step is stale
ym graph # print the graph (--format dot | mermaid)
✓ 3-analysis/frame.py 0.41 s (2-project/geometry.yml changed)
✓ 5-validation/beams/calc.yml 1.30 s 4 documents (frame changed)
· 5-validation/joists/calc.yml up to date
✓ 5-validation/utilizations.py 0.05 s (capacities changed)
✓ 6-documentation/report.yml 0.38 s (utilizations changed)
Built 4 of 5 steps in 2.1 s
ym build works on the project whose config (*.ymprint.yml) is nearest above the current
directory, or the one containing --project DIR.
The steps#
The build runs:
every document matched by
_build.documentsin the project config. A pattern that matches no files is an error.every producer named in a
_dataentry’sfrom:: documents and.pyscripts.every document with a
_renderentry, rendered as that entry says (once per parameter set, to itsoutput).
# project.ymprint.yml
_data:
geometry: 2-project/geometry.yml
frame:
path: build/data/frame.json
from: 3-analysis/frame.py
capacities:
from: 5-validation/beams/calc.yml
utilizations:
from: 5-validation/utilizations.py
_build:
documents: # globs, relative to this file
- 6-documentation/*.yml
Scripts#
A script joins the build by being named in from:. It reads data by name and publishes
what it produces with ymprint.project:
# 3-analysis/frame.py
from ymprint.project import data, publish
geometry, loads, design = data("geometry"), data("loads"), data("design")
model = build_frame(geometry, loads, design, data("sections"), data("materials"))
model.analyze()
publish("frame", extract_results(model)) # writes where `frame` is declared
Function |
Meaning |
|---|---|
|
A fresh copy of data source |
|
The file a data source is read from, for code that does its own I/O. |
|
Writes |
For how a script producer compares with a document producer (which hands over its values
with _export instead), see Produced data — from:.
The project is found from the script’s own location, so a script also runs on its own
(python 3-analysis/frame.py). Under ym build, scripts run in the same process,
as python script.py would run them, with their folder importable.
How the order is found: recorded, not declared#
What produces each data source is declared once, by from:. What each step reads isn’t
declared at all; it is recorded as the step runs: every data source a document uses (in
text, _py, _hc, for_each or ym.path()) and every data() call in a script, with a
hash of each file read. The records live in build/.ym/deps.json.
When a step reads a data source, ym build first brings that source’s producers up to date.
So even the first build, with nothing recorded, runs every step after the data it needs.
A step is stale, and runs, when:
it has never been built, or its last build failed;
its source file changed;
any file it read last time changed (by content hash): its data, images,
_loadjsonfiles and PDF backgrounds, and the project config;one of its outputs (its PDFs, its exports) is missing; or
the YMPrint or plugin version changed.
A producer that runs again but writes the same data doesn’t make its readers stale. For example, editing a calc’s wording rebuilds that calc only, while a change that alters its capacities also rebuilds the utilization check and the report.
A step that reads data it produces itself, or a cycle of steps, is an error. A failed step fails the steps that need its data; the others still build, and the exit code is 1.
Note
Files a document or script opens by itself (open("…") in _py) aren’t recorded. Declare
them as _data and read them by name (or with ym.path()), or use
ym build --all.
ym graph#
Prints each data source with its producers, and each step with the data it read on its last
build. --format dot gives a Graphviz graph and --format mermaid a Mermaid flowchart.
Data sources:
geometry = 2-project/geometry.yml
frame ← 3-analysis/frame.py
capacities ← 5-validation/beams/calc.yml
utilizations ← 5-validation/utilizations.py
Steps:
3-analysis/frame.py reads: geometry
5-validation/beams/calc.yml reads: design, frame, sections
5-validation/utilizations.py reads: capacities, frame
6-documentation/report.yml reads: utilizations