Skip to main content

qjsc - QuickJS Compiler

The qjsc executable is the QuickJS JavaScript compiler. It compiles JavaScript source files into bytecode or C code that can be embedded in executables.

Basic Usage

qjsc [options] [files]

Output Modes

qjsc can generate output in three different formats:
Generate C code with embedded bytecode:
qjsc -o output.c script.js
This creates a C file containing bytecode as a byte array that can be compiled into your application.

Command-Line Options

Output Control

-o OUTPUT
string
Set the output filename (default: out.c)
qjsc -o compiled.c script.js
-b
flag
Output raw bytecode instead of C code
qjsc -b -o script.bin script.js
-e
flag
Output a complete C file with main() function and bytecode
qjsc -e -o app.c app.js
The generated C file can be compiled directly into a standalone executable.

Code Generation

-N CNAME
string
Set the C name of the generated data array
qjsc -N my_script_data -o output.c script.js
By default, the C name is derived from the filename.
-p PREFIX
string
Set the prefix for generated C names (default: qjsc_)
qjsc -p myapp_ -o output.c script.js
-n SCRIPT_NAME
string
Set the script name as used in stack traces
qjsc -n "MyApp v1.0" -o output.c script.js

Module Handling

-m
flag
Compile as ES6 module (default=autodetect)
qjsc -m -o module.c app.js
-C
flag
Compile as classic JavaScript script (default=autodetect)
qjsc -C -o script.c legacy.js
By default, qjsc automatically detects whether a file is a module based on:
  • File extension (.mjs files are modules)
  • Content analysis (presence of import/export statements)
-D MODULE_NAME
string
Compile a dynamically loaded module or worker
qjsc -D worker.js -o output.c main.js
-M MODULE_NAME[,CNAME]
string
Add initialization code for an external C module
# Use default C name
qjsc -M mymodule -e -o app.c script.js

# Specify custom C name
qjsc -M mymodule,my_mod -e -o app.c script.js
This adds initialization code for C modules that will be linked with the executable.
-P
flag
Do not add default system modules (std, os, bjson)
qjsc -P -e -o minimal.c script.js
Useful for creating minimal executables without standard library dependencies.

Optimization

-s
flag
Strip source code from the bytecode. Specify twice (-ss) to also strip debug info.
# Strip source code only
qjsc -s -o output.c script.js

# Strip source code and debug info
qjsc -ss -o output.c script.js
Stripping reduces bytecode size but makes debugging harder.
Stripping debug info will make stack traces less useful. Only use -ss for production builds where size is critical.

Runtime Configuration

-S N
string
Set the maximum stack size to N bytes (default: 262144)
# Set stack size to 512KB
qjsc -S 524288 -e -o app.c script.js

# Using suffixes: k, m, g
qjsc -S 512k -e -o app.c script.js

Help

-h, --help
flag
Display help information and exit

Examples

Compile a Simple Script to C

qjsc -o hello.c examples/hello.js
The generated hello.c contains:
#include <inttypes.h>

const uint32_t qjsc_hello_size = 123;

const uint8_t qjsc_hello[123] = {
  0x02, 0x04, 0x0e, 0x63, 0x6f, 0x6e, 0x73, 0x6f,
  // ... bytecode ...
};

Create a Standalone Executable

qjsc -e -o app.c app.js

Compile Multiple Files

qjsc -e -o app.c main.js utils.js helpers.js
All files will be compiled and embedded in the generated C code.

Compile with External C Module

Given a C module fib.c with an js_init_module_fib function:
# Compile JavaScript that uses the C module
qjsc -M fib -e -o app.c main.js

# Compile everything together
cc app.c fib.c -lquickjs -o app
In main.js:
import { fib } from 'fib';
console.log('fib(10) =', fib(10));

Minimal Executable (No Standard Library)

# Compile without std, os, bjson modules
qjsc -P -e -o minimal.c simple.js

cc minimal.c -lquickjs -o minimal
This creates a smaller executable that doesn’t include the standard library.

Generate Optimized Bytecode

# Strip source code and debug info for smallest size
qjsc -ss -b -o optimized.bin script.js

Compiling Modules

ES6 Module

// module.js
export function greet(name) {
  return `Hello, ${name}!`;
}

export const version = '1.0.0';
qjsc -m -o module.c module.js

Classic Script

// script.js
function greet(name) {
  console.log('Hello, ' + name);
}

greet('World');
qjsc -C -o script.c script.js

Integration with Build Systems

Using with Make

app: app.c
	cc app.c -lquickjs -o app

app.c: src/main.js
	qjsc -e -o app.c src/main.js

clean:
	rm -f app app.c

Using with CMake

add_custom_command(
  OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/app.c
  COMMAND qjsc -e -o ${CMAKE_CURRENT_BINARY_DIR}/app.c ${CMAKE_CURRENT_SOURCE_DIR}/main.js
  DEPENDS main.js
)

add_executable(app ${CMAKE_CURRENT_BINARY_DIR}/app.c)
target_link_libraries(app quickjs)

Generated C Code Structure

With -e flag (Standalone)

The generated C file includes:
#include "quickjs-libc.h"

// Bytecode data
const uint32_t qjsc_script_size = ...;
const uint8_t qjsc_script[...] = { ... };

// Context initialization
static JSContext *JS_NewCustomContext(JSRuntime *rt) {
  // Initialize context and modules
}

// Main function
int main(int argc, char **argv) {
  // Runtime setup
  // Execute bytecode
  // Cleanup
}

Without -e flag (Library)

The generated C file includes only:
#include <inttypes.h>

const uint32_t qjsc_script_size = ...;
const uint8_t qjsc_script[...] = { ... };
You can load this bytecode in your own application using JS_ReadObject().

Compiling Full C Applications

When using qjsc -e, you need to link against QuickJS and its dependencies:
# Full compilation command
cc app.c \
  -I/path/to/quickjs \
  -L/path/to/quickjs \
  -lquickjs \
  -lm \
  -lpthread \
  -ldl \
  -o app
The exact linker flags may vary depending on your system and QuickJS build configuration.

Common Use Cases

Embedding in Applications

Generate C code without main() to embed in your own application:
qjsc -o embedded.c script.js
Then in your C code:
extern const uint8_t qjsc_script[];
extern const uint32_t qjsc_script_size;

JSValue obj = JS_ReadObject(ctx, qjsc_script, qjsc_script_size, 
                             JS_READ_OBJ_BYTECODE);

Pre-compiling for Faster Startup

Compile to bytecode and load at runtime:
# Compile to bytecode
qjsc -b -o script.bin script.js
Load in your application:
// Read bytecode file and load
uint8_t *buf = read_file("script.bin", &size);
JSValue obj = JS_ReadObject(ctx, buf, size, JS_READ_OBJ_BYTECODE);

See Also

Build docs developers (and LLMs) love