Libraries
Two different people use import.
Someone writing scripts in your app (a player, a modder, you in a .mini file). They import another script. No C++. No add_library.
You, the host. You register C++ or bundled packages so scripts can import math.
Import another script (end user)
Same language, same folder. The host does nothing.
mods/quest.mini
mods/helpers.mini
// helpers.mini
fn twice(n) { return n * 2; }
// quest.mini
import helpers
print(helpers.twice(3));
import helpers looks for helpers.mini (or whatever extension the language uses):
- Next to the file that wrote
import - The process working directory
imports.search_directoriesin the language JSON- Folders the host passed to
add_search_path
Dots become folders: import company.utils → company/utils.mini.
A string path works if the language allows it: import "helpers.mini".
A leading relative token (import .helpers, if you set relative_import_token) searches only the importer’s folder.
The imported file runs in its own environment. It can see host binds. It does not dump its locals into the importer unless bind_as is "globals" or "both".
A player cannot import a raw .cpp / .h this way. Only same-language scripts.
Import a host library
Always there. You bind("print", ...). Every script can say print(...). No import.
A library. You add_library("math", ...). A script must say import math before it can use it.
CMake cannot do the second step. Adding a .c++ file to the executable only compiles it. Scripts see nothing until your C++ calls add_library and you pick the name ("math", "app.math", anything).
JSON only describes how scripts write the import. It does not register libraries.
Language JSON (syntax only)
"imports": {
"enabled": true,
"import_keywords": ["import"],
"module_separator": ".",
"bind_as": "namespace",
"search_directories": [],
"plugin_entry": "rescripted_register"
}
bind_as "namespace" → the script writes math.twice(3).
bind_as "globals" → after import math the script just writes twice(3).
bind_as "both" → both.
search_directories are extra folders for import utils when you never registered utils.
plugin_entry is the C symbol a workshop plugin should export. Default rescripted_register. Override per engine with set_plugin_entry.
A C++ library you ship with the app
1. Turn imports on in the language JSON (above).
2. Write the functions in a normal .c++ file:
// stdlib/math.c++
#include <ReScripted.h>
RESCRIPTED_LIBRARY(math) {
lib.bind("twice", [](const std::vector<rescripted::Value>& args) {
return rescripted::Value(args.empty() ? 0.0 : args[0].as_number() * 2.0);
});
}
math here is only a C++ name (rescripted::library::math). Scripts do not see it yet.
3. Compile that file with the rest of the program:
add_executable(game src/main.cpp stdlib/math.c++)
4. Give it an import name when the engine starts:
#include <ReScripted.h>
RESCRIPTED_LIBRARY_DECLARE(math);
engine.add_library("math", rescripted::library::math);
Now a script can write:
import math
print(math.twice(3));
You chose the string "math". You could have used "app.math" and the script would import app.math.
Same call, other sources
add_library always takes the import name first. The second argument is “what is this library?”
| What you have | Call |
|---|---|
Functions in main |
add_library("math", twice) |
| A script file baked into the binary as a string | add_library("prelude", source, "Mini") |
| A script file on disk (mod, workshop pack) | add_library("Workshop", "mods/workshop.mini") or add_library_file(...) |
A normal .h / .cpp already linked into the app |
add_library("native", "path/to/api.h") — best-effort read of simple extern "C" prototypes |
A compiled plugin (.dll / .dylib / .so) |
load_plugin("mods/extra.dylib") — the plugin calls add_library itself |
Baked-in scripts: use rescripted_embed_language so CMake copies the file into a string. Then you still add_library and pick the name. The script does not run until something imports it.
engine.add_library("prelude", std::string(rescripted::embed::prelude), "Mini");
Normal headers
The host registers the path. ReScripted is not a C++ compiler. It reads simple declarations (int add(int, int); and similar) and looks up those symbols in the running process. Skip or fail what it cannot understand. A player script cannot drop a random .cpp on disk and import it.
On Linux, the executable must export those symbols (ENABLE_EXPORTS / -rdynamic).
Workshop plugins
The host loads an already-compiled library. ReScripted calls rescripted_register(Engine&) (or whatever you set with set_plugin_entry / imports.plugin_entry). That function typically add_librarys its packages. Same ABI as the app: include ReScripted.h, compile a shared library.
extern "C" void rescripted_register(rescripted::Engine& engine) {
engine.add_library("extra", ping);
}
engine.load_plugin("mods/extra.dylib");
Import on every run
"standard_library": { "automatically_imported": ["math"] }
Every run() acts as if the file started with import math. You still have to add_library("math", ...) yourself.
What is not a library
bind("print", …)— always there, no importload_file("quest.mini")— a game script, not a packagemylang.json— the language, compiled in separately