Skip to content

Commit f789574

Browse files
committed
Add self-contained binaries: package CFML apps as single executables
Virtual filesystem abstraction (VFS trait) allows the VM to read source files from disk or from an in-memory archive embedded in the binary. CLI mode (--mode cli): build command-line tools from CFML with a cli scope for arguments. Serve mode (--mode serve): package web apps with start/stop/status daemon management. Usage: rustcfml --build ./myapp -o mybinary --mode cli|serve
1 parent 974b32e commit f789574

7 files changed

Lines changed: 1032 additions & 82 deletions

File tree

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 61 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,65 @@ chmod +x myscript.cfm
101101
./myscript.cfm
102102
```
103103

104+
### Self-Contained Binaries
105+
106+
Package a CFML application into a single executable — no runtime dependencies, no source files to deploy. The binary includes the RustCFML interpreter, web server, and all your application files.
107+
108+
#### CLI Tools
109+
110+
Build command-line tools from CFML. Arguments are available via the `cli` scope, which works like CFML's `arguments` scope — named keys for flags, 1-based numeric keys for positional args.
111+
112+
```plaintext
113+
rustcfml --build ./myapp -o greet --mode cli --entry main.cfm
114+
```
115+
116+
**myapp/main.cfm:**
117+
```cfml
118+
<cfscript>
119+
name = cli.name ?: "World";
120+
writeOutput("Hello, #name#!" & chr(10));
121+
122+
// Positional args: cli[1], cli[2], ...
123+
for (i = 1; i <= structCount(cli); i++) {
124+
if (isNumeric(i) && structKeyExists(cli, i))
125+
writeOutput(" arg #i#: #cli[i]#" & chr(10));
126+
}
127+
</cfscript>
128+
```
129+
130+
```plaintext
131+
./greet # Hello, World!
132+
./greet --name Alex # Hello, Alex!
133+
./greet foo bar # positional: cli[1]="foo", cli[2]="bar"
134+
```
135+
136+
#### Web Applications
137+
138+
Package a web application as a single binary with an embedded HTTP server.
139+
140+
```plaintext
141+
rustcfml --build ./webapp -o myserver --mode serve
142+
```
143+
144+
Run it:
145+
```plaintext
146+
./myserver # Foreground on port 8500
147+
./myserver --port 3000 # Custom port
148+
./myserver start --port 3000 # Daemonize (background)
149+
./myserver status # Check if running
150+
./myserver stop # Graceful shutdown
151+
```
152+
153+
#### Binary Sizes
154+
155+
| Build | Size |
156+
|---|---|
157+
| Release binary (no app) | ~13 MB |
158+
| + small web app | ~13 MB |
159+
| + large app (100+ files) | ~13-15 MB |
160+
161+
No JRE, no runtime, no dependencies. Compare: Lucee/BoxLang require a 200+ MB JRE.
162+
104163
## Performance
105164

106165
Benchmarked serving a "Hello World" `.cfm` page using Apache Bench (`ab -n 100 -c 1`):
@@ -131,6 +190,7 @@ RustCFML covers a substantial portion of the CFML language:
131190
- **Threading**`cfthread` tag (sequential execution model)
132191
- **Closures** — scope capture with parent write-back, arrow functions, spread operator
133192
- **WASM target** — compile to WebAssembly via `wasm-bindgen`
193+
- **Self-contained binaries** — package CFML apps as single executables (CLI tools or web servers)
134194

135195
See [Work.md](Work.md) for detailed implementation status.
136196

@@ -196,7 +256,7 @@ const output = CfmlEngine.new().execute('writeOutput("Hello from WASM!");');
196256
## Testing
197257

198258
```plaintext
199-
cargo run -- tests/runner.cfm # 1181 assertions across 89 suites
259+
cargo run -- tests/runner.cfm # 1197 assertions across 90 suites
200260
cargo test # Rust unit tests
201261
```
202262

crates/cfml-common/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ pub mod dynamic;
44
pub mod encodings;
55
pub mod introspection;
66
pub mod position;
7+
pub mod vfs;
78
pub mod vm;

0 commit comments

Comments
 (0)