我试图从Visual Studio迁移到Jetbrains' (真棒)CLion IDE使用CMake来组织项目。
到目前为止,过渡一直很顺利:创建CMake项目并将它们导入CLion非常简单,我可以开始在一个平台上编码,然后在另一个平台上继续编码而没有问题。
然而,我无法在CMake中找到等效的Visual Studio的一个方面是property sheets:我主要使用它们来保存包含目录'库的路径和链接库(即每个库的一个.vsprops
文件,例如OpenCV.vsprops
,Boost.vsprops
等。
这样,在VS中,我可以在不同项目之间共享库的.vsprops
文件,而无需每次都配置路径/库。
CMake与Visual Studio的属性表有类似的机制吗?如何将库的包含/库存储在 CMake-parsable 文件中,然后" import"它在CMakeLists.txt中以链接库?
基本上,我想做的是:
link_target_to_libs(myTarget "path/to/propertySheet1" "path/to/propertySheet2" ...)
。答案 0 :(得分: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一起使用并链接到变量的内容。
答案 1 :(得分:1)
因为我真的想让库包含/链接到单行命令中,并且就我对CMake的基本知识而言,我认为应该做出一些妥协 - 主要是共享目标名称CMakeLists.txt
与“属性表”之间的变量。所以这是我的解决方案......直到有人提出更简单/更清洁的方法:
.cmake
文本文件TARGET
- 指定目标(即add_executable()
的第一个参数),.cmake
文件包含对target_include_directories(${TARGET} PRIVATE ${PATH_TO_INCLUDE_DIR})
和target_link_libraries(${TARGET} ${LIST_OF_LIBS})
的调用,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")
#############################################
<强>的main.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
中。
答案 2 :(得分:1)
这似乎很有效,但肯定有一些我没有发现的问题。 (我担心多个宏添加相同的target_link_libraries会导致“已经定义”的链接错误,但至少g ++ 5.1.0会多次给出相同的库名称而没有错误。)
在根CMakeLists.txt中, BEFORE add_subdirectory()调用或整数,包括:
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)