The instrument step writes an instrumented copy of your channel to a separate folder. Your sources are never modified. Add it to your release and beta deploys, and keep day-to-day development builds uninstrumented:
{
"scripts": {
"everframe:build": "everframe-roku instrument ./ --out ./.everframe-build --bundle-library",
"deploy:dev": "roku-deploy",
"deploy:release": "npm run everframe:build && cd .everframe-build && roku-deploy"
}
}
.everframe-build is a complete channel folder — the step copies the whole
channel, including rokudeploy.json. That is why deploy:release runs
roku-deploy from inside it. roku-deploy 3.x ignores command-line arguments
and reads its options only from rokudeploy.json / bsconfig.json in the
current directory, so roku-deploy --rootDir ./.everframe-build would silently
deploy your uninstrumented channel. Keep the cd in the same script as the
deploy tool.
You still load the library and call start() as in
Install; --bundle-library copies the library zip into
<out>/components/. The Main() lines from the install page are not needed in
an instrumented build — the step adds the equivalent call itself. Keep them in
your sources anyway if your uninstrumented builds should report crashes; the
two do not conflict.
Add .everframe-build/ to .gitignore.
What gets wrapped
Each targeted function body is wrapped in try … catch … end try on the same
source line, so line numbers in stack traces still match your original
files. The catch records the error and then re-throws the original exception:
an error that would have crashed your channel still crashes it, and an error
your own code catches further up is still caught there.
Main/RunUserInterfaceinsource/initof every componentonKeyEventonChangehandlers declared on interface fields- functions declared in a component
<interface> - callbacks registered with
observeField/observeFieldScoped - Task
functionNametargets
The last four follow extends in both directions: a callback named in a base
component is wrapped where a subclass implements it, and the other way round.
Functions that cannot be wrapped safely are skipped and listed in the output.
That includes any function containing a label (a goto target), because
BrightScript does not allow labels inside a try block.
Instrumentation also records key presses and the scene’s init as
breadcrumbs, and sets the
current screen for components matching
--screens.
Effect on debugging
Instrumentation changes how a crash looks in the BrightScript debugger. The original exception is caught and re-thrown from the end of the wrapped function, so:
- the debugger stops on the wrapped function’s
end sub/end functionline, not on the line that failed - the stack has already unwound to that function, so the local variables of the failing line are gone
The report sent to Everframe still carries the original error, message and backtrace. This is the reason to instrument release and beta builds only.
Options
everframe-roku instrument <channelDir> --out <dir> \
[--exclude <glob>]... \
[--mechanisms main,init,key,observer,task,callfunc] \
[--screens <globs>|none] \
[--bundle-library] [--dry-run]
| Option | Meaning |
|---|---|
--out <dir> | Where the instrumented copy is written. Required unless --dry-run. May be a subdirectory of the channel; must not be the channel directory itself or a parent of it |
--exclude <glob> | Skip files whose channel-relative path matches. Repeatable, for example --exclude "components/vendor/**" |
--mechanisms | Comma-separated subset of main, init, key, observer, task, callfunc. Default is all of them |
--screens | Comma-separated globs (* and ?) for automatic screens. Default *Screen,*View,*Page; none turns it off. Needs the init mechanism |
--bundle-library | Copy the library zip into <out>/components/ |
--dry-run | Print what would be wrapped and which components are tracked as screens, without writing anything |
--out is emptied on every run, so files deleted from your channel do not
linger in the build. To make that safe, each run writes a .everframe-build
marker file into --out, and the CLI only empties a directory that has this
marker. If --out exists, is not empty and has no marker, the command fails
with refusing to overwrite a directory everframe-roku did not create.
Other tools
- VS Code BrightScript extension — add a task that runs
everframe:build, and a launch configuration whoserootDiris${workspaceFolder}/.everframe-buildwith that task as itspreLaunchTask. Keep your normal launch configuration for debugging. - CI or signed packaging — run
everframe:build, then zip or deploy the contents of.everframe-buildwith your own tooling.