5

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

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

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

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

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

基本上,我想做的是:

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

3 回答 3

1

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

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

我已经成功构建并执行了一个使用 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")
#############################################

主文件

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

于 2015-02-07T14:19:57.037 回答
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 一起使用并链接到变量的内容。

于 2015-02-02T19:00:02.353 回答
1

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

在根 CMakeLists.txt 中,在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)
于 2015-05-04T07:36:51.223 回答