Building JaiScript into a Host​

JaiScript has no dependencies and compiles with your program: add its sources, its include folder and a few compiler settings. This page gives each route in full: CMake, Visual Studio's MSBuild, Xcode and an installed package. The quickstart has the short version.

What every build needs​

SettingValueWhy
Sourcessource/jaiscript.cpp, or every .cpp under source/implementation/ (never both)One file or per file
Include pathinclude/headers are included as <jaiscript/...>
Language standardC++20
Exceptions and RTTIrequired, in the library and in every file that includes its headers. Both are every compiler's default; a project built with -fno-exceptions, -fno-rtti or /GR- cannot host JaiScript.errors reach the host as exceptions, and bound classes are matched by type
MSVC/bigobj, in your files that bind classes as well as the library's; /EHsc and /permissive- (a new project's defaults)the binder's templates overflow the default object-file section limit
MinGW GCC-Wa,-mbig-objthe COFF counterpart of /bigobj
GCC and Clang-ffp-contract=offstops a*b+c fusing into one instruction, so floating-point results match on every platform
Windows librariesws2_32 and bcryptthe debugger's sockets and the random source behind crypto::. MSVC and clang-cl pick them up from the source; a GNU linker needs them named.
Define JAISCRIPT_ENABLE_DEBUGGERoptional; for every file or nonecompiles in the debugger's socket transport (below)
Define JAISCRIPT_INTERPRETERoptional; for every file or noneadds the tree-walking interpreter (below)

Compile JaiScript's files with the same settings as yours: the same runtime library, the same NDEBUG, the same defines. NDEBUG and the diagnostic builds (JAISCRIPT_DIAG_ATOMIC_RC, JAISCRIPT_DIAG_XTHREAD_RC, JAISCRIPT_VM_COVERAGE) change class layouts, so a mismatch fails to link: MSVC reports LNK2038: mismatch detected for 'jaiscript_build_config', and GCC and Clang an undefined jai::detail::build_config_debug1_atomic_rc0_xthread_rc0_coverage0 (or the like) naming the configuration the library was not built with.

The debugger define​

JAISCRIPT_ENABLE_DEBUGGER compiles the debugger's TCP listener. Compiled in, it still opens no socket until the host calls jai::debug::listen.

BuildDefaultTo change it
CMakeon: the option JAISCRIPT_ENABLE_DEBUGGER defaults to ON and defines the macro for the library and for every target that links it-DJAISCRIPT_ENABLE_DEBUGGER=OFF for shipping and mobile builds: no socket code is compiled, and constructing a connector is a link error
MSBuild, Xcode, your own buildoff: nothing defines itadd the define to every file, in development configurations only

Platforms​

The library is verified with MSVC 19.51 (Visual Studio 18), Clang 20 and GCC 16. Its continuous integration builds and runs the full test suite, the differential fuzzer and the example hash gates, in Debug and Release, on:

PlatformCompiler
Windows x64 (Visual Studio 2026 image)MSVC, and clang-cl against the MSVC standard library
Linux x64 (Ubuntu 24.04)GCC 14, and Clang (also under ASan and UBSan)
macOS 15, Apple siliconAppleClang; a second job builds with the Xcode generator and runs the VM suite

Two more targets are checked by gates in tools/ci/gates.sh that run where their SDK is installed, not in CI: android cross-compiles the library and its suites with the NDK for arm64-v8a and 32-bit armeabi-v7a (libc++), and wasm builds the engine with Emscripten (a 32-bit target) and runs the example games under Node to the native builds' hashes.

One file or per file​

  • source/jaiscript.cpp includes every implementation file: one file adds the whole library, which compiles once and stays built. The default when you use JaiScript unchanged.
  • source/implementation/**/*.cpp is the same library as about fifty units. Use it, with parallel compilation on (MSBuild's /MP; Ninja and Xcode by default), when you work on JaiScript itself: an edit rebuilds one file.

CMake​

The library is the target JaiScript::jaiscript; linking it brings every setting above. Put the JaiScript folder inside your project (a copy elsewhere takes a binary directory too: add_subdirectory(path/to/JaiScript jaiscript)). As a subproject only the library builds, and its MSVC runtime follows yours.

CMakeLists.txt
cmake_minimum_required(VERSION 3.20)
project(my_game CXX)
add_subdirectory(JaiScript)
add_executable(my_game main.cpp)
target_link_libraries(my_game PRIVATE JaiScript::jaiscript)

Or fetch it at configure time:

CMakeLists.txt
include(FetchContent)
FetchContent_Declare(jaiscript GIT_REPOSITORY https://github.com/Devacor/jaiscript.git GIT_TAG v0.5.2)
FetchContent_MakeAvailable(jaiscript)
target_link_libraries(my_game PRIVATE JaiScript::jaiscript)

Options, set before add_subdirectory or FetchContent_MakeAvailable, or with -D:

OptionStandalone / subprojectBuilds
JAISCRIPT_BUILD_RUNNER, JAISCRIPT_BUILD_TESTS, JAISCRIPT_BUILD_EXAMPLES, JAISCRIPT_BUILD_LSP, JAISCRIPT_BUILD_SPIDERon / offthe runner, the test suite, the examples, the language server, jai_spider
JAISCRIPT_INTERPRETERon / offthe jaiscript_interpreter target
JAISCRIPT_INSTALLon / offthe install rules and the CMake package
JAISCRIPT_LTCGon / offMSVC whole-program optimization for Release (/GL, /LTCG)
JAISCRIPT_ENABLE_DEBUGGERon / onthe debugger's socket transport

Visual Studio (MSBuild)​

New to Visual Studio? Visual Studio, Step by Step goes from a fresh install to a running program, with the errors a missed step gives.

In the IDE. Add JaiScript\source\jaiscript.cpp to the project. In its Properties, for All Configurations, under C/C++:

PropertyValue
General → Additional Include Directories$(SolutionDir)JaiScript\include
Language → C++ Language StandardISO C++20 (/std:c++20); Conformance mode Yes (/permissive-)
Command Line → Additional Options/bigobj
Code Generation → Enable C++ ExceptionsYes (/EHsc), the default
Preprocessor → Preprocessor DefinitionsJAISCRIPT_ENABLE_DEBUGGER, for VS Code attach

For the per-file route add the .cpp files under JaiScript\source\implementation instead and set General → Multi-processor Compilation to Yes.

In a property sheet. The same settings in one file a project imports. Save it beside your project as jaiscript.props:

jaiscript.props
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <JaiScriptDir Condition="'$(JaiScriptDir)'==''">$(MSBuildThisFileDirectory)JaiScript\</JaiScriptDir>
    <JaiScriptPerFile Condition="'$(JaiScriptPerFile)'==''">false</JaiScriptPerFile>
  </PropertyGroup>
  <ItemDefinitionGroup>
    <ClCompile>
      <AdditionalIncludeDirectories>$(JaiScriptDir)include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
      <LanguageStandard>stdcpp20</LanguageStandard>
      <ConformanceMode>true</ConformanceMode>
      <ExceptionHandling>Sync</ExceptionHandling>
      <AdditionalOptions>/bigobj %(AdditionalOptions)</AdditionalOptions>
      <PreprocessorDefinitions>JAISCRIPT_ENABLE_DEBUGGER;%(PreprocessorDefinitions)</PreprocessorDefinitions>
    </ClCompile>
  </ItemDefinitionGroup>
  <ItemGroup Condition="'$(JaiScriptPerFile)'!='true'">
    <ClCompile Include="$(JaiScriptDir)source\jaiscript.cpp" />
  </ItemGroup>
  <ItemGroup Condition="'$(JaiScriptPerFile)'=='true'">
    <ClCompile Include="$(JaiScriptDir)source\implementation\**\*.cpp" />
  </ItemGroup>
</Project>

This sheet defines JAISCRIPT_ENABLE_DEBUGGER in every configuration; remove that line, or put a configuration condition on it, for a shipping build. Import the sheet in the .vcxproj after Microsoft.Cpp.props:

my_game.vcxproj (excerpt)
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<Import Project="jaiscript.props" />

A Directory.Build.props can carry the ItemDefinitionGroup for every project in a folder; keep the ClCompile items in the one project that compiles the library. /p:JaiScriptPerFile=true /p:MultiProcessorCompilation=true on the msbuild command line selects the per-file route.

Xcode​

Add JaiScript/source/jaiscript.cpp to your target (or the files under source/implementation/), then set in its Build Settings:

Build setting (.xcconfig name)Value
Header Search Paths (HEADER_SEARCH_PATHS)$(SRCROOT)/JaiScript/include
C++ Language Dialect (CLANG_CXX_LANGUAGE_STANDARD)C++20 (c++20)
C++ Standard Library (CLANG_CXX_LIBRARY)libc++ (the default)
Enable C++ Exceptions (GCC_ENABLE_CPP_EXCEPTIONS)Yes (the default)
Enable C++ Runtime Types (GCC_ENABLE_CPP_RTTI)Yes (the default)
Other C++ Flags (OTHER_CPLUSPLUSFLAGS)$(inherited) -ffp-contract=off
Preprocessor Macros (GCC_PREPROCESSOR_DEFINITIONS)Release: NDEBUG=1. Add JAISCRIPT_ENABLE_DEBUGGER=1 to a desktop development build only.

Xcode's Release configuration does not define NDEBUG. Add it to every target that compiles JaiScript or includes its headers. Left out of all of them, the library's assertions stay on and cost speed; left out of some, the link fails with the configuration mismatch above.

Debug and Release​

  • A Debug build checks the library's invariants with assertions and runs script many times slower. Measure Release builds, which define NDEBUG (automatic in CMake and Visual Studio).
  • MSVC whole-program optimization speeds the VM up a few percent and makes every Release link much slower.
  • Deeply recursive scripts need native stack. The engine raises a catchable error instead of crashing when the stack runs low; a host thread that runs such scripts wants a larger stack than the platform default.

An installed package​

Build and install once per configuration (Debug and Release share a prefix; the Debug library is jaiscriptd):

shell
cmake -S JaiScript -B build-jai -G Ninja -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/opt/jaiscript -DJAISCRIPT_LTCG=OFF -DJAISCRIPT_BUILD_TESTS=OFF -DJAISCRIPT_BUILD_EXAMPLES=OFF -DJAISCRIPT_BUILD_RUNNER=OFF -DJAISCRIPT_BUILD_SPIDER=OFF -DJAISCRIPT_BUILD_LSP=OFF
cmake --build build-jai
cmake --install build-jai
CMakeLists.txt
cmake_minimum_required(VERSION 3.20)
project(my_game CXX)
find_package(JaiScript 0.5 CONFIG REQUIRED)        # configure with -DCMAKE_PREFIX_PATH=/opt/jaiscript
add_executable(my_game main.cpp)
target_link_libraries(my_game PRIVATE JaiScript::jaiscript)
set_property(TARGET my_game PROPERTY MSVC_RUNTIME_LIBRARY "${JaiScript_MSVC_RUNTIME_LIBRARY}")
  • The last line matters on MSVC. A standalone JaiScript build uses the static runtime (/MT, /MTd) unless you pass CMAKE_MSVC_RUNTIME_LIBRARY, and a CMake project defaults to the DLL runtime. The package records its runtime in JaiScript_MSVC_RUNTIME_LIBRARY; without the line the link fails with LNK2038: mismatch detected for 'RuntimeLibrary'.
  • The version must share its minor. find_package(JaiScript 0.5) accepts any installed 0.5.z and refuses 0.6 (Stability).
  • From another build system, compile your files with the definitions the library was built with: its runtime, NDEBUG for a Release library, and JAISCRIPT_ENABLE_DEBUGGER unless it was configured off.

The interpreter, for checking parity​

The tree-walking interpreter (Backends) is the reference the VM is checked against. Nothing a host runs needs it, so the library compiles the VM alone, and set_backend(jai::backend_type::interpreter) throws set_backend(interpreter) is unsupported: this build has no interpreter (link jaiscript_interpreter). A program that compares the backends adds it:

  • CMake: link JaiScript::jaiscript_interpreter instead of JaiScript::jaiscript. A standalone build's test suite, fuzzer, runner and jai_spider link it.
  • Other build systems: define JAISCRIPT_INTERPRETER and add the files under source/interpreter/, or define it for source/jaiscript.cpp, which then includes them.

The runner, for trying scripts​

shell
cmake -S JaiScript -B build -G Ninja -DCMAKE_BUILD_TYPE=Release
cmake --build build --target jaiscript_runner
build/bin/jaiscript hello.jai                   # run a file; no argument starts a REPL
build/bin/jaiscript --backend=interp --warnings hello.jai

The runner registers the standard library plus file and console functions, runs on the VM, and lifts the execution budget (--budget=N puts one back).

The headers a host includes​

C++
#include <jaiscript/core/engine.hpp>              // engine, script_value, the error types
#include <jaiscript/core/dynamic_binder.hpp>      // dynamic_binder, convert_script_function
#include <jaiscript/stdlib/stdlib.hpp>            // jai::stdlib::register_all
#include <jaiscript/serialization/convenience.hpp> // jai::to_json / from_json / to_binary / from_binary
#include <jaiscript/core/engine_time.hpp>         // eng->time(): the clock scripts read
#include <jaiscript/debug/connector.hpp>          // jai::debug::listen (VS Code attach)

<jaiscript/jaiscript.hpp> pulls the core, the binder and the archives in one include (not the standard library).