Helios Engine
A modular ECS based data-oriented C++23 game engine framework
Loading...
Searching...
No Matches
Helios Engine

C++23 MIT License

Linux GCC Linux Clang Windows MSVC macOS Clang


Helios Engine Logo

Helios Engine

A modular, data-oriented C++23 game engine framework inspired by Bevy
Get Started ยป ยท Features ยท Modules ยท Build ยท Third-Party ยท Docs

Table of Contents


About The Project

Helios Engine is a high-performance, ECS-based game engine framework written in C++23. It combines an archetype-based Entity Component System with deferred commands, double-buffered messages, and parallel system scheduling over a work-stealing task executor.

โ†‘ Back to Top

Key Features

  • ECS โ€” archetype and sparse-set storage, deferred Commands, rich query iterators
  • Parallel scheduling โ€” access-conflict detection, topological execution, Taskflow-backed executors
  • Application layer โ€” App / SubApp lifecycle, builtin schedules, static and dynamic plugins
  • Modular build โ€” independent modules; enable only what you need
  • Modern C++23 โ€” concepts, ranges, std::expected, PMR allocators
  • Flexible dependencies โ€” system packages first, CPM download as fallback

Design Philosophy

  1. Data-oriented design โ€” components stored contiguously for cache-friendly iteration
  2. Composability โ€” behavior emerges from systems operating on component data
  3. Explicitness โ€” data access declared through system parameter types; schedules resolve ordering

โ†‘ Back to Top


Modules

Module Description Default Documentation
core Asserts, UUID, stack traces, CStringView ON README
platform Platform detection, HELIOS_API, debug break ON README
compiler Branch hints, feature detection macros ON README
utils TypeId, Delegate, timers, filesystem, adapters ON README
container SparseSet, MultiTypeMap, TypedBuffer, StaticString ON README
memory PMR allocators, Rc/Arc ON README
log spdlog-based typed logging ON README
async Task graphs and work-stealing executor ON README
ecs World, entities, components, schedules ON README
app Application framework, plugins, sub-apps ON README
profile Tracy / flamegraph profiling (opt-in) OFF README
window GLFW windowing (skeleton) ON README
cmake --preset linux-gcc-release -DHELIOS_BUILD_PROFILE=ON -DHELIOS_BUILD_WINDOW=OFF

โ†‘ Back to Top


Getting Started

Requirements

Tool Minimum Recommended
CMake 3.25+ 3.28+
C++ compiler GCC 14+, Clang 19+, MSVC 19.34+ GCC 15+, Clang 21+
Generator โ€” Ninja
Python 3.8+ 3.10+ (scripts, pre-commit)

Clone with submodules (needed for Doxygen theme):

git clone --recursive https://github.com/RexarX/HeliosEngine.git
cd HeliosEngine

Installing Dependencies

Helios resolves dependencies per module: system packages are tried first, then CPM download if missing (HELIOS_DOWNLOAD_PACKAGES=ON, default). Pre-installing system packages speeds up configuration and avoids network fetches.

Package names below match INSTALL_HINTS in cmake/dependencies/.

All platforms โ€” build tools

Tool Purpose
CMake โ‰ฅ 3.25 Configure and build
Ninja Recommended generator (used by presets)
clang-format Code formatting (scripts/format.py)
Doxygen API docs (scripts/docs.py) โ€” optional

Linux (APT โ€” Ubuntu / Debian)

sudo apt-get update
sudo apt-get install -y ninja-build clang-format doxygen \
libboost-all-dev libtbb-dev libspdlog-dev \
libtaskflow-cpp-dev libconcurrentqueue-dev libglfw3-dev \
doctest-dev

Optional (profile module): sudo apt-get install -y libtracy-dev

Linux (DNF โ€” Fedora)

sudo dnf install -y ninja-build clang-tools-extra doxygen \
boost-devel tbb-devel spdlog-devel taskflow-devel \
glfw-devel doctest-devel stduuid-devel

Linux (Pacman โ€” Arch)

sudo pacman -S --needed ninja clang doxygen \
boost tbb spdlog taskflow glfw doctest concurrentqueue

Optional (profile module): sudo pacman -S tracy

macOS (Homebrew)

brew install cmake ninja clang-format doxygen \
boost spdlog taskflow glfw doctest concurrentqueue

Optional (profile module): brew install tracy

Note: On Linux with GCC + libstdc++, TBB is required for parallel STL (libtbb-dev / tbb-devel / onetbb). Clang on Linux and all macOS builds use libc++ and do not require TBB. spdlog is auto-downloaded via CPM when using Clang on Linux (system Ubuntu packages are incompatible).

Windows (MSVC)

No system packages required for a minimal build โ€” MSVC + Ninja (via Visual Studio) is sufficient; missing libraries are fetched by CPM.

# Optional: LLVM clang-format for local formatting
choco install llvm
# Or use clang-format bundled with Visual Studio 2022

Building

Preset pattern: {os}-{compiler}-{build_type}

cmake --list-presets # configure presets
cmake --list-presets build # build presets
cmake --list-presets test # test presets

Linux (GCC)

cmake --preset linux-gcc-release
cmake --build --preset linux-gcc-release
ctest --preset linux-gcc-release

Linux (Clang)

cmake --preset linux-clang-release
cmake --build --preset linux-clang-release
ctest --preset linux-clang-release

Windows

Manually after vcvars64.bat:

cmake --preset windows-msvc-release
cmake --build --preset windows-msvc-release

Or generate Visual Studio solution and build from IDE:

cmake --preset windows-vs-release

macOS (Clang)

cmake --preset macos-clang-release
cmake --build --preset macos-clang-release
ctest --preset macos-clang-release

Recommended developer flags

cmake --preset linux-gcc-release \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DHELIOS_DEVELOPER_MODE=ON \
Option Default Notes
HELIOS_BUILD_TESTS ON (top-level) Module test suites
HELIOS_BUILD_EXAMPLES ON (top-level) Example applications
HELIOS_DEVELOPER_MODE OFF Sanitizers and dev checks
HELIOS_DOWNLOAD_PACKAGES ON CPM fallback for missing deps
HELIOS_BUILD_{MODULE} module default Per-module toggle

Run the Example

cmake --preset linux-gcc-release \
-DHELIOS_BUILD_EXAMPLES=ON \
-DHELIOS_BUILD_PROFILE=ON
cmake --build --preset linux-gcc-release --target simple_example
./bin/examples/debug-linux-x86_64/simple_example

See examples/simple/src/main.cpp for schedules, system sets, sub-apps, and profiling.

โ†‘ Back to Top


Usage

Systems are plain structs โ€” operator() parameters declare data access. App owns the main world, executor, and frame scheduler.

#include <utility>
inline constexpr float kVelocityBoost = 1.25F;
struct Position {
float x = 0.0F;
float y = 0.0F;
};
struct Velocity {
float dx = 1.0F;
float dy = 0.0F;
};
struct FrameCount {
size_t count = 0;
};
struct SpawnEntities {
void operator()(helios::ecs::Res<const FrameCount> frame_count,
helios::ecs::Commands commands) {
// Spawning new entity every even frame
if (frame_count->count % 2 == 0) {
commands.Spawn().AddComponents(Position{}, Velocity{});
}
}
};
struct ChangePosition {
movables.ForEach([](Position& pos, const Velocity& vel) {
pos.x += vel.dx;
pos.y += vel.dy;
});
}
};
struct ChangeVelocity {
void operator()(helios::ecs::Query<Velocity&> movables) {
movables.ForEach([](Velocity& vel) {
vel.dx *= kVelocityBoost ;
vel.dy *= kVelocityBoost ;
});
}
};
struct RequestExit {
// Sending message that would be handled in the next schedule
}
};
int main() {
app.InsertResource(FrameCount{});
app.AddSystem(helios::app::kPreUpdate, SpawnEntities{}); // Spawn entities, before modifying
app.AddSystems(helios::app::kUpdate, ChangePosition{}, ChangeVelocity{})
.Sequence(); // Sytems will run one after another (ChangePosition -> ChangeVelocity)
app.AddSystem(helios::app::kPostUpdate, RequestExit{}) // Shutdown after 500 frames
.RunIf("IsFrameCountReached", [](helios::ecs::Res<const FrameCount> frame_count) {
return frame_count->count > 500;
});
return std::to_underlying(app.Run());
}
Application class.
auto AddMessages(this auto &&self) -> decltype(std::forward< decltype(self)>(self))
Registers multiple message types on the main world.
auto AddSystem(const L &label, S &&system, ecs::SystemLocalDataOptions options={}) -> ecs::SystemHandle
Adds a functor system to a main sub-app schedule.
ecs::SystemGroupHandle AddSystems(const L &label, Systems &&... systems)
Adds multiple functor systems to the same main sub-app schedule.
ExitCode Run()
Runs the application with the given arguments.
void Write(U &&message) const
Writes a single message to the local queue.
Definition writer.hpp:49
void ForEach(const Action &action) const
Executes an action for each matching entity's components.
Definition query.hpp:1408
PmrEntityCmdBuffer Spawn()
Spawns a new entity and returns a command buffer for it.
Definition commands.hpp:99
auto AddComponents(this auto &&self, Ts &&... components) -> decltype(std::forward< decltype(self)>(self))
Enqueues a command to add components to the entity.
Read-only or mutable access to resource.
Definition param.hpp:17
constexpr PostUpdate kPostUpdate
Builtin post-update schedule.
@ kSuccess
Successful execution.
constexpr Update kUpdate
Builtin update schedule.
Definition schedules.hpp:98
constexpr PreUpdate kPreUpdate
Builtin pre-update schedule.
Definition schedules.hpp:90
PmrBasicMessageWriter< T > MessageWriter
Alias for BasicMessageWriter bound to a PMR allocator.
Definition writer.hpp:97
BasicQuery< World, std::pmr::polymorphic_allocator<>, Args... > Query
Alias for BasicQuery bound to World with a PMR allocator.
Definition query.hpp:2264
Message that requests the application to exit.
Parameter Purpose
Res<T> / Res<const T> Singleton resource access
Query<Args...> Entity iteration with With<> / Without<> filters
Commands Deferred spawn, destroy, component, and resource mutations
Local<T> Per-system persistent state
MessageWriter<T> / MessageReader<T> Frame-delayed inter-system messages Live two frames by default, visible between schedules
AsyncMessageWriter<T> / AsyncMessageReader<T> Lock-free async messages between systems

Builtin schedules (helios/app/schedules.hpp): MainStartup โ†’ PreStartup โ†’ Startup โ†’ PostStartup โ†’ First โ†’ PreUpdate โ†’ Update โ†’ PostUpdate โ†’ Last โ†’ Extract โ†’ shutdown stages.

โ†‘ Back to Top


Architecture

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ App โ”‚
โ”‚ โ”œโ”€ async::Executor (work-stealing thread pool) โ”‚
โ”‚ โ”œโ”€ Scheduler (frame stages) โ”‚
โ”‚ โ”œโ”€ SubApp (main) (ecs::World + schedules) โ”‚
โ”‚ โ”œโ”€ SubApp... (optional parallel worlds) โ”‚
โ”‚ โ””โ”€ Plugins (static + dynamic) โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ”‚ schedules โ”‚ task graphs
โ–ผ โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ” โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ ecs::Schedule โ”‚ โ”‚ async::Executor โ”‚
โ”‚ systems + DAG โ”‚ โ”‚ TaskGraph โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜ โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
โ”‚
โ–ผ
โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚ ecs::World โ”‚
โ”‚ entities ยท components ยท resources ยท messages ยท commands โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
  • Entities โ€” 64-bit ID (32-bit index + 32-bit generation), free-list recycling
  • Components โ€” archetype columns or per-type sparse sets; structural changes via deferred Commands
  • Messages โ€” double-buffered (read previous frame); async messages use lock-free queues

โ†‘ Back to Top


Using as a Dependency

Helios can be consumed from another CMake project in several ways. All methods expose targets as helios::module::<name> and the helper helios_link_modules().

Typical consumer settings when embedding:

set(HELIOS_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(HELIOS_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)

Method 1: add_subdirectory

Best for vendoring a copy inside your tree (e.g. third_party/HeliosEngine).

# YourProject/CMakeLists.txt
cmake_minimum_required(VERSION 3.25)
project(MyGame LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 23)
add_subdirectory(third_party/HeliosEngine)
add_executable(my_game src/main.cpp)
helios_link_modules(
TARGET my_game
MODULES PUBLIC app
)

Method 2: FetchContent

Fetches at configure time without a manual submodule.

include(FetchContent)
FetchContent_Declare(
HeliosEngine
GIT_REPOSITORY https://github.com/RexarX/HeliosEngine.git
GIT_TAG main
GIT_SHALLOW TRUE
)
set(HELIOS_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(HELIOS_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
FetchContent_MakeAvailable(HeliosEngine)
add_executable(my_game src/main.cpp)
helios_link_modules(
TARGET my_game
MODULES PUBLIC app
)

Method 3: CPM

Uses the same CPM integration as Helios itself (cmake/DownloadUsingCPM.cmake).

# Download CPM once (or vendor cmake/CPM.cmake)
include(cmake/DownloadUsingCPM.cmake) # from Helios, or your own CPM bootstrap
CPMAddPackage(
NAME HeliosEngine
GITHUB_REPOSITORY RexarX/HeliosEngine
GIT_TAG main
OPTIONS
"HELIOS_BUILD_TESTS OFF"
"HELIOS_BUILD_EXAMPLES OFF"
)
add_executable(my_game src/main.cpp)
helios_link_modules(
TARGET my_game
MODULES PUBLIC app
)

Method 4: Installed Package (find_package)

Build and install Helios, then use the generated CMake package config.

cmake --preset linux-gcc-release -DHELIOS_ENABLE_INSTALL=ON
cmake --build --preset linux-gcc-release
cmake --install build/linux-gcc-release --prefix /opt/helios
list(APPEND CMAKE_PREFIX_PATH "/opt/helios")
find_package(Helios REQUIRED CONFIG)
add_executable(my_game src/main.cpp)
helios_link_modules(
TARGET my_game
MODULES PUBLIC app
)

Installed artifacts: HeliosConfig.cmake, HeliosConfigVersion.cmake, HeliosTargets.cmake (see cmake/Install.cmake).

โ†‘ Back to Top


Documentation

API reference (Doxygen)

python scripts/docs.py
# โ†’ docs/doxygen/html/index.html

Config: docs/doxygen/Doxyfile.in โ€” version from project(VERSION โ€ฆ) via CMake (cmake --preset docs, cmake --build --preset docs) or scripts/docs.py.

Project guidelines

docs/guidelines.md โ€” code style, module layout, testing, build options.


Development

Code formatting

Formatting runs automatically on every local commit (via pre-commit) and is verified on every push / PR (.github/workflows/format.yaml). Unformatted code cannot land on main if hooks and CI are used.

When Mechanism
Every commit (local) pre-commit install โ€” runs python scripts/format.py (auto-fix)
Every push / PR CI โ€” python scripts/format.py --check
# Format all sources
python scripts/format.py
# Check only (same as CI)
python scripts/format.py --check
# Install local commit hook (auto-formats on commit)
pip install pre-commit
pre-commit install

Creating a Custom Module

Helios modules live under src/ by default. Register additional search paths with helios_add_extra_module_dirs() (before discovery) or HELIOS_EXTRA_MODULE_DIRS. The greeting example path is registered automatically when HELIOS_BUILD_EXAMPLES=ON. See the full walkthrough:

examples/custom_module/README.md

That example defines a minimal greeting module (registration, build target, tests, and a demo executable) under examples/custom_module/, discovered through the extra module path mechanism โ€” no manual include(Module.cmake) required.

# From a parent CMake project (before add_subdirectory(HeliosEngine)):
# list(APPEND CMAKE_MODULE_PATH ".../HeliosEngine/cmake")
# include(ModuleRegistry)
# helios_add_extra_module_dirs("${CMAKE_CURRENT_SOURCE_DIR}/modules")
# Or via cache variable:
cmake --preset linux-gcc-release \
-DHELIOS_EXTRA_MODULE_DIRS="/path/to/my/modules"

When HELIOS_BUILD_EXAMPLES=ON, Helios calls helios_add_extra_module_dirs(examples/custom_module) before discovery.

Quick layout:

examples/custom_module/
โ”œโ”€โ”€ Module.cmake # helios_register_module(...)
โ”œโ”€โ”€ CMakeLists.txt # helios_module(...) + demo target
โ”œโ”€โ”€ README.md # Step-by-step guide
โ”œโ”€โ”€ include/helios/greeting/ # Public headers
โ”œโ”€โ”€ src/ # Optional private sources
โ””โ”€โ”€ tests/ # doctest suite

Link it from your executable with helios_link_modules(TARGET โ€ฆ MODULES PUBLIC greeting).

See also docs/guidelines.md for module conventions.

Other scripts

python scripts/lint.py --build-dir build/linux-gcc-release # clang-tidy
python scripts/docs.py # Doxygen
ctest --preset linux-gcc-release # tests

โ†‘ Back to Top


Roadmap

  • Rendering module
  • Full window/input integration

โ†‘ Back to Top


Acknowledgments

Inspired by Bevy, EnTT, and Taskflow.

โ†‘ Back to Top


License

Distributed under the MIT License. See LICENSE for details.

โ†‘ Back to Top


Contact

RexarX โ€” who72.nosp@m.7car.nosp@m.es@gm.nosp@m.ail..nosp@m.com

Project: github.com/RexarX/HeliosEngine

โ†‘ Back to Top