如何构建一个包含不同第三方库的CMake项目

9

我对CMake很新,想要创建一个需要一些第三方库的小项目。我希望将这些库作为git仓库以保持最新状态。有些库只是.cpp和.hpp文件(如glad、imgui),而另一些则是cmake项目(如glfw、glm)。

我的想法是建立一个第三方项目,其中包含所有的库,作为子项目;同时建立一个沙盒项目来使用这些库,并包含等等。我希望使用现代的CMake代码,不会在框架结构外安装任何东西。

文件夹结构:

Framework
|--3rd_party
|  |--glad
|  |  |--include
|  |  |--src
|  |--glfw-master
|  |  |--...
|  |  |--CMakeLists.txt
|  |--glm-master
|  |  |--..
|  |  |--CMakeLists.txt
|  |--imgui-master
|  |  |--*.cpp
|  |  |--*.hpp
|  |  |--examples
|  |  |  |--*.cpp
|  |  |  |--*.hpp
|  |--CMakeLists.txt
|--sandbox
|  |--main.cpp
|  |--CMakeLists.txt
|--CMakeLists.txt

我创建了这个文件夹结构,并编写了一些CMakeLists文件:

CMakeLists.txt(框架)

cmake_minimum_required(VERSION 3.10)

project(Framework)

add_subdirectory("3rd_party")
add_subdirectory("sandbox")

CMakeLists.txt(第三方)

#GLFW
set(GLFW_BUILD_DOCS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_TESTS OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
add_subdirectory(glfw-master)

# GLM
set(GLM_TEST_ENABLE OFF CACHE BOOL "" FORCE)
add_subdirectory(glm-master)

# Glad
add_library(
    Glad STATIC
    "glad/src/glad.c"
)

target_include_directories(Glad PUBLIC "glad/include")

# ImGui
add_compile_definitions(IMGUI_IMPL_OPENGL_LOADER_GLAD=1)

set(IMGUI_SOURCES
    "imgui-master/imgui.cpp"
    "imgui-master/imgui_demo.cpp"
    "imgui-master/imgui_draw.cpp"
    "imgui-master/imgui_widgets.cpp"
    "imgui-master/examples/imgui_impl_glfw.cpp"
    "imgui-master/examples/imgui_impl_opengl3.cpp"
)

set(IMGUI_HEADERS
    "imgui-master/imconfig.h"
    "imgui-master/imgui.h"
    "imgui-master/imgui_internal.h"
    "imgui-master/imstb_rectpack.h"
    "imgui-master/imstb_textedit.h"
    "imgui-master/imstb_truetype.h"
    "imgui-master/examples/imgui_impl_glfw.h"
    "imgui-master/examples/imgui_impl_opengl3.h"
)

add_library(
    ImGui STATIC
    ${IMGUI_SOURCES}
    ${IMGUI_HEADERS}
)

target_include_directories(ImGui PUBLIC "imgui-master" "glfw-master/include" "glad/include")

CMakeLists.txt(沙盒)

project(Sandbox)

find_package(OpenGL REQUIRED)

add_executable(sandbox main.cpp)

# OpenGL
target_include_directories(Sandbox PUBLIC ${OPENGL_INCLUDE_DIR})
target_include_directories(Sandbox PUBLIC external)

# Glfw
target_include_directories(Sandbox PUBLIC "../3rd_party/glfw-master/include")

# Link libs
target_link_libraries(Sandbox PUBLIC
           ${OPENGL_LIBRARIES}
           "../3rd_party/glfw-master/src/Debug/glfw3"
           Glad
           ImGui
           glm_static
)

这段代码可以正常运行,但是结果并不符合我的预期。首先,我知道它可能有点丑陋,也许有更好的方法来处理包含和源路径,但更大的问题是项目结构。 例如,在将其构建为 MS VS Studio 时,我有三个解决方案。

./framework.sln
./sandbox/sandbox.sln
./3rd_party/glfw-master/glfw.sln

而 glad、glm 和 imgui 是 sandbox.sln 的一部分。

我想要的是一个解决方案,其中包含两个子解决方案 sandbox 和 3rd_party,它们也都有所有库的子解决方案或项目。

那么这是否可能呢?如果可以,我该如何使用 cmake 创建这样的结构?

1个回答

7

经过进一步调查和大量使用CMake进行尝试和错误,我想我开始时有些错误的期望和误解。

从CMake文件中获取一个对于Visual Studio有用的解决方案/项目结构是不可能的,因为所有的CMake项目将会转化成一个VS解决方案,而所有的add_library或add_executable都会转化成一个VS项目。如果我想要为我的框架创建一个CMake项目并添加GLFW作为第三方库,这也创建了一个CMake项目,这将以两个不同的VS解决方案结束,结构就混乱了。我认为这就是为什么Microsoft在Visual Studio中引入了一个特殊的上下文来打开CMake文件。

OpenCMakeProject_VS2019

如果使用此上下文打开项目,则“解决方案”查看器显示项目的文件夹结构。这基本上是我一开始所期望的。

FolderView_VS2019

还有一种选项可以切换视图以查看所有CMake目标(exec、libs等)。

我还“升级”了我的CMakeLists。我使用不同的方法添加第三方库:

  1. add_subdirectory用于包含CMakeLists的库,如GLFW
  2. add_library和INTERFACE用于仅包含头文件的库,如glm
  3. add_library STATIC用于静态库,如ImGui(在我的情况下)

Sandbox的包含由库的公共接口提供,并且构建/依赖关系顺序是由target_link_libraries中的顺序确定的。

我希望这很有用并将为您节省大量时间 ;)

干杯!boss0r

CMakeLists.txt(框架)

cmake_minimum_required(VERSION 3.10)

project(OpenGL_Framework
    VERSION 0.0.1
    LANGUAGES CXX C    # C for GLFW
)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CXX_EXTENSIONS OFF)

add_subdirectory(ThirdParty)
add_subdirectory(Sandbox)

CMakeLists.txt(第三方)
# GLFW
set(GLFW_LIB_NAME "GLFW")
set(GLFW_INC_PATH ${GLFW_LIB_NAME}/include)

set(GLFW_BUILD_DOCS     OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_TESTS    OFF CACHE BOOL "" FORCE)
set(GLFW_BUILD_EXAMPLES OFF CACHE BOOL "" FORCE)
#set(GLFW_VULKAN_STATIC  OFF CACHE BOOL "" FORCE)    # OFF by default
#set(BUILD_SHARED_LIBS   OFF CACHE BOOL "" FORCE)    # OFF by default
set(GLFW_INSTALL        OFF CACHE BOOL "" FORCE)

add_subdirectory(${GLFW_LIB_NAME})

# spdlog
set(SPDLOG_LIB_NAME "spdlog")

set(SPDLOG_MASTER_PROJECT OFF CACHE BOOL "" FORCE)

add_subdirectory(${SPDLOG_LIB_NAME})

# OR
#set(SPDLOG_LIB_NAME "spdlog")
#set(SPDLOG_SRC_PATH ${SPDLOG_LIB_NAME}/src)
#set(SPDLOG_INC_PATH ${SPDLOG_LIB_NAME}/include)

#add_library(${SPDLOG_LIB_NAME}
#    STATIC
#        ${SPDLOG_SRC_PATH}/spdlog.cpp
#)

#target_include_directories(${SPDLOG_LIB_NAME}
#    PUBLIC
#        ${SPDLOG_INC_PATH})

# glm
set(GLM_LIB_NAME "glm")
set(GLM_INC_PATH ${GLM_LIB_NAME}/glm)

add_library(${GLM_LIB_NAME} INTERFACE)

target_include_directories(${GLM_LIB_NAME}
    INTERFACE
        ${GLM_INC_PATH}
)

# OR
#set(GLM_LIB_NAME "glm")
#set(GLM_INC_PATH ${GLM_LIB_NAME}/glm)

#set(GLM_TEST_ENABLE OFF CACHE BOOL "" FORCE)

#add_subdirectory(${GLM_LIB_NAME})

#target_include_directories(${GLM_LIB_NAME}
#    PUBLIC
#        $(GLM_INC_PATH)
#)

# Glad
set(GLAD_LIB_NAME "Glad")
set(GLAD_SRC_PATH "${GLAD_LIB_NAME}/src")
set(GLAD_INC_PATH "${GLAD_LIB_NAME}/include")

add_library( ${GLAD_LIB_NAME}
    STATIC
        "${GLAD_SRC_PATH}/glad.c"
)

target_include_directories(${GLAD_LIB_NAME}
    PUBLIC
        "${GLAD_INC_PATH}"
)

# ImGui
set(IMGUI_LIB_NAME "ImGui")

set(IMGUI_SOURCES
    "${IMGUI_LIB_NAME}/imgui.cpp"
    "${IMGUI_LIB_NAME}/imgui_demo.cpp"
    "${IMGUI_LIB_NAME}/imgui_draw.cpp"
    "${IMGUI_LIB_NAME}/imgui_widgets.cpp"
    "${IMGUI_LIB_NAME}/examples/imgui_impl_glfw.cpp"
    "${IMGUI_LIB_NAME}/examples/imgui_impl_opengl3.cpp"
)

set(IMGUI_HEADERS
    "${IMGUI_LIB_NAME}/imconfig.h"
    "${IMGUI_LIB_NAME}/imgui.h"
    "${IMGUI_LIB_NAME}/imgui_internal.h"
    "${IMGUI_LIB_NAME}/imstb_rectpack.h"
    "${IMGUI_LIB_NAME}/imstb_textedit.h"
    "${IMGUI_LIB_NAME}/imstb_truetype.h"
    "${IMGUI_LIB_NAME}/examples/imgui_impl_glfw.h"
    "${IMGUI_LIB_NAME}/examples/imgui_impl_opengl3.h"
)

set(IMGUI_INC_PATH "${IMGUI_LIB_NAME}/")

add_library(${IMGUI_LIB_NAME}
    STATIC
        ${IMGUI_SOURCES}
        ${IMGUI_HEADERS}
)

target_compile_definitions(${IMGUI_LIB_NAME}
    PRIVATE
        IMGUI_IMPL_OPENGL_LOADER_GLAD=1
)

target_include_directories(${IMGUI_LIB_NAME}
    PUBLIC
        "${IMGUI_INC_PATH}"
        "${GLFW_INC_PATH}"
        "${GLAD_INC_PATH}"
)

CMakeLists.txt(沙盒)

project(Sandbox)

find_package(OpenGL REQUIRED)

add_executable(${PROJECT_NAME} Sandbox.cpp)

target_include_directories(${PROJECT_NAME}
    PUBLIC
        external
        ${OPENGL_INCLUDE_DIR}
)

target_link_libraries(${PROJECT_NAME}
    PUBLIC
        ${OPENGL_gl_LIBRARY}
        glfw
        Glad
        ImGui
        glm
        #glm_static    # if build with add_subdirectory
        spdlog::spdlog
)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接