Hot++ is a scripting layer for C++ programs. You write a class in a script. The program compiles the script to native code and loads it. When you save the script, the running program reloads it. Live objects keep their state.
A script can derive from a native C++ class. It calls the C++ API directly. There are no bindings and no wrapper code.
- Rapid prototyping: change the code and see the result in the running program.
- Run-time code reload with state transfer: objects stay alive, and their field values move to the new code.
- Scripting without bindings: a script has full access to the C++ API of the host.
- Games: the target is a game or an engine with a frame loop and native classes.
A .hot script. Wolf derives from the host class Creature (see samples/aot):
using "Creature.h";
using <string>;
class Wolf : Creature {
int bites = 0;
override void Tick(float dt) {
bites = bites + 1;
Hp = Hp - 1;
std.string line = "${Name}: bites=${bites} hp=${Hp:03d}";
std.printf("[wolf] %s\n", line.c_str());
}
}
The host loads generation 1, makes an object and reloads (trimmed from samples/hot-reload):
hot::Loader loader;
auto backend = hot::make_default_backend(options); // JIT or clang files
loader.load(std::move(*backend->load({path, text_v1, {}}, 1).module));
std::unique_ptr<Creature> wolf(static_cast<Creature*>(loader.find("Wolf")->create().native));
wolf->Tick(1.0f / 60.0f);
loader.request_reload(backend->load({path, text_v2, {}}, 2)); // validate
loader.commit_pending(); // swap, at a safe point
wolf->Tick(1.0f / 60.0f); // same pointer, new code- Parse:
lexyreads a.hotscript.libclangreads a.cppscript. - Check:
libclangreads the native headers. Hot++ finds the base classes, the virtual methods and the types. - Translate to C++:
hotcwrites a state struct, a shell class that derives from the native base, and a slot table. - Compile: Clang compiles the C++ in the process (JIT), through
clang++(clang files), or ahead of time (AOT). - Load and swap: the loader moves the fields to the new generation and swaps the slot table. The shell keeps its address.
See Introduction for the generated code. What Hot++ uses:
- lexy: the parser of the
.hotsyntax. libclang(C API): reads the native headers and the.cppscripts.- Clang: compiles the generated C++, as a library (JIT) or as
clang++(files). - LLVM ORC (
LLJIT): loads the compiled code in the process and unloads it. - fmt: string interpolation
${}in C++17. C++20 can usestd::format. - nlohmann_json and
clangd: the language serverhot-ls. - CMake with
CPM.cmake: the build, and the fetch of missing packages. GoogleTest runs the tests.
.hot: a C#-like syntax with handles, properties,foreach, lambdas and string interpolation..cpp: a plain C++ file. A normal build compiles it, andhotctranslates it for reload.- Native C++: the host code, and the reference for speed.
The numbers come from bench_backends (Release build, median of 3 runs). See Benchmarks.
- A loop inside a script runs at native speed (0.94x to 1.0x), for
.hotand for.cpp. - A call from the host into a script costs 2.2x to 2.4x of a native virtual call in
filesandaot(about 2 ns more). Injitit costs 2.9x. newand free of a.hotobject cost 47 to 50 ns (4.4x to 4.6x ofstd::make_shared).
Hot++ needs CMake 3.20 and a Clang C++ compiler with libclang. The JIT also needs the LLVM and Clang development packages.
set(CMAKE_CXX_STANDARD 17)
set(HOT_ROOT "/path/to/hotpp" CACHE PATH "The Hot++ source tree")
add_subdirectory(${HOT_ROOT} hot)
add_executable(myapp main.cpp)
hot_add_host(TARGET myapp MODE HOT_RELOAD SCRIPTS wolf.hot
INCLUDES ${CMAKE_CURRENT_SOURCE_DIR} DEPENDS Creature.h)MODE is AOT, AOT_RELOAD, HOT_RELOAD or PRECOMPILED. See CMake. To build Hot++ and run its tests, use cmake --preset linux-clang-files, then cmake --build --preset linux-clang-files-dbg and ctest --preset linux-clang-files-dbg.
The prebuilt SDKs for Linux and Windows are in the release latest. Use them with find_package(Hot) and CMAKE_PREFIX_PATH. See Download the SDK.
The documentation is at https://rokups.github.io/hotpp/: Introduction, Getting started, Hot reload, the .hot language, C++ scripts, Embedding, Tools and Development notes.
Each folder in samples/ shows one way to host Hot++: aot, aot-reload, runtime-compile, precompiled-library, hot-reload, clang-files-backend, jit-backend and imgui.
- Linux: tested with Clang, also under ASan and TSan.
- Windows: MSVC builds the host, and the tests pass on Windows. A MinGW host also works. See Windows.
- macOS: experimental. The code has macOS branches and a CI job builds and tests them. No maintainer runs macOS. See macOS.
- Coroutines:
asyncmethods andawaitwork, and they need C++20. See Async and await.
Hot++ uses the MIT license. See LICENSE.
The LICENSE file covers all files of the repository. The pinned test inputs have no copyright header. These are the files in tests/scripts, tests/golden, tests/engine/Actor.h and the grammar samples in editors. The tests compare the line numbers of these files with expected texts, and a header shifts the lines.