CMake 相当于 Visual Studio 的 属性 Sheets (.vsprops)
CMake's equivalent to Visual Studio's Property Sheets (.vsprops)
我正在尝试从 Visual Studio 迁移到 Jetbrains(很棒)CLion IDE which uses CMake 来组织项目。
到目前为止,过渡一直很顺利:创建 CMake 项目并将它们导入 CLion 很容易,我可以在一个平台上开始编码,然后在另一个平台上继续,没有任何问题。
然而,Visual Studio 的一个方面是我在 CMake 中找不到的等效项是 property sheets:我主要使用它们来保存包含目录的路径和 linking 库的库(即每个库一个 .vsprops
文件,例如 OpenCV.vsprops
、Boost.vsprops
等)。
这样,在 VS 中,我可以在不同项目之间共享库的 .vsprops
文件,而不必每次都配置 paths/libs。
CMake 是否具有与 Visual Studio 的 属性 工作表类似的机制?如何将库的 includes/libs 存储在 CMake-parsable 文件中,然后将其 "import" 存储在 CMakeLists.txt 中以便 link反对图书馆?
基本上,我想做的是:
- 为给定的库创建一个 "cmake property sheet"(因为缺少更好的名称)。
- 然后,在 CMakeLists.txt 中,写下
link_target_to_libs(myTarget "path/to/propertySheet1" "path/to/propertySheet2" ...)
.
在 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
而不是 'linking to property sheets',您 link 到 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 和 link 一起用于变量的内容。
因为我真的想把库的 inclusion/linking 变成一个单行命令,就我对 CMake 的(基本)知识而言,我认为应该做出一些妥协——主要是在 CMakeLists.txt
和 "property sheets" 之间共享目标名称的 变量 。所以这是我的解决方案......直到有人提出 simpler/cleaner 一个:
- A CMake 属性 sheet 是一个
.cmake
文本文件,
- A well-known variable name--
TARGET
--指定目标(即add_executable()
的第一个参数),
- 除了特定于库的命令外,
.cmake
文件包含对 target_include_directories(${TARGET} PRIVATE ${PATH_TO_INCLUDE_DIR})
和 target_link_libraries(${TARGET} ${LIST_OF_LIBS})
、 的调用
- 为了 use/link 对抗库,在
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")
#############################################
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;
}
现在,每次我想在project/program中使用OpenCV,我只需要将include("opencv.cmake")
放在相应的CMakeLists.txt
中即可。
这似乎很有效,但肯定存在我尚未发现的问题。 (我担心添加相同 target_link_libraries 的多个宏会导致 "already defined" linking 错误,但至少 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" 到 link 到适当的库,改变预处理器定义,等等。参见 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)
我正在尝试从 Visual Studio 迁移到 Jetbrains(很棒)CLion IDE which uses CMake 来组织项目。
到目前为止,过渡一直很顺利:创建 CMake 项目并将它们导入 CLion 很容易,我可以在一个平台上开始编码,然后在另一个平台上继续,没有任何问题。
然而,Visual Studio 的一个方面是我在 CMake 中找不到的等效项是 property sheets:我主要使用它们来保存包含目录的路径和 linking 库的库(即每个库一个 .vsprops
文件,例如 OpenCV.vsprops
、Boost.vsprops
等)。
这样,在 VS 中,我可以在不同项目之间共享库的 .vsprops
文件,而不必每次都配置 paths/libs。
CMake 是否具有与 Visual Studio 的 属性 工作表类似的机制?如何将库的 includes/libs 存储在 CMake-parsable 文件中,然后将其 "import" 存储在 CMakeLists.txt 中以便 link反对图书馆?
基本上,我想做的是:
- 为给定的库创建一个 "cmake property sheet"(因为缺少更好的名称)。
- 然后,在 CMakeLists.txt 中,写下
link_target_to_libs(myTarget "path/to/propertySheet1" "path/to/propertySheet2" ...)
.
在 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
而不是 'linking to property sheets',您 link 到 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 和 link 一起用于变量的内容。
因为我真的想把库的 inclusion/linking 变成一个单行命令,就我对 CMake 的(基本)知识而言,我认为应该做出一些妥协——主要是在 CMakeLists.txt
和 "property sheets" 之间共享目标名称的 变量 。所以这是我的解决方案......直到有人提出 simpler/cleaner 一个:
- A CMake 属性 sheet 是一个
.cmake
文本文件, - A well-known variable name--
TARGET
--指定目标(即add_executable()
的第一个参数), - 除了特定于库的命令外,
.cmake
文件包含对target_include_directories(${TARGET} PRIVATE ${PATH_TO_INCLUDE_DIR})
和target_link_libraries(${TARGET} ${LIST_OF_LIBS})
、 的调用
- 为了 use/link 对抗库,在
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")
#############################################
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;
}
现在,每次我想在project/program中使用OpenCV,我只需要将include("opencv.cmake")
放在相应的CMakeLists.txt
中即可。
这似乎很有效,但肯定存在我尚未发现的问题。 (我担心添加相同 target_link_libraries 的多个宏会导致 "already defined" linking 错误,但至少 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" 到 link 到适当的库,改变预处理器定义,等等。参见 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)