0

I've been trying to make a c++ static library using cmake on linux, but I keep getting undefined reference errors

cmake_minimum_required(VERSION 3.0.0)
project(eecsge VERSION 0.1.0)

include(CTest)
enable_testing()

include_directories(.)

set(SRCS
    EECSGE/core/src/ComponentManager.cpp
    EECSGE/core/src/Coordinator.cpp
    EECSGE/core/src/EntityManager.cpp
    EECSGE/core/src/SystemManager.cpp
)

set(SYSTEMS
    EECSGE/systems/src/animation.cpp
    EECSGE/systems/src/background.cpp
    EECSGE/systems/src/collision.cpp
    EECSGE/systems/src/death.cpp
    EECSGE/systems/src/drawable.cpp
    EECSGE/systems/src/movement.cpp
    EECSGE/systems/src/player.cpp
    EECSGE/systems/src/sound.cpp
)

include(FetchContent)
FetchContent_Declare(SFML
    GIT_REPOSITORY https://github.com/SFML/SFML.git
    GIT_TAG 2.5.x)
FetchContent_MakeAvailable(SFML)
FetchContent_Declare(GTEST
    GIT_REPOSITORY https://github.com/google/googletest
    GIT_TAG v1.13.x)
FetchContent_MakeAvailable(GTEST)

add_library(eecsge STATIC ${SRCS} ${SYSTEMS})

target_link_libraries(eecsge sfml-audio sfml-graphics sfml-system sfml-window gtest gtest_main)

target_include_directories(eecsge PUBLIC
  $<BUILD_INTERFACE:${${CMAKE_CURRENT_SOURCE_DIR}}>
  PRIVATE ${${CMAKE_CURRENT_SOURCE_DIR}}/EECSGE/core/include
  ${${CMAKE_CURRENT_SOURCE_DIR}}/EECSGE/systems/include
  ${${CMAKE_CURRENT_SOURCE_DIR}}/EECSGE/components
)

Here is the directory organization

EECSGE
├── components
│   ├── collision.hpp
│   ├── Components.hpp
│   ├── drawable.hpp
│   ├── health.hpp
│   ├── input.hpp
│   ├── movement.hpp
│   ├── sound.hpp
│   └── transform.hpp
├── core
│   ├── Core.hpp
│   ├── include
│   │   ├── ComponentManager.hpp
│   │   ├── Coordinator.hpp
│   │   ├── EntityManager.hpp
│   │   ├── IComponentArray.hpp
│   │   ├── System.hpp
│   │   ├── SystemManager.hpp
│   │   └── Types.hpp
│   └── src
│       ├── ComponentManager.cpp
│       ├── Coordinator.cpp
│       ├── EntityManager.cpp
│       └── SystemManager.cpp
├── EECSGE.hpp
└── systems
    ├── include
    │   ├── animation.hpp
    │   ├── background.hpp
    │   ├── collision.hpp
    │   ├── death.hpp
    │   ├── drawable.hpp
    │   ├── movement.hpp
    │   ├── player.hpp
    │   └── sound.hpp
    ├── src
    │   ├── animation.cpp
    │   ├── background.cpp
    │   ├── collision.cpp
    │   ├── death.cpp
    │   ├── drawable.cpp
    │   ├── movement.cpp
    │   ├── player.cpp
    │   └── sound.cpp
    └── Systems.hpp

Yes it's not pretty, I plan on refactoring when i'm done, but I want to be able to test what I have already.

Here is some of the errors I get when trying to use this library with another program

/usr/bin/ld: CMakeFiles/Demo.dir/demo/demo.cpp.o: in function `init_player()':
demo.cpp:(.text+0x377): undefined reference to `void Coordinator::AddComponent<Transform>(unsigned int, Transform)'
/usr/bin/ld: demo.cpp:(.text+0x3e8): undefined reference to `void Coordinator::AddComponent<Movement>(unsigned int, Movement)'
/usr/bin/ld: demo.cpp:(.text+0x471): undefined reference to `void Coordinator::AddComponent<Drawable>(unsigned int, Drawable)'
/usr/bin/ld: demo.cpp:(.text+0x4f6): undefined reference to `void Coordinator::AddComponent<InputKeys>(unsigned int, InputKeys)'
/usr/bin/ld: demo.cpp:(.text+0x516): undefined reference to `void Coordinator::AddComponent<Collision>(unsigned int, Collision)'
/usr/bin/ld: demo.cpp:(.text+0x537): undefined reference to `void Coordinator::AddComponent<Health>(unsigned int, Health)'
/usr/bin/ld: CMakeFiles/Demo.dir/demo/demo.cpp.o: in function `init_enemy()':
demo.cpp:(.text+0x91e): undefined reference to `void Coordinator::AddComponent<Transform>(unsigned int, Transform)'
/usr/bin/ld: demo.cpp:(.text+0x98f): undefined reference to `void Coordinator::AddComponent<Movement>(unsigned int, Movement)'
/usr/bin/ld: demo.cpp:(.text+0xa1b): undefined reference to `void Coordinator::AddComponent<Drawable>(unsigned int, Drawable)'
/usr/bin/ld: demo.cpp:(.text+0xa46): undefined reference to `void Coordinator::AddComponent<Collision>(unsigned int, Collision)'
/usr/bin/ld: demo.cpp:(.text+0xa67): undefined reference to `void Coordinator::AddComponent<Health>(unsigned int, Health)'
/usr/bin/ld: CMakeFiles/Demo.dir/demo/demo.cpp.o: in function `init_background(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, sf::Vector2<float>, sf::Vector2<float>)':
demo.cpp:(.text+0xee3): undefined reference to `void Coordinator::AddComponent<Transform>(unsigned int, Transform)'
/usr/bin/ld: demo.cpp:(.text+0xf45): undefined reference to `void Coordinator::AddComponent<Movement>(unsigned int, Movement)'
/usr/bin/ld: demo.cpp:(.text+0xfd1): undefined reference to `void Coordinator::AddComponent<Drawable>(unsigned int, Drawable)'
/usr/bin/ld: CMakeFiles/Demo.dir/demo/demo.cpp.o: in function `main':
demo.cpp:(.text+0x1743): undefined reference to `void Coordinator::RegisterComponent<Movement>()'
/usr/bin/ld: demo.cpp:(.text+0x1752): undefined reference to `void Coordinator::RegisterComponent<Transform>()'
/usr/bin/ld: demo.cpp:(.text+0x1761): undefined reference to `void Coordinator::RegisterComponent<InputKeys>()'
/usr/bin/ld: demo.cpp:(.text+0x1770): undefined reference to `void Coordinator::RegisterComponent<Drawable>()'
/usr/bin/ld: demo.cpp:(.text+0x177f): undefined reference to `void Coordinator::RegisterComponent<Collision>()'
/usr/bin/ld: demo.cpp:(.text+0x178e): undefined reference to `void Coordinator::RegisterComponent<Health>()'
/usr/bin/ld: demo.cpp:(.text+0x17a7): undefined reference to `std::shared_ptr<PlayerSystem> Coordinator::RegisterSystem<PlayerSystem>()'
/usr/bin/ld: demo.cpp:(.text+0x17c0): undefined reference to `std::shared_ptr<DrawSystem> Coordinator::RegisterSystem<DrawSystem>()'
/usr/bin/ld: demo.cpp:(.text+0x17d9): undefined reference to `std::shared_ptr<CollisionSystem> Coordinator::RegisterSystem<CollisionSystem>()'
/usr/bin/ld: demo.cpp:(.text+0x17f2): undefined reference to `std::shared_ptr<MovementSystem> Coordinator::RegisterSystem<MovementSystem>()'
/usr/bin/ld: demo.cpp:(.text+0x180b): undefined reference to `std::shared_ptr<DeathSystem> Coordinator::RegisterSystem<DeathSystem>()'
/usr/bin/ld: demo.cpp:(.text+0x1824): undefined reference to `std::shared_ptr<AnimationSystem> Coordinator::RegisterSystem<AnimationSystem>()'
/usr/bin/ld: demo.cpp:(.text+0x183d): undefined reference to `std::shared_ptr<BackgroundSystem> Coordinator::RegisterSystem<BackgroundSystem>()'
/usr/bin/ld: demo.cpp:(.text+0x1857): undefined reference to `unsigned char Coordinator::GetComponentType<Movement>()'
/usr/bin/ld: demo.cpp:(.text+0x1880): undefined reference to `unsigned char Coordinator::GetComponentType<Transform>()'
/usr/bin/ld: demo.cpp:(.text+0x18b3): undefined reference to `void Coordinator::SetSystemSignature<MovementSystem>(std::bitset<32ul>)'
/usr/bin/ld: demo.cpp:(.text+0x18cd): undefined reference to `unsigned char Coordinator::GetComponentType<Transform>()'
/usr/bin/ld: demo.cpp:(.text+0x18f6): undefined reference to `unsigned char Coordinator::GetComponentType<Drawable>()'
/usr/bin/ld: demo.cpp:(.text+0x1929): undefined reference to `void Coordinator::SetSystemSignature<DrawSystem>(std::bitset<32ul>)'
/usr/bin/ld: demo.cpp:(.text+0x1943): undefined reference to `unsigned char Coordinator::GetComponentType<InputKeys>()'
/usr/bin/ld: demo.cpp:(.text+0x1976): undefined reference to `void Coordinator::SetSystemSignature<PlayerSystem>(std::bitset<32ul>)'
/usr/bin/ld: demo.cpp:(.text+0x198f): undefined reference to `void Coordinator::SetSystemSignature<AnimationSystem>(std::bitset<32ul>)'
/usr/bin/ld: demo.cpp:(.text+0x19a9): undefined reference to `unsigned char Coordinator::GetComponentType<Drawable>()'
/usr/bin/ld: demo.cpp:(.text+0x19d2): undefined reference to `unsigned char Coordinator::GetComponentType<Collision>()'
/usr/bin/ld: demo.cpp:(.text+0x19fb): undefined reference to `unsigned char Coordinator::GetComponentType<Health>()'
/usr/bin/ld: demo.cpp:(.text+0x1a2e): undefined reference to `void Coordinator::SetSystemSignature<CollisionSystem>(std::bitset<32ul>)'
/usr/bin/ld: demo.cpp:(.text+0x1a48): undefined reference to `unsigned char Coordinator::GetComponentType<Health>()'
/usr/bin/ld: demo.cpp:(.text+0x1a7b): undefined reference to `void Coordinator::SetSystemSignature<DeathSystem>(std::bitset<32ul>)'
/usr/bin/ld: demo.cpp:(.text+0x1a95): undefined reference to `unsigned char Coordinator::GetComponentType<Drawable>()'
/usr/bin/ld: demo.cpp:(.text+0x1abe): undefined reference to `unsigned char Coordinator::GetComponentType<Transform>()'
/usr/bin/ld: demo.cpp:(.text+0x1af1): undefined reference to `void Coordinator::SetSystemSignature<BackgroundSystem>(std::bitset<32ul>)'
/usr/bin/ld: _deps/eecsge-build/libeecsge.a(animation.cpp.o): in function `AnimationSystem::Update()':
animation.cpp:(.text+0x6f): undefined reference to `Transform& Coordinator::GetComponent<Transform>(unsigned int)'
/usr/bin/ld: animation.cpp:(.text+0x8a): undefined reference to `Movement& Coordinator::GetComponent<Movement>(unsigned int)'
/usr/bin/ld: animation.cpp:(.text+0xa5): undefined reference to `Drawable& Coordinator::GetComponent<Drawable>(unsigned int)'
/usr/bin/ld: _deps/eecsge-build/libeecsge.a(background.cpp.o): in function `BackgroundSystem::Update()':
background.cpp:(.text+0x6f): undefined reference to `Transform& Coordinator::GetComponent<Transform>(unsigned int)'
/usr/bin/ld: background.cpp:(.text+0x8a): undefined reference to `Drawable& Coordinator::GetComponent<Drawable>(unsigned int)'
/usr/bin/ld: _deps/eecsge-build/libeecsge.a(collision.cpp.o): in function `CollisionSystem::Update(float)':
collision.cpp:(.text+0x108): undefined reference to `Collision& Coordinator::GetComponent<Collision>(unsigned int)'
/usr/bin/ld: collision.cpp:(.text+0x12a): undefined reference to `Collision& Coordinator::GetComponent<Collision>(unsigned int)'
/usr/bin/ld: collision.cpp:(.text+0x160): undefined reference to `Drawable& Coordinator::GetComponent<Drawable>(unsigned int)'
/usr/bin/ld: collision.cpp:(.text+0x18f): undefined reference to `Drawable& Coordinator::GetComponent<Drawable>(unsigned int)'
/usr/bin/ld: collision.cpp:(.text+0x235): undefined reference to `Health& Coordinator::GetComponent<Health>(unsigned int)'
/usr/bin/ld: collision.cpp:(.text+0x25b): undefined reference to `Health& Coordinator::GetComponent<Health>(unsigned int)'
/usr/bin/ld: _deps/eecsge-build/libeecsge.a(death.cpp.o): in function `DeathSystem::Update()':
death.cpp:(.text+0x6c): undefined reference to `Health& Coordinator::GetComponent<Health>(unsigned int)'
/usr/bin/ld: _deps/eecsge-build/libeecsge.a(drawable.cpp.o): in function `DrawSystem::DrawEntities(sf::RenderWindow*)':
drawable.cpp:(.text+0x74): undefined reference to `Transform& Coordinator::GetComponent<Transform>(unsigned int)'
/usr/bin/ld: drawable.cpp:(.text+0x8f): undefined reference to `Movement& Coordinator::GetComponent<Movement>(unsigned int)'
/usr/bin/ld: drawable.cpp:(.text+0xaa): undefined reference to `Drawable& Coordinator::GetComponent<Drawable>(unsigned int)'
/usr/bin/ld: _deps/eecsge-build/libeecsge.a(movement.cpp.o): in function `MovementSystem::Update()':
movement.cpp:(.text+0x6d): undefined reference to `Movement& Coordinator::GetComponent<Movement>(unsigned int)'
/usr/bin/ld: movement.cpp:(.text+0x85): undefined reference to `Transform& Coordinator::GetComponent<Transform>(unsigned int)'
/usr/bin/ld: _deps/eecsge-build/libeecsge.a(player.cpp.o): in function `PlayerSystem::Shoot(Transform&, Movement&)':
player.cpp:(.text+0x1eb): undefined reference to `void Coordinator::AddComponent<Movement>(unsigned int, Movement)'
/usr/bin/ld: player.cpp:(.text+0x328): undefined reference to `void Coordinator::AddComponent<Drawable>(unsigned int, Drawable)'
/usr/bin/ld: player.cpp:(.text+0x46f): undefined reference to `void Coordinator::AddComponent<Transform>(unsigned int, Transform)'
/usr/bin/ld: player.cpp:(.text+0x48f): undefined reference to `void Coordinator::AddComponent<Collision>(unsigned int, Collision)'
/usr/bin/ld: player.cpp:(.text+0x4b0): undefined reference to `void Coordinator::AddComponent<Health>(unsigned int, Health)'
/usr/bin/ld: _deps/eecsge-build/libeecsge.a(player.cpp.o): in function `PlayerSystem::Update(sf::Event)':
player.cpp:(.text+0x5f6): undefined reference to `InputKeys& Coordinator::GetComponent<InputKeys>(unsigned int)'
/usr/bin/ld: player.cpp:(.text+0x611): undefined reference to `Movement& Coordinator::GetComponent<Movement>(unsigned int)'
/usr/bin/ld: player.cpp:(.text+0x62c): undefined reference to `Transform& Coordinator::GetComponent<Transform>(unsigned int)'
collect2: error: ld returned 1 exit status

Any help would be appreciated

  • There is nothing wrong with the directory organization. I however will put a CMakeLists.txt in nearly every folder of the hierarchy ending at the target level (unless a target is further subdivided into logical sections) – drescherjm Feb 14 '23 at 19:47
  • 1
    My guess is whatever bug you have is in the CMakeLists.txt file for the demo application and not the CMakeLists.txt file for the `EECSGE` library. However there could be other bugs. Like trying to implement your template functions in the `.cpp` files and not in the `.hpp` files. Like `void Coordinator::AddComponent<>` – drescherjm Feb 14 '23 at 20:07
  • `${${CMAKE_CURRENT_SOURCE_DIR}}` looks very weird. – Botje Feb 14 '23 at 20:37
  • @drescherjm all the functions for every class is implemented in the cpp files – The Walrus Gaming Feb 14 '23 at 20:48
  • Then I believe it's a duplicate of this: [https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file](https://stackoverflow.com/questions/495021/why-can-templates-only-be-implemented-in-the-header-file) – drescherjm Feb 14 '23 at 20:49
  • @drescherjm You are indeed right, I swapped the implementations to the header files and it works like a charm now, Thank you so much!!! – The Walrus Gaming Feb 14 '23 at 21:08

1 Answers1

0

Then I believe it's a duplicate of this: Why can templates only be implemented in the header file? – drescherjm 19 mins ago

Because I had implemented the Core files in .cpp, it caused problems. Re-implementing them in the .hpp files worked.