A tool made of several files — a main.scua, a
lib/ folder, a few packages from scua add —
can travel as one file: an application bundle,
NAME.scuapp. scua runs it directly. The
machine running it needs scua and nothing else: no
deps/ folder, no project layout, and no
scua-pkg.
#Build one
The package manager writes bundles. In the project folder, name the
entry script (this needs a scua-pkg newer than 0.3.19,
which writes the bundle format this scua reads):
$ scua-pkg bundle --app main.scua
bundled app `tally` (entry main.scua): 2 app file(s), 0 package(s) with 0 file(s) into tally.scuapp (1955 bytes)
needs: fs — grant them when you run it: `scua-pkg run [--allow-…] tally.scuapp`
The bundle holds your own .scua files, every package
your lock resolved, the lock itself, and a digest for each of them.
tally here is examples/tally, a
small wc: the repository also carries the bundle built from
it, examples/tally.scuapp.
#Run it
Run it like a .scua file. scua options go
before the file and the tool's own arguments after it:
$ scua --allow-fs=. tally.scuapp notes.txt main.scua
2 5 24 notes.txt
30 131 879 main.scua
scua knows a bundle by its first bytes, not by its name,
so a renamed one still runs as a bundle.
#It gets only the grants you give it
A bundle grants itself nothing. Its capabilities come from your
command line, exactly as for a .scua file, and
--allow-fs=. means the folder you are in when you
type the command, not the folder the bundle sits in.
A run that is missing a grant is refused before anything starts, as
it is for a .scua file. The bundle also records which
capabilities its code reaches, so the message names every missing grant
at once, not only the first one the compiler met:
$ scua tally.scuapp notes.txt
scua: tally.scuapp:main.scua:10: this app needs capabilities this run was not granted: fs. Grant them before the file: `scua --allow-fs tally.scuapp` (or narrower: --allow-fs=DIR)
That exits with status 4, like any refused grant (see Exit status). The list only
shapes that message. It never grants anything, and it never refuses a
run on its own.
#What is checked before it runs
Before a single line of the tool is compiled, scua
checks the whole bundle:
- it is a bundle format this
scuareads, and an application rather than a dependency-only bundle; - the whole file matches the digest in its header, which covers every byte: names, paths and the layout as well as the code;
- every offset and length points inside the file;
- no path in it is absolute or contains an empty,
.or..part; - every file matches its digest, and each package's files are exactly the ones its release record lists, with the same digests;
- every package's release record matches its release root, and the lock names exactly the packages the bundle carries, at the versions and roots it carries them;
- the lock, the name table and the list of capabilities match the digest that covers them.
If any check fails, nothing runs, and the message says which one,
with a stable code first (E-APP-FORMAT,
E-APP-CORRUPT, or the lock and record codes a project's
deps/ folder uses):
$ scua --allow-fs=. tally.scuapp notes.txt
scua: tally.scuapp: E-APP-CORRUPT: this application bundle does not match its own digest — it is damaged or was changed after it was built
That exits with status 3: nothing compiled, and the fix
is the file, not the command.
A bundle built by scua-pkg 0.3.19 is an older format,
and is refused with a message saying how to rebuild it:
$ scua --allow-fs=. tally.scuapp notes.txt
scua: tally.scuapp: E-APP-FORMAT: this application bundle is format 2, and this scua reads format 3 — rebuild it with a current `scua-pkg bundle --app`
These checks find damage. They don't prove who built the bundle. Every digest lives inside the bundle, so someone who changes a file and then recomputes all the digests produces a bundle that passes. To know a bundle is the one its author built, get its SHA-256 from the author through a channel you trust, and compare:
$ shasum -a 256 tally.scuapp
#Imports work as they did on disk
Inside a bundle, import finds the same file it found
when you ran the sources:
- a module's own folder first (
lib/fmt.scuaimportinghelpergetslib/helper.scuaif it's there); - then the entry script's folder;
- then the packages, which see their own modules as they do under
deps/.
A name that both your files and a package provide is refused as ambiguous, as it is on disk. A bundle that runs is the program you tested.
#What doesn't combine with a bundle
A bundle is the whole program, so the options that would add files or settings from beside it are refused rather than mixed in:
--mod-pathand--mod-overrideadd module folders from disk;--profilereads ascua.toml, and a bundle carries none. Pass-Dflags instead;scua debugsteps through source files. Debug the tool from its sources.
Everything else works as it does for a .scua file:
--fast, --jit, --max-ops,
--workers, --output=json, every
--allow-… grant, -D flags and script
arguments.
#Related pages
- Modules:
packages,
deps/and the lock - Command-line interface
- Read command-line arguments
- Read and write files: what
--allow-fsgrants