Modules
A module starts with a Recoil [...] header that declares its type,
id, imports, and exports. Imports may pull specific names from a module:
Recoil [
Type: module
Module: tests/math-module-demo
Imports: [
std/math/core [abs-value clamp-value]
]
Exports: []
]
print abs-value [i32!] -7
print clamp-value [i32!] 10 0 5
Some modules (extensions) are called through a namespace prefix instead of importing individual names — see Extensions.
The package manager
Recoil ships a dependency workflow driven through the same CLI. A workspace
has a recoil.project manifest and a generated
recoil.lock.reb lockfile.
| Command | What it does |
|---|---|
init | create a minimal recoil.project in the workspace |
install tls | install optional capabilities (e.g. TLS/HTTPS support) |
fetch | resolve dependencies, populate the source store, write the lockfile |
compile <entry.rcl> / run <entry.rcl> | build or run an entry point using the lockfile (no re-fetch) |
update | refresh dependency refs / archives |
doctor | validate the workspace without fetching or compiling |
repair | rebuild missing source-store entries referenced by the lockfile |
r3 -s recoil.r3 init
r3 -s recoil.r3 fetch
r3 -s recoil.r3 run app.rcl
On success, package commands print exactly one Rebol value (tagged
Recoil-Init, Recoil-Fetch, …) that can be loaded
directly for scripting. Failures use the standard CLI diagnostics.
Exporting functions
Mark functions with #export in the spec to expose them from a
generated library. An init function (if defined) runs when the
library loads.
add: func [#export a [i32!] b [i32!] return: [i32!]] [return a + b]
sub: func [#export a [i32!] b [i32!] return: [i32!]] [return a - b]
init: func [#export return: [none!]] [print "Library loaded!"]
Building libraries
Compile a source file to a shared or static library:
r3 -s recoil.r3 --lib mylib.rcl # shared, name from source
r3 -s recoil.r3 --lib mylib.rcl --name mylib # shared, custom name
r3 -s recoil.r3 --lib mylib.rcl --static # static
Given mylib.rcl, the compiler produces the C source
mylib.c, a header mylib.h with the exported
declarations, and the library itself (.so/.dylib/.dll
for shared, .a/.lib for static — auto-detected per
platform).
Using it from C
// main.c
#include "mylib.h"
int main() {
init(); // run library init if defined
int32_t r = add(1, 2);
printf("%d\n", r);
return 0;
}
gcc -o myprogram main.c -L. -lmylib # shared
gcc -o myprogram main.c libmylib.a # static
Extensions
Extensions under the ext/ tree wrap C libraries behind a Recoil
module. They are imported by module id and called through a namespace prefix.
For example, ext/sqlite:
Recoil [
Title: "sqlite demo"
Imports: [ext/sqlite]
]
db: ext/sqlite:db-open ":memory:"
if none? db [print "open failed"]
stmt: ext/sqlite:prepare-stmt db "select ? + ?"
ext/sqlite:bind-int stmt 1 10
ext/sqlite:bind-int stmt 2 20
if ext/sqlite:stmt-step stmt = ext/sqlite:row-code [
print ext/sqlite:column-int stmt 0 ; 30
]
ext/sqlite:stmt-finalize stmt
Writing your own extension (foreign declarations, type mapping, refinement patterns, one-shot vs handle wrappers, build/link choices, and a test pattern) is covered in the repository's extension authoring guide.