Cmake 入门实战
本文主要包含如下内容:
本博客将教会你编写简单的 Cmake 文件,随后会提供一些相关的代码仅供参考。首先,我们介绍什么是 Cmake。
什么是 CMake
你或许听过好几种Make
工具,例如GNU Make
,QT
的qmake
,微软的MS nmake
,BSD Make
(pmake
),Makepp
,等等。这些 Make
工具遵循着不同的规范和标准,所执行的Makefile
格式也千差万别。这样就带来了一个严峻的问题:如果软件想跨平台,必须要保证能够在不同平台编译。而如果使用上面的Make
工具,就得为每一种标准写一次Makefile
,这将是一件让人抓狂的工作。
CMake
就是针对上面问题所设计的工具:它首先允许开发者编写一种平台无关的CMakeList.txt
文件来定制整个编译流程,然后再根据目标用户的平台进一步生成所需的本地化Makefile
和工程文件,如Unix
的Makefile
或Windows
的Visual Studio
工程。从而做到“Write once, run everywhere”。显然,CMake
是一个比上述几种make
更高级的编译配置工具。
- 编写
CMake
配置文件CMakeLists.txt
- 执行命令
cmake .
生成Makefile
- 使用
make
命令进行编译
单个源文件
首先,假设现在我们的项目中只有一个源文件main.cpp,CMakeLists.txt
编写如下:
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)
# 项目信息
project (Demo1)
# 指定生成目标
add_executable(Demo main.cpp)
符号#
后面的内容被认为是注释。命令由命令名称、小括号和参数组成,参数之间使用空格进行间隔。
cmake_minimum_required
:指定运行此配置文件所需的CMake
的最低版本;project
:参数值是Demo1
,该命令表示项目的名称是Demo1
。add_executable
:将名为main.cpp
的源文件编译成一个名称为Demo
的可执行文件。
之后,在当前目录执行cmake .
,得到Makefile
后再使用make
命令编译得到Demo
可执行文件。
多个源文件
如果需要编译的多个源文件位于同一目录,那么编写 Cmake 的格式如下:
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)
# 项目信息
project (Demo2)
# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_SRCS 变量
aux_source_directory(. DIR_SRCS)
# 指定生成目标
add_executable(Demo ${DIR_SRCS})
aux_source_directory
:将当前目录所有源文件的文件名赋值给变量DIR_SRCS
将当前目录所有源文件的文件名赋值给变量DIR_SRCS
,再指示变量DIR_SRCS
中的源文件需要编译成一个名称为Demo
的可执行文件。
如果需要编译的多个源文件位于多个目录中,那么编写 Cmake 的格式如下:
其中,根目录中的CMakeLists.txt
,编写如下:
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)
# 项目信息
project (Demo3)
# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_SRCS 变量
aux_source_directory(. DIR_SRCS)
# 添加 math 子目录
add_subdirectory(math)
# 指定生成目标
add_executable(Demo ${DIR_SRCS})
# 添加链接库
target_link_libraries(Demo MathFunctions)
add_subdirectory
:指明本项目包含一个子目录math
,这样math
目录下的CMakeLists.txt
文件和源代码也会被处理。
接下来, 子目录中的CMakeLists.txt
,编写如下:
# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_LIB_SRCS 变量
aux_source_directory(. DIR_LIB_SRCS)
# 生成链接库
add_library (MathFunctions ${DIR_LIB_SRCS})
add_library
:将src
目录中的源文件编译为静态链接库
配置OpenCV
如果在项目中,我们使用到了 OpenCV,那么在项目根目录的CMakeLists
文件中添加OpenCV
库。
FIND_PACKAGE(OpenCV REQUIRED )
INCLUDE_DIRECTORIES( ${OPENCV_INCLUDE_DIR} )
TARGET_LINK_LIBRARIES(Demo ${OpenCV_LIBS})
支持C++11
同样的,如果在项目中,我们需要添加支持 C++11,在项目根目录的CMakeLists
文件中添加add_compile_options
库。
add_compile_options(-std=c++11)
测试
我们可以在编写 Cmake 的时候对代码进行简单的测试,则在项目根目录的CMakeLists
文件中调用一系列的add_test
命令。
# 启用测试
enable_testing()
# 测试程序是否成功运行
add_test (test_run Demo 5 2)
# 测试帮助信息是否可以正常提示
add_test (test_usage Demo)
set_tests_properties (test_usage
PROPERTIES PASS_REGULAR_EXPRESSION "Usage: .* base exponent")
# 测试 5 的平方
add_test (test_5_2 Demo 5 2)
set_tests_properties (test_5_2
PROPERTIES PASS_REGULAR_EXPRESSION "is 25")
# 测试 10 的 5 次方
add_test (test_10_5 Demo 10 5)
set_tests_properties (test_10_5
PROPERTIES PASS_REGULAR_EXPRESSION "is 100000")
# 测试 2 的 10 次方
add_test (test_2_10 Demo 2 10)
set_tests_properties (test_2_10
PROPERTIES PASS_REGULAR_EXPRESSION "is 1024")
PASS_REGULAR_EXPRESSION
:用来测试输出是否包含后面跟着的字符串。
常用CMakeLists.txt
文件
最后,我们将粘贴一些常用的 Cmake 代码,仅供参考,你可以选择其中的代码进行使用。
/*CMakeLists_OpenCV版*/
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)
# 项目信息
project (Demo)
# 编译器支持C++11
add_compile_options(-std=c++11)
# 添加`OpenCV`库
FIND_PACKAGE(OpenCV REQUIRED )
INCLUDE_DIRECTORIES( ${OPENCV_INCLUDE_DIR} )
# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_SRCS 变量
aux_source_directory(. DIR_SRCS)
# 指定生成目标
add_executable(Demo ${DIR_SRCS})
TARGET_LINK_LIBRARIES(Demo ${OpenCV_LIBS})
/*CMakeLists_Boost版*/
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)
# 项目信息
project (Demo)
# 编译器支持C++11
add_compile_options(-std=c++11)
# 设置boost库
#set(BOOST_ROOT "/usr/local/boost_1_63_0")
# 添加`OpenCV`库
FIND_PACKAGE(OpenCV REQUIRED)
FIND_PACKAGE(Boost REQUIRED)
INCLUDE_DIRECTORIES( ${OPENCV_INCLUDE_DIR} )
INCLUDE_DIRECTORIES( ${BOOST_INCLUDE_DIRS} )
# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_SRCS 变量
aux_source_directory(. DIR_SRCS)
# 指定生成目标
add_executable(Demo ${DIR_SRCS})
TARGET_LINK_LIBRARIES(Demo ${OpenCV_LIBS} ${Boost_LIBRARIES})
/*此版本适合与CUDA编程*/
# CMake 最低版本号要求
CMAKE_MINIMUM_REQUIRED(VERSION 2.8)
# 项目信息
PROJECT(test_cuda_project)
FIND_PACKAGE(CUDA REQUIRED)
# nvcc flags
#set(CUDA_NVCC_FLAGS -gencode arch=compute_20,code=sm_20;-G;-g)
#set(CUDA_NVCC_FLAGS -gencode arch=compute_52,code=sm_52;-G;-g)
file(GLOB_RECURSE CURRENT_HEADERS *.h *.hpp *.cuh)
file(GLOB CURRENT_SOURCES *.cpp *.cu)
source_group("Include" FILES ${CURRENT_HEADERS})
source_group("Source" FILES ${CURRENT_SOURCES})
CUDA_ADD_EXECUTABLE(test_cuda_project ${CURRENT_HEADERS} ${CURRENT_SOURCES})