Israel Calebe
Israel Calebe

Reputation: 13

CMake cannot find the header files of a git submodule

I have two git repositories with CMake, one is a game engine, and the other is a game that I am making with the game engine.

It turns out, this game engine has a submodule that is included in the project's CMakeLists.txt, and in the game repository, the game engine is added as a submodule that is also included in CMakeLists.txt. However, when compiling the two projects, the Game Engine compiles everything normal without errors, I update the game repository to update the submodules, and when compiling the game, it does not find the game engine submodule for some unknown reason.

Game Engine CMakeLists:

cmake_minimum_required(VERSION 3.8)

set(PROJECT_NAME "Enel")

set(CMAKE_CXX_STANDARD 17)

project(${PROJECT_NAME} VERSION 0.1.0)

include_directories(
    "${PROJECT_SOURCE_DIR}/include"
    "${PROJECT_SOURCE_DIR}/src"
    "${PROJECT_SOURCE_DIR}/libs/spdlog/include"
    "${PROJECT_SOURCE_DIR}/libs/spdlog/src"
)

file(GLOB SRC_FILES
    "${PROJECT_SOURCE_DIR}/include/**/*.h"
    "${PROJECT_SOURCE_DIR}/include/**/*.hh"
    "${PROJECT_SOURCE_DIR}/include/**/*.hpp"
    "${PROJECT_SOURCE_DIR}/src/**/*.c"
    "${PROJECT_SOURCE_DIR}/src/**/*.cc"
    "${PROJECT_SOURCE_DIR}/src/**/*.cpp"
)

add_library(${PROJECT_NAME} STATIC ${SRC_FILES})

Game CMakeLists:

cmake_minimum_required(VERSION 3.8)

set(PROJECT_NAME "Minicraft")

set(CMAKE_CXX_STANDARD 17)

project(${PROJECT_NAME} VERSION 0.1.0)

include_directories(
    "${PROJECT_SOURCE_DIR}/include"
    "${PROJECT_SOURCE_DIR}/src"
    "${PROJECT_SOURCE_DIR}/libs/enel/include"
    "${PROJECT_SOURCE_DIR}/libs/enel/src"
)

link_directories(${PROJECT_SOURCE_DIR}/libs/enel)

file(GLOB SRC_FILES
    "${PROJECT_SOURCE_DIR}/include/**/*.h"
    "${PROJECT_SOURCE_DIR}/include/**/*.hh"
    "${PROJECT_SOURCE_DIR}/include/**/*.hpp"
    "${PROJECT_SOURCE_DIR}/src/**/*.c"
    "${PROJECT_SOURCE_DIR}/src/**/*.cc"
    "${PROJECT_SOURCE_DIR}/src/**/*.cpp"
    "${PROJECT_SOURCE_DIR}/libs/enel/src/**/*.c"
    "${PROJECT_SOURCE_DIR}/libs/enel/src/**/*.cc"
    "${PROJECT_SOURCE_DIR}/libs/enel/src/**/*.cpp"
    "${PROJECT_SOURCE_DIR}/libs/enel/include/**/*.h"
    "${PROJECT_SOURCE_DIR}/libs/enel/include/**/*.hh"
    "${PROJECT_SOURCE_DIR}/libs/enel/include/**/*.hpp"
)

add_executable(${PROJECT_NAME} ${SRC_FILES})

Build Output:

[ 33%] Building CXX object CMakeFiles/Minicraft.dir/src/MC/Game.cc.o
In file included from /home/yorichii/repos/minicraft/libs/enel/include/Enel/Platform/EntryPoint.hh:4,
                 from /home/yorichii/repos/minicraft/src/MC/Game.cc:2:
/home/yorichii/repos/minicraft/libs/enel/include/Enel/Util/Log.hh:3:10: fatal error: spdlog/spdlog.h: Arquivo ou diretório inexistente
    3 | #include <spdlog/spdlog.h>
      |          ^~~~~~~~~~~~~~~~~
compilation terminated.
make[2]: *** [CMakeFiles/Minicraft.dir/build.make:76: CMakeFiles/Minicraft.dir/src/MC/Game.cc.o] Erro 1
make[1]: *** [CMakeFiles/Makefile2:76: CMakeFiles/Minicraft.dir/all] Erro 2
make: *** [Makefile:84: all] Erro 2

Upvotes: 1

Views: 1686

Answers (1)

Guillaume Racicot
Guillaume Racicot

Reputation: 41780

If you use directory based property like include_directory or link_directory, you'll have to repeat requirements:

include_directories(
    "${PROJECT_SOURCE_DIR}/include"
    "${PROJECT_SOURCE_DIR}/src"
    "${PROJECT_SOURCE_DIR}/libs/enel/include"
    "${PROJECT_SOURCE_DIR}/libs/enel/src"
    # Repeat all requirements
    "${PROJECT_SOURCE_DIR}/libs/enel/libs/spdlog/include"
    "${PROJECT_SOURCE_DIR}/libs/enel/libs/spdlog/src"
)

This is why you should strongly consider target based property, as all modern build system are using, including modern CMake:

In Enel:

cmake_minimum_required(VERSION 3.8)

set(PROJECT_NAME "Enel")

set(CMAKE_CXX_STANDARD 17)

project(${PROJECT_NAME} VERSION 0.1.0)

# If you can install spdlog in a local directory in the project,
# prefer find_package(spdlog REQUIRED)
add_subdirectrory(libs/spdlog)

file(GLOB SRC_FILES
    "strongly/consider/not/globbing/**/*.cpp"
)

add_library(Enel STATIC ${SRC_FILES})

target_link_libraries(Enel PUBLIC spdlog)
target_include_directories(Enel PUBLIC src include)

Then in your game, do this:

cmake_minimum_required(VERSION 3.8)

set(PROJECT_NAME "Minicraft")

set(CMAKE_CXX_STANDARD 17)

project(${PROJECT_NAME} VERSION 0.1.0)

add_subdirectory(libs/enel)

file(GLOB SRC_FILES
   ...
)

add_executable(Minicraft ${SRC_FILES})

# Links to all required libraries, add all required include directories
target_link_libraries(Minicraft PUBLIC Enel)
target_include_directory(Minicraft PUBLIC include src)

Upvotes: 2

Related Questions