Any repository-built program — a game as much as another library, in either library mode — may name the programs it needs.
[program]
depends = ["demo-library", "usb-driver"]Each entry is a Roost address, not a LibLoad name and not a URL. One list covers both jobs: what the build links against, and what Swoop installs alongside the program.
Pinning a version#
A bare address builds against whatever that program published most recently. Append @version to
build against one release instead:
[program]
depends = ["demo-library", "usb-driver@1.4.0"]A pin fails the build if that release was never published, which is what to reach for when a library changes an ABI. It applies to the build only — a release records the address alone, because the install graph resolves to whatever is published when a calculator asks.
The rules#
countat most 8Per program. A program needing more than eight libraries is usually a program that wants one library that bundles them.
published firstRequiredEach dependency has to be published before the build that names it. A name nothing is published at fails the build.
a libraryRequiredA build can only link against a LibLoad library. Naming an ordinary program fails.
acyclicRequiredCycles are refused, including a program that names itself.
listed onceRequiredThe same address twice is an error, not a list quietly reduced to one.
repository projects onlyTI-BASIC projects have no manifest and cannot declare dependencies.
What the build gets#
Nothing is rebuilt. Every library publishes a developer archive holding the appvar, the .lib stub
and the public headers, and a build that depends on one is handed that archive.
The Flight builder does the work before the sandbox starts, because the sandbox has no network:
Resolve
It asks Roost what each address resolves to, and gets a version, a library name, a size and a checksum back.
Fetch what is new
Archives are cached by checksum. A repeat build downloads nothing, and a new release is simply a new key.
Verify and unpack
Each archive is checked against its checksum. The stub and the headers are unpacked; the appvar is dropped, since that is what a calculator installs and no part of what a build links against.
Build
The container sees them on a read-only mount, with the headers beside the toolchain's own and the stubs on the LibLoad search path.
An ordinary project makefile needs no changes for any of this. A dependency shipping a header the
toolchain already provides — its own string.h — fails the build by name rather than quietly
replacing it.
Reading the flattened graph#
Do not walk the graph yourself. Ask for it flattened:
/api/v1/programs/{slug}/requiresPublic{
"slug": "snake",
"programs": [
{
"slug": "usb-driver",
"title": "USB Driver",
"version": "2.1.0",
"checksum": "a3f1…",
"size": 8412,
"size_text": "8.2 KB",
"var_name": "USBDRVCE",
"var_type": "appvar",
"archived": true,
"language": "lib",
"raw_url": "/d/usb-driver/raw"
},
{
"slug": "demo-library",
"title": "Demo Library",
"version": "1.0.0",
"checksum": "77c2…",
"size": 3120,
"size_text": "3.0 KB",
"var_name": "DEMO",
"var_type": "appvar",
"archived": true,
"language": "lib",
"raw_url": "/d/demo-library/raw"
}
]
}Deepest dependency first. Write them in exactly that order, then write the program itself, which is not included in the list.
The same array rides along on the single-program endpoint as requires, so fetching a program page
needs one call rather than two.
What a client does with it#
Ask for the requirements
One request, before downloading anything.
Compare checksums
Each entry carries its own checksum. Anything already on the calculator at the same checksum is already correct: skip it.
Write what is left, in order
Each entry says its variable name, its type, its size and whether it wants to be archived.
Write the program
Last.
That is exactly what Swoop does.
The full client-side procedure, including the bulk version check.
When a dependency is archived#
Archiving a project suspends its program, and a suspended program is filtered out of the dependency graph. A program that depends on it keeps its declaration, but the requirement stops being returned.
That means an install can silently become incomplete. If you maintain a library other people depend on, archiving it is a decision about their programs as much as yours.
Choosing what to depend on#
Published at a stable address, with an append-only export table. That is what libraries are for.
Nothing stops it, but a program is not an interface. If two of your programs share code, make the shared part a library.