Appendix D - Build and Debug
The toolchain in one place: the CLI’s two commands and their options,
the four files a build writes, the conventions that let Debug80 treat
a .glim file as a runnable target, and the diagnostics the compiler
reports. Every usage line, output line and message here is copied
from real runs of Glimmer 0.5.3.
The command line
glimmer -h prints the whole surface:
Usage: glimmer [options] <entry.glim>
glimmer build [options] <entry.glim>
The default command compiles .glim to a generated AZM source file
and register-contract checks it with AZM. build also assembles it
with AZM (.hex, .bin, .d8.json) and rewrites the Debug80 map so
block-body lines step in the .glim source.
Options:
-o, --output <file> Output AZM path (default: <entry>.main.asm, the Debug80 entry-point convention)
--org <addr> Assembly origin, e.g. $4000 (default: $4000)
--no-check Generate only; skip the AZM register-contract check (not with build)
--deps Print the dependency report (writers/readers per cell) and exit
-V, --version Print package version
-h, --help Print this help
Two commands share that surface:
| Invocation | Work performed |
|---|---|
glimmer game.glim |
Generates game.main.asm and register-contract checks it with AZM. Stops there. |
glimmer build game.glim |
The same generation and check, then AZM assembles the file and the Debug80 map is rewritten so block bodies step in .glim source. |
Each prints what it wrote:
glimmer demo.glim
Wrote demo.main.asm (register contracts checked by AZM)
glimmer build demo.glim
Wrote demo.main.asm (register contracts checked by AZM)
Wrote demo.main.d8.json (11 block segments attributed to .glim source)
build’s messages name the two files Debug80 reads; the .hex and
.bin land beside them in the same pass.
Options
| Flag | Effect |
|---|---|
-o, --output <file> |
Where the generated AZM goes. The default, <entry>.main.asm, is the name Debug80 discovers as an entry point; pick another name only for output you will wire up yourself. |
--org <addr> |
Assembly origin. The default $4000 is where MON-3 expects user code; --org $6000 moves the generated .org line and everything after it. |
--no-check |
Generate only; the AZM register-contract check is skipped. Generation-only runs print Wrote demo.main.asm without the check note. |
--deps |
Print the dependency report and exit. Nothing is written. |
-V, --version |
The package version: 0.5.3. |
-h, --help |
The usage text above. |
--no-check belongs to the default command. Combining it with
build stops immediately:
build always runs the AZM check; --no-check is not supported with build.
--deps prints one stanza per cell, writers above readers, the same
report chapter 11 works through:
program Demo
DotX : state byte
raised by: MoveRight
triggers: DrawDot (render)
Right : pulse
raised by: key KEY_6 (held)
triggers: MoveRight (logic)
The four artifacts
A build of demo.glim leaves four files beside the source:
| File | Holds |
|---|---|
demo.main.asm |
The generated AZM program: your block bodies wrapped in the runtime - loop, dispatch, change flags, profile library - as one readable file. The other three files are derived from this one. |
demo.main.hex |
The assembled bytes as Intel HEX records, the transfer format for loading onto hardware. |
demo.main.bin |
The same bytes as a raw binary image, starting at the origin. |
demo.main.d8.json |
The Debug80 map: address segments attributed to source files, the symbol table (DotX, Glim_MoveRight, every label with its address), and a generator record naming the AZM version and inputs. |
The map’s file list names both sources: demo.main.asm for the
generated glue and demo.glim for the block bodies. The eleven
“block segments” in the build message are the address ranges that
point back into the .glim file.
Debug80 targets
Debug80 finds Glimmer programs two ways.
By convention. A file named main.glim, or ending in
.main.glim, whose first declaration is program, is discovered as
a target - press F5 and Debug80 builds it through Glimmer and runs
the result. Part files open with their own declarations (effect,
state), so the program check keeps them out of the target list.
By explicit entry. A debug80.json target names any .glim
file directly by pointing sourceFile at it. The Glimmer
repository’s own project file carries this entry for Tetro, trimmed
here to the shape that matters:
{
"targets": {
"tetro-glim": {
"outputDir": "build",
"platform": "tec1g",
"profile": "mon3",
"sourceFile": "examples/tetro.glim",
"artifactBase": "tetro",
"sourceRoots": ["examples"]
}
}
}
sourceFile ending in .glim is what routes the build through
Glimmer; the artifacts land in outputDir under artifactBase
names. The full entry in the repository adds a tec1g section
mapping the memory regions (ROM to $07FF, RAM to $7FFF, ROM from
$C000) and the $4000 application start.
Where the debugger stops
The rewritten map splits the program along the begin/end
boundary:
| Code | Steps in |
|---|---|
Block bodies (begin to end) |
The .glim file. Breakpoints on body lines resolve; stepping walks your source line by line. |
| Generated glue (dispatch, wrappers, timers, profile library) | The .main.asm file. Stepping into a call FbPlot or past an end drops into readable generated assembly. |
Build errors follow the same split. A bad instruction inside a body
is reported against the .glim line it sits on, at column
precision:
badbody.glim:17:5: [AZMN_PARSE] error: inc expects one operand
Line 17 is the inc a,b inside the block body, in the file you
edit, so the fix is one keystroke away from the report.
Diagnostics
Compiler messages carry a file, a line, a [GLIM] tag and a
severity. An error stops the build and nothing is written; a warning
prints and the build finishes. Each message below is the real output
of a real broken program.
Duplicate name. Two declarations named Score - states, pulses
and blocks all draw from one pool of names:
dup.glim:7: [GLIM] error: Duplicate name "Score": all declared names share one namespace.
Reserved name. A state named GlimScore collides with the
generated runtime’s namespace:
reserved.glim:6: [GLIM] error: Reserved name "GlimScore": it belongs to the generated runtime (states cannot use Glim*/Snd_*/Curve_*/Shape_*/CHG_* or runtime symbols).
Undeclared cell. A block triggers on Points with no Points
anywhere in the program - a typo for Score, caught at the header:
undeclared.glim:8: [GLIM] error: Effect DrawScore triggers on undeclared cell "Points".
Render with updates. A render block declares updates Score,
claiming a write that the phase forbids:
renderupd.glim:8: [GLIM] error: render DrawScore cannot update state cells: render blocks depict state. Use effect or compute.
Missing program declaration. A file of declarations with no
program line at the top; the message carries the file alone, since
the gap has no line to point at:
noprog.glim: [GLIM] error: Missing program declaration.
Missing updates (warning). An effect stores to Score while its
header declares no updates Score. The build finishes - both
Wrote lines follow the warning - and the program runs with the
consequence the message spells out:
warn.glim:12: [GLIM] warning: AddPoint writes Score but does not declare "updates Score": the change flag will not be raised and dependent blocks will not run.
Wrote warn.main.asm (register contracts checked by AZM)
Wrote warn.main.d8.json (4 block segments attributed to .glim source)
Chapter 11 walks this warning through a running program: the store
executes, the cell climbs in memory, and every block waiting on
that cell sleeps through it.