Creating Standalone Executables
QuickJS-ng provides two methods for creating standalone executables from JavaScript code:- Using
qjs -c- Simple, single-file bundling (recommended) - Using
qjsc -e- Full C compilation with custom modules
Method 1: Using qjs -c (Recommended)
The simplest way to create a standalone executable is using theqjs interpreter’s compile flag.
Basic Usage
app that bundles your JavaScript file with the QuickJS runtime.
How It Works
Append to Executable
The bytecode is appended to a copy of the
qjs executable with a trailer to help locate itComplete Example
Using a Different Base Executable
By default,qjs -c uses the current qjs executable as the base. You can specify a different one:
The
--exe parameter expects an absolute path, such as ~/bin/qjs or $HOME/bin/qjs.- Cross-compilation for different platforms
- Using a custom-built
qjswith specific features - Creating executables with different runtime configurations
Limitations
To work around this limitation, use a bundler:Bundling Multiple Files
Sinceqjs -c only compiles a single file, you need to bundle dependencies first.
Using esbuild
Important esbuild Options
Bundle all dependencies into a single file
Mark QuickJS built-in modules (
qjs:std, qjs:os, qjs:bjson) as external to avoid bundling errorsOutput ES module format (recommended for QuickJS)
Target ECMAScript 2023 (QuickJS supports most ES2023 features)
Minify the output to reduce executable size
Method 2: Using qjsc -e
For more control, you can useqjsc to generate a complete C program and compile it.
Basic Workflow
Complete Example
Advantages of qjsc -e
- Full control over C compilation flags
- Can integrate with C modules
- Can customize the runtime initialization
- Can compile multiple JavaScript files together
With External C Modules
You can embed custom C modules in the executable:Optimizations
- Strip Source Code
- Strip Debug Info
- Minimal Runtime
Remove source code from bytecode to reduce size:This removes the original JavaScript source but keeps debug info (line numbers, function names).
Comparison of Methods
| Feature | qjs -c | qjsc -e |
|---|---|---|
| Ease of use | ⭐⭐⭐ Very easy | ⭐⭐ Requires C compiler |
| Single command | ✅ Yes | ❌ Two steps required |
| Bundle multiple files | ❌ Needs bundler | ✅ Built-in |
| C module integration | ❌ No | ✅ Yes |
| Custom runtime config | ❌ Limited | ✅ Full control |
| Cross-compilation | ✅ Via —exe | ✅ Via C cross-compiler |
| Executable size | Same as qjs | Can be smaller with -P |
Advanced Examples
Full Application with Bundler
With Standard Library Access
app.js
Platform-Specific Builds
Distribution
The resulting executables are self-contained and have the same runtime dependencies as the baseqjs executable:
- libc (standard C library)
- libm (math library)
- pthreads (if threading is enabled)
- libdl (if dynamic module loading is enabled)
You can check dependencies with:
Troubleshooting
”Module not found” errors
If you get module errors when running a bundled executable:- Make sure you used
--external:qjs:*in esbuild - Check that all imports use the correct module specifiers
- Verify the bundle works with
qjsbefore compiling
Linking errors with qjsc
If you get linker errors when compiling C code:Large executable size
To reduce executable size:- Use
--minifyin esbuild - Use
-sor-ssflags with qjsc - Use
-Pto exclude standard library (if not needed) - Strip the final executable: