【问题标题】:CMake's equivalent to Visual Studio's Property Sheets (.vsprops)CMake 相当于 Visual Studio 的属性表 (.vsprops)
【发布时间】:2015-04-01 18:10:49
【问题描述】:

我正在尝试从 Visual Studio 迁移到 Jetbrains(很棒)CLion IDE,它使用 CMake 来组织项目。

到目前为止,过渡一直很顺利:创建 CMake 项目并将其导入 CLion 很容易,我可以在一个平台上开始编码,然后继续在另一个平台上毫无问题。

然而,我在 CMake 中找不到对应的 Visual Studio 的一个方面是 property sheets:我主要使用它们来保存包含目录的路径和库的链接库(即一个 .vsprops 文件对于每个库,例如OpenCV.vspropsBoost.vsprops 等)。

这样,在 VS 中,我可以在不同项目之间共享库的 .vsprops 文件,而无需每次都配置路径/库。

CMake 是否具有与 Visual Studio 的属性表类似的机制?如何将库的包含/库存储在 CMake-parsable 文件中,然后将其“导入”到 CMakeLists.txt 中以链接到库?

基本上,我想做的是:

  1. 为给定的库创建一个“cmake 属性表”(因为没有更好的名称)。
  2. 然后,在 CMakeLists.txt 中,编写类似 link_target_to_libs(myTarget "path/to/propertySheet1" "path/to/propertySheet2" ...) 的内容。

【问题讨论】:

  • 如何在 CMake 中模拟 Visual Studio 的属性表(用于库)? 您必须使用 cmake 命令自己生成这些文件才能创建文件。
  • 我主要使用它们来保存包含目录的路径和库的链接库如果库和包含文件,我只会使用 CMake 的处理.或者您是否打算不使用 CMake 创建您的 Visual Studio 项目。
  • 我编辑了帖子的最后一部分以阐明我的意图:) 你是对的,我不想再使用 VS。我只想拥有要使用 CLion 编辑的源代码的 CMake 项目。

标签: c++ visual-studio cmake clion vsprops


【解决方案1】:

在 CMake 中,库可以导出带有 IMPORTED 目标的包,其他构建系统使用 find_package 导入这些目标:

http://www.cmake.org/cmake/help/v3.1/manual/cmake-packages.7.html

http://www.cmake.org/cmake/help/v3.0/manual/cmake-buildsystem.7.html

http://www.cmake.org/cmake/help/v3.0/manual/cmake-buildsystem.7.html#imported-targets

您不是“链接到属性表”,而是链接到 IMPORTED 目标。

target_link_libraries(myTarget Dep1::Dep1 Dep2::Dep2)

并非所有库都创建 IMPORTED 目标,也并非所有库都提供 cmake 配置文件包。在这些情况下(包括 OpenCV 和 Boost),CMake 提供了查找模块:

http://www.cmake.org/cmake/help/v3.0/manual/cmake-developer.7.html#find-modules

与 find_package 一起使用并链接到变量的内容。

【讨论】:

    【解决方案2】:

    由于我真的想将库的包含/链接变成一个单行命令,并且就我对 CMake 的(基本)知识而言,我认为应该做出一些妥协——主要是共享目标名称的CMakeLists.txt 和“属性表”之间的变量。所以这是我的解决方案......直到有人提出更简单/更清洁的解决方案:

    1. CMake 属性表是一个.cmake 文本文件,
    2. 一个众所周知的变量名 --TARGET-- 指定目标(即add_executable()的第一个参数),
    3. 除了特定于库的命令之外,.cmake 文件还包含对 target_include_directories(${TARGET} PRIVATE ${PATH_TO_INCLUDE_DIR})target_link_libraries(${TARGET} ${LIST_OF_LIBS}) 的调用,
    4. 要使用/链接库,请在CMakeLists.txt 中调用include("path/to/.cmake")

    我已经成功构建并执行了一个简单的程序,该程序使用 X11 和 OpenCV 以及以下文件:

    x11.cmake

    target_include_directories(${TARGET} PRIVATE "/usr/include/X11")
    target_link_libraries(${TARGET} "/usr/lib/x86_64-linux-gnu/libX11.so")
    

    opencv.cmake

    # OpenCV-specific stuff
    set(OpenCV_DIR "/PATH/TO/OPENCV/INSTALL/DIR/share/OpenCV") # path to OpenCVConfig.cmake
    find_package(OpenCV REQUIRED)
    # include path
    target_include_directories(${TARGET} PRIVATE ${OpenCV_INCLUDE_DIRS})
    # linking libs
    target_link_libraries(${TARGET} opencv_world opencv_ts)
    

    CMakeLists.txt

    cmake_minimum_required(VERSION 2.8.4)
    project(hello_clion)
    
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
    
    ## hello-clion ##############################
    # make a new target name
    set(TARGET hello-clion)
    
    # find sources
    file(GLOB_RECURSE SOURCE_FILES "src/*.cpp" "src/*.hpp")
    
    # declare a target
    add_executable(${TARGET} ${SOURCE_FILES})
    
    # link the libraries (to the last-declared ${TARGET}, which should be the last-added executable)
    include("x11.cmake")
    include("opencv.cmake")
    #############################################
    

    ma​​in.cpp

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <thread>
    
    #include <opencv2/opencv.hpp>
    
    #include <Xlib.h>
    
    int main_x11()
    {
        // adapted from: http://rosettacode.org/wiki/Window_creation/X11#Xlib
    }
    
    int main_ocv()
    {
        // adapted from: http://docs.opencv.org/doc/tutorials/introduction/display_image/display_image.html#source-code
    }
    
    int main()
    {
        using namespace std;
    
        thread tocv(main_ocv);
        thread tx11(main_x11);
    
        tocv.join();
        tx11.join();
    
        return 0;
    }
    

    现在,每次我想在项目/程序中使用 OpenCV 时,我只需将 include("opencv.cmake") 放入相应的 CMakeLists.txt 中即可。

    【讨论】:

    • 当您在一个目录中定义多个目标时,这不是一个好的解决方案。我建议您查看我提供的文档链接。
    • 您能否详细说明为什么此解决方案可能存在问题?我可以看到 include 路径可能是 polluted (即包含不必要的目录),但我认为这不是问题......是吗?
    • 我已经编辑了我的解决方案以使用 target_include_directories() 以便每个目标包含目录。
    【解决方案3】:

    这似乎工作得很好,但肯定有我没有发现的问题。 (我担心添加相同 target_link_libraries 的多个宏会导致“已定义”链接错误,但至少 g++ 5.1.0 句柄被多次赋予相同的库名称而不会出错。)

    在根 CMakeLists.txt 中,BEFORE add_subdirectory() 调用或 glob,包括:

    macro(USES_WX)
        include_directories(SYSTEM /usr/local/include/wx-3.0)
        include_directories(SYSTEM /usr/local/lib/wx/include/gtk3-unicode-3.0)
        link_directories(/usr/local/lib)
        add_definitions(-D_FILE_OFFSET_BITS=64 -DWXUSINGDLL -D__WXGTK__ -pthread)
        target_link_libraries(${TARGET} pthread wx_gtk3u_xrc-3.0 wx_gtk3u_html-3.0 wx_gtk3u_qa-3.0 wx_gtk3u_adv-3.0 wx_gtk3u_core-3.0 wx_baseu_xml-3.0 wx_baseu_net-3.0 wx_baseu-3.0)
    endmacro()
    

    (您可以使宏更花哨,例如检查 CMAKE_BUILD_TYPE 是否为“Debug”或“Release”以链接到适当的库、改变预处理器定义等。参见http://www.cmake.org/cmake/help/v3.0/command/if.html

    让你的项目的 CMakeLists.txt 是这样的:

    set(TARGET myProgramName)
    add_executable(${TARGET} myProgramName.cpp)
    USES_WX()
    

    ^^ 宏调用必须在 add_executable() 之后


    而且,如果您想要多目标支持,请将上面显示的根 CMakeLists.txt 部分中的行修改为:

        ...
        target_link_libraries(${ARGV0} pthread wx_gtk3u_xrc-3.0 ...)
        ...
    

    并让您的项目的 CMakeLists.txt 像这样(行更少,但出错的机会更大):

    add_executable(myProgramName myProgramName.cpp)
    USES_WX(myProgramName)
    

    【讨论】:

    • 感谢您的回答。我应该说,我通过在输入目标名称的函数中“封装”.cmake 属性表的内容来改进我的解决方案(我不必再依赖全局 TARGET 变量了) .另外,我制作了一个类似add_executable() 的函数,负责管理属性表的包含等。它实际上与您的建议有一些相似之处:)
    • 如果我有时间,我会将我的最终解决方案放在我的公共仓库或其他地方。可能对像我一样拥有本地库库并需要快速 1 的人有用-line-mechanism 用于在基于 cmake 的项目中使用它们...
    • 如果你能把它放在某个地方那就太好了。我很高兴看到更好/不同的解决方案。
    猜你喜欢
    • 2012-02-09
    • 2011-06-11
    • 2019-05-26
    • 2010-09-07
    • 2015-07-27
    • 1970-01-01
    • 2011-02-04
    • 2014-01-26
    • 2011-02-27
    相关资源
    最近更新 更多