【问题标题】:How to structure a cmake project with different 3rd-party libraries如何使用不同的 3rd-party 库构建 cmake 项目
【发布时间】:2019-08-29 04:31:33
【问题描述】:

我是 cmake 的新手,我尝试创建一个需要一些 3rd-party 库的小项目。我希望将库作为 git repos 始终保持最新。一些库只是 .cpp 和 .hpp 文件(glad、imgui),而其他库是 cmake 项目(glfw、glm)。

这个想法是有一个包含所有库的第 3 方项目作为一种子项目和一个使用库和包含等的沙盒项目。 而且我想使用不会在框架结构之外安装任何东西的现代 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 (3rd_party)

#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

很高兴,glm 和 imgui 是 sandbox.sln 的一部分

我想要的是一个包含两个子解决方案沙箱和 3rd_party 的解决方案,其中还包含所有库的子解决方案或项目。

那么有可能吗?如果可以,我如何使用 cmake 创建这样的结构?

【问题讨论】:

    标签: cmake


    【解决方案1】:

    经过进一步调查和对 CMake 的大量尝试和错误,我想我是从错误的期望和一些误解开始的。

    不可能从 CMake 文件中获得适用于 Visual Studio 的有用解决方案/项目结构,因为所有 CMake 项目都会生成 VS 解决方案,并且所有 add_library 或 add_executable 都将是 VS 项目。如果我想为我的框架创建一个 CMake 项目并将 GLFW 添加为第三方,这也会创建一个 CMake 项目,它将以两个不同的 VS 解决方案和 bang 结构结束。我认为这就是为什么微软在 Visual Studio 中为 CMake 文件引入了一个特殊的开放上下文。

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

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

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

    1. 为带有 CMakeLists(如 GLFW)的库添加子目录
    2. add_library 和 INTERFACE 用于 glm 等仅标头库
    3. add_library STATIC 用于静态库,如 ImGui(在我的例子中)

    沙盒的包含由库的公共接口提供,构建/依赖顺序由 target_link_libraries 中的顺序给出。

    我希望这对您有所帮助,并且可以节省您很多时间;)

    干杯! 老板0r

    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 (3rd_party)

    # 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
    )
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-19
      • 1970-01-01
      • 2011-03-08
      • 2017-01-04
      • 2012-06-02
      • 2012-04-30
      相关资源
      最近更新 更多