SanderMertens / flecs

A fast entity component system (ECS) for C & C++
https://www.flecs.dev
Other
6.47k stars 454 forks source link

Flecs with C99 and declaration decoupled from definition causes issues with ASAN #1011

Closed tanis2000 closed 1 year ago

tanis2000 commented 1 year ago

I have a C99 project using flecs and the code is spread across different implementation .c files. I noticed that when I enable ASAN and use ECS_DECLARE and ECS_DEFINE, suddenly something different happens during compilation and I start getting errors about duplicate symbols.

As an example, I have the following (stripped down example):

types.h

typedef struct health_t {
  int32_t max_health;
  int32_t health;
  bool destroyed;
} health_t;

ECS_DECLARE(health_t);

main.c

#include "types.h"
int main(int argc, char *argv[]) {
  ECS_COMPONENT_DEFINE(game.ecs, health_t);
}

hero.c

#include "types.h"

extern struct game_t game;

ecs_entity_t hero_new() {
  ecs_entity_t e = ecs_set_name(game.ecs, 0, "hero");
  ecs_set(game.ecs, e, health_t, {
    .destroyed = false,
    .max_health = 100,
    .health = 100,
  });

  return e;
}

That leads to

duplicate symbol '___odr_asan_gen_FLECS_IDhealth_tID_' in:
    CMakeFiles/game-template.dir/src/hero.c.o
    CMakeFiles/game-template.dir/src/main.c.o
duplicate symbol '_FLECS_IDhealth_tID_' in:
    CMakeFiles/game-template.dir/src/hero.c.o
    CMakeFiles/game-template.dir/src/main.c.o

Do you have any idea how to fix this issue?

SanderMertens commented 1 year ago

What you need to do is:

in types.h, add extern:

extern ECS_DECLARE(health_t);

in main.c, add the declaration:

ECS_DECLARE(health_t);

If you don't do that, the variable will get declared in each source file that includes the header, which leads to duplicate symbols.

tanis2000 commented 1 year ago

Thanks. I didn't look at what the macros look like. So ECS_DECLARE is actually declaring a variable. Now it makes sense that it gets redeclared many times as I include the same header multiple times :) Thanks for pointing this out! Awesome project btw ;)

SanderMertens commented 1 year ago

Thanks! You're right, I should probably make this more clear in the documentation.