【问题标题】:CMake source files cannot find header filesCMake 源文件找不到头文件
【发布时间】:2020-06-03 14:27:38
【问题描述】:

我有一个项目,我使用 CMake 的结构如下:

CMakeLists.txt
├── build
├── include
│   ├── AudioDevice.h
│   ├── Game.h
│   ├── game_objects
│   │   ├── Ball.h
│   │   ├── Brick.h
│   │   ├── GameObject.h
│   │   ├── IndestructibleBrick.h
│   │   ├── MoveableGameObject.h
│   │   ├── Physics.h
│   │   ├── Platform.h
│   │   └── Wall.h
│   ├── GameParameter.h
│   ├── InputHandler.h
│   ├── Level.h
│   ├── Renderer.h
│   └── SDL_RAII.h
├── src
│   ├── AudioDevice.cpp
│   ├── Game.cpp
│   ├── game_objects
│   │   ├── Ball.cpp
│   │   ├── Brick.cpp
│   │   ├── GameObject.cpp
│   │   ├── MoveableGameObject.cpp
│   │   ├── Physics.cpp
│   │   └── Platform.cpp
│   ├── GameParameter.cpp
│   ├── InputHandler.cpp
│   ├── Level.cpp
│   ├── main.cpp
│   ├── Renderer.cpp
│   └── SDL_RAII.cpp
├── test
│   ├── game_objects
│   │   ├── Ball_test.cpp
│   │   ├── Brick_test.cpp
│   │   ├── GameObject_test.cpp
│   │   ├── MoveableGameObject_test.cpp
│   │   ├── Physics_test.cpp
│   │   └── Platform_test.cpp
│   └── Level_test.cpp

现在我想通过 CMake 改进项目的组织方式。目前我在根目录中只有一个CMakeLists.txt。好的做法是在每个文件夹中都有它。

我在根目录下的CMakeLists.txt目前看起来是这样的:

cmake_minimum_required(VERSION 3.7)

add_definitions(-std=c++17)

set(CXX_FLAGS "-Wall")
set(CMAKE_CXX_FLAGS, "${CXX_FLAGS}")

set(CMAKE_CXX_CLANG_TIDY clang-tidy -checks=-*,readability-*)

project(bricks)

list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)

set(LIBRARY_OUTPUT_PATH "${CMAKE_SOURCE_DIR}/lib")

#set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")

find_package(SDL2 REQUIRED)
find_package(SDL2_mixer REQUIRED)

include_directories(
    ${SDL2_INCLUDE_DIRS} 
    ${SDL2_mixer_INCLUDE_DIRS} 
    include 
    include/game_objects
    include/types
    include/utility 
)

add_subdirectory(thirdparty/googletest)

add_executable(bricks 
    src/game_objects/Ball.cpp
    src/game_objects/Brick.cpp
    src/game_objects/GameObject.cpp
    src/game_objects/MoveableGameObject.cpp
    src/game_objects/Physics.cpp
    src/game_objects/Platform.cpp

    src/AudioDevice.cpp
    src/Game.cpp
    src/GameParameter.cpp
    src/InputHandler.cpp
    src/Level.cpp
    src/main.cpp
    src/Renderer.cpp
    src/SDL_RAII.cpp
)

target_link_libraries(
    bricks 
    SDL2::Main
    SDL2::Mixer
)

add_executable(test 
    test/game_objects/Ball_test.cpp
    src/game_objects/Ball.cpp
    test/game_objects/Brick_test.cpp
    src/game_objects/Brick.cpp
    test/game_objects/GameObject_test.cpp
    src/game_objects/GameObject.cpp
    test/game_objects/MoveableGameObject_test.cpp
    src/game_objects/MoveableGameObject.cpp
    test/game_objects/Physics_test.cpp
    src/game_objects/Physics.cpp
    test/game_objects/Platform_test.cpp
    src/game_objects/Platform.cpp

# needs to be added so linker works with level
    src/GameParameter.cpp

    test/Level_test.cpp
    src/Level.cpp
)

target_link_libraries(test 
    gtest_main 
)

现在我认为作为第一步,最好将文件夹 src 中的内容放在它自己的 CMakeLists.txt 中。

所以我的根文件变成了这样:

cmake_minimum_required(VERSION 3.7)

add_definitions(-std=c++17)

set(CXX_FLAGS "-Wall")
set(CMAKE_CXX_FLAGS, "${CXX_FLAGS}")

set(CMAKE_CXX_CLANG_TIDY clang-tidy -checks=-*,readability-* -fix)

project(bricks)

list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)

set(LIBRARY_OUTPUT_PATH "${CMAKE_SOURCE_DIR}/lib")

#set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")

find_package(SDL2 REQUIRED)
find_package(SDL2_mixer REQUIRED)

add_subdirectory(src)

add_subdirectory(thirdparty/googletest)

add_executable(test 
    test/game_objects/Ball_test.cpp
    src/game_objects/Ball.cpp
    test/game_objects/Brick_test.cpp
    src/game_objects/Brick.cpp
    test/game_objects/GameObject_test.cpp
    src/game_objects/GameObject.cpp
    test/game_objects/MoveableGameObject_test.cpp
    src/game_objects/MoveableGameObject.cpp
    test/game_objects/Physics_test.cpp
    src/game_objects/Physics.cpp
    test/game_objects/Platform_test.cpp
    src/game_objects/Platform.cpp

    src/GameParameter.cpp

    test/Level_test.cpp
    src/Level.cpp
)

target_link_libraries(test 
    gtest_main 
)

我在src创建了这个文件:

include_directories(
    ${SDL2_INCLUDE_DIRS} 
    ${SDL2_mixer_INCLUDE_DIRS} 
    ../include 
    ../include/game_objects
    ../include/types
    ../include/utility 
)

add_executable(bricks 
    game_objects/Ball.cpp
    game_objects/Brick.cpp
    game_objects/GameObject.cpp
    game_objects/MoveableGameObject.cpp
    game_objects/Physics.cpp
    game_objects/Platform.cpp


    AudioDevice.cpp
    Game.cpp
    GameParameter.cpp
    InputHandler.cpp
    Level.cpp
    main.cpp
    Renderer.cpp
    SDL_RAII.cpp
)

target_link_libraries(
    bricks 
    SDL2::Main
    SDL2::Mixer
)

现在当我运行 CMake 时它不起作用。我在Ball.cpp 和其他文件中抱怨找不到头文件。我以为我用include_directories 添加了它们。

我真的不知道这里发生了什么。我已经用谷歌搜索了这个问题,但找不到解决方案。

如果有人能给我提示如何很好地重组,我将不胜感激。

【问题讨论】:

  • 编译 Ball.cpp 时遇到的确切错误是什么?使用的完整命令行是什么? (使用make VERBOSE=1 构建)
  • 这能回答你的问题吗? Cmake include_directories() 使用include_directories() 命令将包含目录应用到当前 目录及其下面的目录。因此,根 CMakeLists.txt 文件中的源文件将不了解您的头文件。您应该将此调用移至您的 top-level CMake 文件。更好的是,您应该考虑放弃 include_directories() 以支持 target_include_directories(),这将基于每个目标应用包含目录。
  • 我之前已经检查过该链接,但我不明白该怎么做。你能举一个我的结构的例子吗?此外,target_include_directories

标签: c++ cmake


【解决方案1】:

include_directories() 命令将列出的包含目录应用于当前 CMake 文件中的目标以及子目录中的目标。因此,include_directories() 命令不会将包含目录应用到顶级 CMake 文件中的 test 目标。因此,为您的test 可执行文件列出的源将不了解您列出的包含目录。一个简单的解决方法是将 include_directories() 调用移动到您的顶级 CMake 文件:

... 

include_directories(
    ${SDL2_INCLUDE_DIRS} 
    ${SDL2_mixer_INCLUDE_DIRS} 
    ${CMAKE_SOURCE_DIR}/include 
    ${CMAKE_SOURCE_DIR}/include/game_objects
    ${CMAKE_SOURCE_DIR}/include/types
    ${CMAKE_SOURCE_DIR}/include/utility 
)

add_subdirectory(src)

add_subdirectory(thirdparty/googletest)

add_executable(test 
    test/game_objects/Ball_test.cpp
    src/game_objects/Ball.cpp
    test/game_objects/Brick_test.cpp
    src/game_objects/Brick.cpp
    test/game_objects/GameObject_test.cpp
    src/game_objects/GameObject.cpp
    test/game_objects/MoveableGameObject_test.cpp
    src/game_objects/MoveableGameObject.cpp
    test/game_objects/Physics_test.cpp
    src/game_objects/Physics.cpp
    test/game_objects/Platform_test.cpp
    src/game_objects/Platform.cpp
    src/GameParameter.cpp
    test/Level_test.cpp
    src/Level.cpp
)

target_link_libraries(test 
    gtest_main 
)

您还应该使用变量CMAKE_SOURCE_DIR 来获取顶级 CMake 文件的完整路径,以避免使用相对路径。


FWIW,我不知道有任何指南声称您应该在项目的每个子目录中都有一个 CMakeLists.txt 文件。在项目层次结构中构建 CMakeLists.txt 文件的方式显然取决于文件在文件系统中的布局方式、每个 CMakeLists.txt 文件的长度以及其他设计决策。对于大型项目,我发现每个目标 都有一个 CMakeLists.txt 文件是很常见的。

【讨论】:

  • 感谢您的回答。我尝试将测试也添加到测试文件夹中自己的文件中,但失败了。我是这样添加的:add_subdirectory(test) 在主文件中。在测试文件add_executable(test game_objects/Ball_test.cpp ../src/game_objects/Ball.cpp 和底部target_link_libraries(test gtest_main ) 但它失败了CMake Error: Cannot open file for write: /mnt/Programmierung/Cpp/Udacity/Project/Bricks/build/test/CMakeFiles/test.dir/build.make.tmp
猜你喜欢
  • 2015-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-12-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多