【问题标题】:"Cannot open include file" when implementing library that implements GLM using CMake实现使用 CMake 实现 GLM 的库时“无法打开包含文件”
【发布时间】:2020-03-23 20:53:09
【问题描述】:

我正在使用 opengl、glfw 和 glm 创建游戏。现在我有两个项目,引擎(名为Cheetah)和游戏。引擎是一个 dll 库,游戏实现了该库。引擎和游戏项目都包含一个 CMakeLists.txt,并且有一个顶级 CMakeLists.txt 可以构建两者。 文件夹结构如下:

问题

我正在尝试将 glm 添加到库中,但现在我遇到了可以构建库但无法构建实现库的游戏项目的问题,引发编译错误:

错误 C1083 无法打开包含文件:'glm/common.hpp':没有这样的文件 或者 目录 C:\Projects\Game\out\build\x64-Debug\Game C:\Projects\Game\Cheetah\src\Engine\Renderer\OrthoGraphicCamera.h

以下是每个项目的 CMake 文件:

猎豹(引擎项目)

# CMakeList.txt : CMake project for Cheetah, include source and define
# project specific logic here.
#
cmake_minimum_required (VERSION 3.8)
project ("Cheetah")

# Platform defines
IF (WIN32)
  add_compile_definitions(CH_PLATFORM_WINDOWS)
ELSE()
  # set stuff for other systems
ENDIF()

#----------------------------------------------
# ADD CHEETAH LIBRARY
#----------------------------------------------
message(${PROJECT_SOURCE_DIR})
# Define Cheetah variables
set(LIB_DIR "${PROJECT_SOURCE_DIR}/dependencies")
set(INCLUDES_DIR_PUBLIC "${PROJECT_SOURCE_DIR}/includes")
set(INCLUDES_DIR_PRIVATE "${PROJECT_SOURCE_DIR}/src")
set(ENGINE_DIR "${PROJECT_SOURCE_DIR}/src/Engine")
set(ENGINE_CORE_DIR "${ENGINE_DIR}/Core")
set(ENGINE_INPUT_DIR "${ENGINE_DIR}/Input")
set(ENGINE_EVENTS_DIR "${ENGINE_DIR}/Events")
set(ENGINE_RENDERER_DIR "${ENGINE_DIR}/Renderer")
set(ENGINE_DEBUG_DIR "${ENGINE_DIR}/Debug")
set(ENGINE_MATH_DIR "${ENGINE_DIR}/Math")
set(ENGINE_RESOURCES_DIR "${ENGINE_DIR}/Resources")
set(PLATFORM_DIR "${PROJECT_SOURCE_DIR}/src/Platform")
set(PLATFORM_WINDOWS_DIR "${PLATFORM_DIR}/Windows")
set(PLATFORM_OPENGL_DIR "${PLATFORM_DIR}/OpenGL")

# Set default files
list(APPEND SOURCE_FILES    
    "${ENGINE_DIR}/Engine.h"
    "${ENGINE_CORE_DIR}/Application.h"
    "${ENGINE_CORE_DIR}/Application.cpp"
    "${ENGINE_CORE_DIR}/Core.h"
    "${ENGINE_CORE_DIR}/EntryPoint.h"
    "${ENGINE_CORE_DIR}/Window.h"
    "${ENGINE_CORE_DIR}/UpdateLayer.h"
    "${ENGINE_CORE_DIR}/UpdateLayer.cpp"
    "${ENGINE_CORE_DIR}/UpdateLayerQueue.h"
    "${ENGINE_CORE_DIR}/UpdateLayerQueue.cpp"
    "${ENGINE_CORE_DIR}/Time.h"
    "${ENGINE_CORE_DIR}/Time.cpp"
    "${ENGINE_RENDERER_DIR}/RenderAction.h"
    "${ENGINE_RENDERER_DIR}/RenderAction.cpp"
    "${ENGINE_RENDERER_DIR}/GraphicsContext.h"
    "${ENGINE_RENDERER_DIR}/GraphicsContext.cpp"
    "${ENGINE_RENDERER_DIR}/RenderAPI.h"
    "${ENGINE_RENDERER_DIR}/RenderAPI.cpp"
    "${ENGINE_RENDERER_DIR}/Renderer.h"
    "${ENGINE_RENDERER_DIR}/Renderer.cpp"
    "${ENGINE_RENDERER_DIR}/Renderer2D.h"
    "${ENGINE_RENDERER_DIR}/Renderer2D.cpp"
    "${ENGINE_RENDERER_DIR}/IndexBuffer.h"
    "${ENGINE_RENDERER_DIR}/IndexBuffer.cpp"
    "${ENGINE_RENDERER_DIR}/VertexBuffer.h"
    "${ENGINE_RENDERER_DIR}/VertexBuffer.cpp"
    "${ENGINE_RENDERER_DIR}/VertexArray.h"
    "${ENGINE_RENDERER_DIR}/VertexArray.cpp"
    "${ENGINE_RENDERER_DIR}/Shader.h"
    "${ENGINE_RENDERER_DIR}/Shader.cpp"
    "${ENGINE_RENDERER_DIR}/VertexBufferLayout.h"
    "${ENGINE_RENDERER_DIR}/VertexBufferLayout.cpp"
    "${ENGINE_RENDERER_DIR}/Texture.h"
    "${ENGINE_RENDERER_DIR}/Texture.cpp"
    "${ENGINE_RENDERER_DIR}/OrthoGraphicCamera.h"
    "${ENGINE_RENDERER_DIR}/OrthoGraphicCamera.cpp"
    "${ENGINE_RENDERER_DIR}/Renderer2DQueue.h"
    "${ENGINE_RENDERER_DIR}/Renderer2DQueue.cpp"
    "${ENGINE_INPUT_DIR}/Input.h"
    "${ENGINE_INPUT_DIR}/Input.cpp"
    "${ENGINE_EVENTS_DIR}/ApplicationEvents.h"
    "${ENGINE_EVENTS_DIR}/ApplicationEvents.cpp"
    "${ENGINE_EVENTS_DIR}/Event.h"
    "${ENGINE_EVENTS_DIR}/Event.cpp"
    "${ENGINE_EVENTS_DIR}/EventDispatcher.h"
    "${ENGINE_EVENTS_DIR}/EventDispatcher.cpp"
    "${ENGINE_EVENTS_DIR}/EventTypes.h"
    "${ENGINE_EVENTS_DIR}/InputEvents.h"
    "${ENGINE_EVENTS_DIR}/InputEvents.cpp"
    "${ENGINE_RESOURCES_DIR}/ResourceCache.h"
    "${ENGINE_RESOURCES_DIR}/ResourceCache.inl"
    "${ENGINE_RESOURCES_DIR}/ResourceLoader.h"
    "${ENGINE_RESOURCES_DIR}/ResourceLoader.cpp"
)
# Set platform specific files
# Windows
list(APPEND SOURCE_FILES_WINDOWS
    "${PLATFORM_WINDOWS_DIR}/WindowsWindow.h"
    "${PLATFORM_WINDOWS_DIR}/WindowsWindow.cpp"
    "${PLATFORM_WINDOWS_DIR}/WindowsTime.h"
    "${PLATFORM_WINDOWS_DIR}/WindowsTime.cpp"
    "${PLATFORM_WINDOWS_DIR}/WindowsInput.h"
    "${PLATFORM_WINDOWS_DIR}/WindowsInput.cpp"
)

# OpenGL
list(APPEND SOURCE_FILES_OPENGL
    "${PLATFORM_OPENGL_DIR}/OpenGLRenderAPI.h"
    "${PLATFORM_OPENGL_DIR}/OpenGLRenderAPI.cpp"
    "${PLATFORM_OPENGL_DIR}/OpenGLGraphicsContext.h"
    "${PLATFORM_OPENGL_DIR}/OpenGLGraphicsContext.cpp"
    "${PLATFORM_OPENGL_DIR}/OpenGLVertexBuffer.h"
    "${PLATFORM_OPENGL_DIR}/OpenGLVertexBuffer.cpp"
    "${PLATFORM_OPENGL_DIR}/OpenGLIndexBuffer.h"
    "${PLATFORM_OPENGL_DIR}/OpenGLIndexBuffer.cpp"
    "${PLATFORM_OPENGL_DIR}/OpenGLShader.h"
    "${PLATFORM_OPENGL_DIR}/OpenGLShader.cpp"
    "${PLATFORM_OPENGL_DIR}/OpenGLVertexArray.h"
    "${PLATFORM_OPENGL_DIR}/OpenGLVertexArray.cpp"
    "${PLATFORM_OPENGL_DIR}/OpenGLTexture.h"
    "${PLATFORM_OPENGL_DIR}/OpenGLTexture.cpp"
)

list(APPEND SOURCE_FILES ${SOURCE_FILES_OPENGL})

# Append Platform specific files
# Operating platform
IF (WIN32)
  list(APPEND SOURCE_FILES ${SOURCE_FILES_WINDOWS})
  # TODO: Linux
  # TODO: MacOS
  # TODO: Android
  # TODO: IOS
ENDIF()

# Add source to this project's executable.
add_library(Cheetah SHARED ${SOURCE_FILES})

target_include_directories (Cheetah INTERFACE ${INCLUDES_DIR_PUBLIC})
target_include_directories (Cheetah PRIVATE ${ENGINE_DIR})
target_include_directories (Cheetah PRIVATE ${INCLUDES_DIR_PRIVATE})

# Add compile definitions
list(APPEND CHEETAH_COMP_DEFS
    "CH_BUILD_DLL"
    ${RENDER_API}
)

target_compile_definitions(Cheetah PRIVATE ${CHEETAH_COMP_DEFS})
target_compile_definitions(Cheetah PUBLIC "$<$<CONFIG:DEBUG>:DEBUG>")
target_compile_definitions(Cheetah PUBLIC "$<$<CONFIG:DEBUG>:CH_ASSERT_ENABLED>")

set_target_properties(Cheetah PROPERTIES LINKER_LANGUAGE CXX)
# Copy dll to game project build folder

IF(${APPLICATION_NAME})
message("---------------------------------------------------------------------")
add_custom_command(
    TARGET Cheetah 
    POST_BUILD
    COMMAND ${CMAKE_COMMAND} -E copy_if_different
    "${PROJECT_BINARY_DIR}/Cheetah.dll"
    "${PROJECT_BINARY_DIR}/${APPLICATION_NAME}"
)
ENDIF()

#----------------------------------------------
# ADD OPENGL LIBRARY DEPENDENCY
#----------------------------------------------
find_package(OpenGL REQUIRED)
target_link_libraries(Cheetah ${OpenGL})

#----------------------------------------------
# ADD GLFW LIBRARY DEPENDENCY
#----------------------------------------------
set(GLFW_DIR "${LIB_DIR}/glfw")
set(GLFW_BUILD_EXAMPLES OFF CACHE INTERNAL "Build the GLFW example programs")
set(GLFW_BUILD_TESTS OFF CACHE INTERNAL "Build the GLFW test programs")
set(GLFW_BUILD_DOCS OFF CACHE INTERNAL "Build the GLFW documentation")
set(GLFW_INSTALL OFF CACHE INTERNAL "Generate installation target")
add_subdirectory("${GLFW_DIR}")
target_include_directories(Cheetah PRIVATE "${GLFW_DIR}/include")
target_link_libraries(Cheetah "glfw" "${GLFW_LIBRARIES}")
target_compile_definitions(Cheetah PRIVATE "GLFW_INCLUDE_NONE")

#----------------------------------------------
# ADD GLAD LIBRARY DEPENDENCY
#----------------------------------------------
set(GLAD_DIR "${LIB_DIR}/glad")
add_library("glad" "${GLAD_DIR}/src/glad.c")
target_include_directories("glad" PRIVATE "${GLAD_DIR}/include")
target_include_directories(Cheetah PUBLIC "${GLAD_DIR}/include")
target_link_libraries(Cheetah "glad" "${CMAKE_DL_LIBS}")

#----------------------------------------------
# ADD STB_IMAGE LIBRARY DEPENDENCY
#----------------------------------------------
set(STB_IMAGE_DIR "${LIB_DIR}/stb_image")
add_library("stb_image" "${STB_IMAGE_DIR}/stb_image.cpp")
target_include_directories("stb_image" PRIVATE "${STB_IMAGE_DIR}/include")
target_include_directories(Cheetah PUBLIC "${STB_IMAGE_DIR}/include")
target_link_libraries(Cheetah "stb_image" "${CMAKE_DL_LIBS}")

#---------------------------------------------
# ADD GLM LIBRARY DEPENDENCY
# --------------------------------------------
set(GLM_DIR "${LIB_DIR}/glm")
add_subdirectory("${LIB_DIR}/glm")
target_include_directories(Cheetah PRIVATE "${GLM_DIR}/glm")
target_link_libraries(Cheetah glm)

游戏

# CMakeList.txt : CMake project for Cheetah, include source and define
# project specific logic here.
#
cmake_minimum_required (VERSION 3.13)

set(SOURCE_DIR "${PROJECT_SOURCE_DIR}/Game/src")

list(APPEND SOURCE_FILES 
    "${SOURCE_DIR}/Main.cpp"
    "${SOURCE_DIR}/GameLayer.cpp"
    "${SOURCE_DIR}/GameLayer.h"
    "${SOURCE_DIR}/GameObject.h"
    "${SOURCE_DIR}/GameObject.cpp"
    "${SOURCE_DIR}/Scene.h"
    "${SOURCE_DIR}/Scene.cpp"
    "${SOURCE_DIR}/GameScene.h"
    "${SOURCE_DIR}/GameScene.cpp"
)

# Platform defines
IF (WIN32)
  add_compile_definitions(CH_PLATFORM_WINDOWS)
ELSE()
  # set stuff for other systems
ENDIF()

find_library( CHEETAH_LIB 
    NAMES Cheetah
    HINTS "${CMAKE_BINARY_DIR}/Cheetah")

# Add source to this project's executable.
add_executable (Game ${SOURCE_FILES})

target_include_directories(Game PUBLIC "${PROJECT_SOURCE_DIR}/Cheetah/includes")

# TODO: Add tests and install targets if needed.

target_link_libraries(Game ${CHEETAH_LIB})

顶级 CMakeList

# CMakeList.txt : Top-level CMake project file, do global configuration
# and include sub-projects here.
#
cmake_minimum_required (VERSION 3.8)

project ("Game")

set(APPLICATION_NAME "Game")
set(RENDER_API "OPENGL")

# Include sub-projects.
add_subdirectory("Cheetah")
add_subdirectory ("Game")

非常感谢任何可以为我指明正确方向的内容!

【问题讨论】:

  • 文件路径${PROJECT_SOURCE_DIR}/dependencies/glm/glm/common.hpp有效吗?这就是您在 Cheetah CMake 文件底部为 Cheetah 目标包含的 (${PROJECT_SOURCE_DIR}/dependencies/glm/glm)。
  • 是的,该文件是有效的,即使构建失败我也可以单击包含路径来打开该特定文件。
  • 您可以考虑将 GLM 包含目录添加到您的 Game 目标;他们似乎没有在那里列出。您也可以将Game CMake 文件更改为简单地使用Cheetah CMake 目标,而不是使用find_library(),但这是一个设计决定。
  • @squareskittles 感谢您的建议,使用 Cheetah CMake 目标为我解决了这个问题。虽然我不确定会有什么区别
  • 我写了一个答案来解释使用已经创建的Cheetah CMake 目标的优点。唯一的缺陷是现在Game CMake 文件不能是一个独立的项目。

标签: c++ cmake glm-math


【解决方案1】:

与您为Cheetah 指定的目录相比,您为Game 目标指定的包含目录非常短:

target_include_directories(Game PUBLIC "${PROJECT_SOURCE_DIR}/Cheetah/includes")

您可能还需要其中一些Cheetah 包含Game 的目录。

注意:如果您愿意重新组织这两个项目的设计以始终使用顶级 CMake 文件,则无需使用find_library() 来查找@987654328 @ 图书馆。 CMake 已经知道 Cheetah 目标,因为它刚刚创建! Game CMakeLists.txt 文件可能如下所示:

# CMakeList.txt : CMake project for Game, include source and define
# project specific logic here.
#
cmake_minimum_required (VERSION 3.13)

set(SOURCE_DIR "${PROJECT_SOURCE_DIR}/Game/src")

list(APPEND SOURCE_FILES 
    "${SOURCE_DIR}/Main.cpp"
    "${SOURCE_DIR}/GameLayer.cpp"
    "${SOURCE_DIR}/GameLayer.h"
    "${SOURCE_DIR}/GameObject.h"
    "${SOURCE_DIR}/GameObject.cpp"
    "${SOURCE_DIR}/Scene.h"
    "${SOURCE_DIR}/Scene.cpp"
    "${SOURCE_DIR}/GameScene.h"
    "${SOURCE_DIR}/GameScene.cpp"
)

# Platform defines
# Note, this block can also be removed if target_compile_definitions 
#  is used for Cheetah instead.
IF (WIN32)
  add_compile_definitions(CH_PLATFORM_WINDOWS)
ELSE()
  # set stuff for other systems
ENDIF()

# Add source to this project's executable.
add_executable (Game ${SOURCE_FILES})

# TODO: Add tests and install targets if needed.

target_link_libraries(Game PUBLIC Cheetah)

Cheetah 目标将携带所有包含目录,因此无需再次单独列出它们。它也可以传播编译定义,只需在为Cheetah 目标定义它们时使用target_compile_definitions()

【讨论】:

  • 谢谢!我误解了 cmake 中目标的使用,并认为它们仅在声明它们的文件中可用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-05-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-24
  • 2013-10-25
  • 2020-02-07
相关资源
最近更新 更多