#ecs #game #flecs


Rust bindings for the Flecs Entity Component System

4 releases

0.1.3 Apr 17, 2023
0.1.2 Apr 17, 2023
0.1.1 Aug 4, 2022
0.1.0 Aug 4, 2022

#142 in Game dev

28 downloads per month

MIT license

54K SLoC

C 52K SLoC // 0.0% comments Rust 1.5K SLoC // 0.2% comments C++ 5 SLoC

flecs-rs: Rust bindings for Flecs

Crates.io license Discord Chat

A Rust binding for the Flecs ECS library: https://github.com/SanderMertens/flecs

Wraps native Flecs v3.2.1

A Simple Example

use flecs::*;

#[derive(Default, Debug, PartialEq)]
struct Position {
    x: f32,
    y: f32,

#[derive(Default, Debug, PartialEq)]
struct Walking { }

fn main() {
    let mut world = World::new();

    // We have to manually register all components

    // Create an entity with name Bob
    let bob = world.entity().named("Bob")
        .set(Position { x: 10.0, y: 20.0 }) 

    // Get the value for the Position component
    let pos = bob.get::<Position>();
    println!("Bob position: {}, {}", pos.x, pos.y);

    // Overwrite the value of the Position component
    bob.set(Position { x: 20.0, y: 30.0 });
    println!("Bob position: {}, {}", pos.x, pos.y);

    // Create another named entity
    let alice = world.entity().named("Alice")
        .set(Position { x: 10.0, y: 20.0 });

    // Add a tag after entity is created

    // Print all of the components the entity has. This will output:
    //    Position, Walking, (Identifier,Name)
    println!("Alice type = [ {} ]", alice.type_info().to_str());

    // Remove tag

    // Iterate all entities with Position
    world.each1(|e: flecs::Entity, p: &Position| {
        println!("{}: {}, {}", e.name(), p.x, p.y);

Compiling and running the examples

git clone https://github.com/jazzay/flecs-rs
cd flecs-rs
cargo build --release

Main examples are located in the examples directory. These can be run like so:

cargo test

cargo run --example hello_world
cargo run --example prefabs

Compiling with WebAssembly

Compiling with WebAssembly requires using the wasm32-unknown-emscripten target.

This is because there is no official toolchain for C/C++ targeting wasm32-unknown-unknown, which means that C/C++ bindings with do not work with this target and will result in unresolved symbols.

The Emscripten target which is not as well supported as the wasm32-unknown-unknown, which means that wasm-bindgen and some other popular Rust libraries that target WebAssembly will not work. So be sure to keep that in mind.

Create a directory to be statically served:

mkdir static

Create a file called index.html under static/:

    <script type="module">
      import init from './systems.js'
      await init()

Emscripten Setup: A specific version of the Emscripten SDK is required. Newer versions will usually cause build or runtime errors.

On Mac you may need to make sure your Python3 SSL certs are setup: https://bugs.python.org/issue43404

make setup_emsdk EMSDK=/your/install/directory

If necessary, you can override the standard library path:

export STDLIB=/usr/include

By default it uses the EMSDK's sysroot for includes.

On some platforms you may get linker errors:


To avoid this run this prior to building: (TODO make this automatic)

emcc -c gxx_personality_v0_stub.cpp

Build WASM binary:

cargo build --example systems --target wasm32-unknown-emscripten
cp ./target/wasm32-unknown-emscripten/debug/examples/systems.js ./static/
cp ./target/wasm32-unknown-emscripten/debug/examples/systems.wasm ./static/

Serve static file locally with any HTTP server tool, for example basic-http-server:

cargo install basic-http-server
basic-http-server ./static/


~35K SLoC