目录
一、前言
二、HelloWorld
三、CMAKE 界面
3.1 gui正则表达式
3.2 GUI构建
四 关键字
4.1 add_library
4.2 add_subdirectory
4.3 add_executable
4.4 aux_source_directory
4.5 SET设置变量
4.6 INSTALL安装
4.7 ADD_LIBRARY
4.8 SET_TARGET_PROPERTIES
4.9 INCLUDE_DIRECTORIES
4.10 TARGET_LINK_LIBRARY
4.11 MESSAGE
4.12 option
4.13 configure_file
4.14 Set
4.15 find_package
4.16 add_dependencies
4.17 cmake package
五、CMake实例
5.1 多文件编译
5.2 配置选项
5.3 CTest (cmake test)
5.4 gbd调试
5.5 CPack
一、前言
CMake是一个跨平台的安装/编译工具,它能用简单的语句描述所有平台的安装/编译过程。
CMake可以生成编译构建工具的脚本,也可以调用编译构建工具去构建源码。
CTest可以进行单元测试构建和运行,也可以集成第三方的单元测试框架如gtest。
CPack可以打包,如库、可执行文件,解析CMakeList.txt打包如二进制或源码包,可以进行版本控制。
www.cmake.org
一般安装CMake后会有帮助文档,CMake官方文档
实战不足导致百公里加速不足,继续更新!
快速查找帮助文档:cmake --help-command find_library | more
cmake --help-variable-list | grep CMAKE | grep HOST
cmake --help-property-list | grep NAME
CMake 入门实战 | HaHack
二、HelloWorld
建立目录,并编写一个简单的cpp文件,如下图所示:
编写CMakeLists.txt
# minimum version
cmake_minimum_required(VERSION 3.23 FATAL_ERROR)
project(projectName
VERSION 1.0
DESCRIPTION "know how to use cmake"
HOMEPAGE_URL "https://edu.csdn.net/learn/37441/581656?spm=1003.2001.3001.4143"
LANGUAGES CXX #指定编程语言为CPP, 默认是CXX C
)
#优化message输出
list(APPEND CMAKE_MESSAGE_CONTEXT Top)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
message("-------------hello-------------")
add_executable(main src/main.cpp)
message("-------------world-------------")
编译配置指令: cmake -S . -B build
编译: cmake --build build
在vscode中选择cmake套件:点击左下角cmake,选择使用哪个开发编译套件,进行debug和run
在vscode下Cmake快捷键ctrl+shift+p,打印cmake
如果在Windows下使用cmake .. 后发现没有生成makefile文件,以下解决方法:
mkdir build
cd build
cd VS2013开发人员命令提示
cmake -G "NMake Makefiles" ..
然后
nmake
解决在[windows10+VS2013]下cmake不能生成makefile问题_cmake没有生成makefile_Shu_xiaobai_的博客-CSDN博客
三、CMAKE 界面
3.1 gui正则表达式
regular expression 简称regex是⼀组由字⺟和符号组成的特殊⽂本。
3.2 GUI构建
打开GUI界面,添加源码路径,二进制路径,点击configure,Generate即可
四 关键字
4.1 add_library
add_library(<name> [STATIC | SHARED | MODULE]
[EXCLUDE_FROM_ALL]
[<source>...])
add_library根据源码来生成库。<name>是个逻辑名称,在项目中必须唯一。完整的库名依赖于具体构建方式(可能为lib<name>.a or <name>.lib)。
STATIC指静态库,SHARED指动态库,MODULE指在运行期通过类似于dlopen的函数动态加载。
4.2 add_subdirectory
add_subdirectory(source_dir [binary_dir] [EXCLUDE_FROM_ALL])
用来向当前工程添加存放源文件的子目录。将子目录添加到构建系统中。
source_dir指定一个目录,其中存放CMakeLists.txt文件和代码文件。
binary_dir指定的目录存放输出文件,如果没有指定则使用source_dir。
4.3 add_executable
使用指定的源文件来生成目标可执行文件。具体分为三类:普通、导入、别名
# 第一种:Normal Executables
add_executable(<name> [WIN32] [MACOSX_BUNDLE]
[EXCLUDE_FROM_ALL]
[source1] [source2 ...])
<name>是可执行文件的名称,在cmake工程中必须唯一。
WIN32用于在windows下创建一个以WinMain为入口的可执行文件。
MACOSX_BUNDLE用于mac系统或者IOS系统下创建一个GUI可执行应用程序
EXCLUDE_FROM_ALL:用于指定可执行目标是否会被构建,当该选项使用的时候,可执行目标不会被构建
[source1] [source2 …]:构建可执行目标文件所需要的源文件。也可以通过target_sources()继续为可执行目标文件添加源文件,要求是在调用target_sources之前,可执行目标文件必须已经通过add_executable或add_library定义了。
# 第二种:Imported Executables
add_executable(<name> IMPORTED [GLOBAL])
将工程外部的可执行目标文件导入进来,不会有任何构建可执行目标文件的动作发生
name:导入可执行文件目标的名字
GLOBAL:可执行目标文件的范围为文件创建的目录及子目录;指定GLOBAL则会将范围扩大到整个工程。
IMPORTED:选项指定后,属性IMPORTED会被置为TRUE,在工程内构建的可执行目标文件的属性IMPORTED会被置为FALSE。
# 第三种:Alias Executables
add_executable(<name> ALIAS <target>)
为可执行目标文件创建一个别名。创建该别名后,可以使用别名进行可执行目标的读、测试操作,但是不能利用别名对可执行目标的修改属性操作
ADD_EXECUTABLE(main ${SRC_LIST}) 将变量SRC_LIST编译成可执行文件main
ADD_EXECUTABLE(main a.c b.c c.c)
https://blog.csdn.net/qq_26849933/article/details/127138497
4.4 aux_source_directory
将src目录设置为1个变量表示。
将当前目录所有源文件的文件名赋值给变量 DIR_SRCS
aux_source_directory( <dir> <variable>)
4.5 SET设置变量
用于将指定的文件名用变量表示
SET(SRC_LIST main.cpp add.cpp)
4.6 INSTALL安装
把编译出来的文件(可执行文件、静态库、动态库、头文件等)拷贝到相应的目录下面;默认bin安装在/usr/local/bin,/usr/local/include中,/usr/local/是默认安装目录,可以通过CMAKE_INSTALL_PREFIX变量指定拷贝到哪个根目录SET(CMAKE_INSTALL_PREFIX <你要安装的路径>)。
install(TARGETS <target>... [...]) 二进制、动态库、静态库
install({FILES | PROGRAMS} <file>... [...]) 文件
install(DIRECTORY <dir>... [...]) 目录
install(SCRIPT <file> [...])脚步
install(CODE <code> [...]) 安装时要执行的代码
install(EXPORT <export-name> [...]) 用于将TARGETS所需的外部符号写入到一个CMake文件,并安装到项目中
安装文件
INSTALL(FILES xxx DESTINATION 路径)
安装非目标可执行文件
INSTALL(PROGRAMS xxxx DESTINATION 路径)
安装目录
INSTALL(DERECTORY xxx DESTINATION 路径)
# 安装可执行文件,静态库和动态库。CMAKE会根据target类型自动推断。
# 通过ARCHIVE/LIBRARY/RUNTIME关键字分别指定静态库、动态库和可执行文件的属性。
比如指定安装后缀DESTINATION。
例如静态库安装路径就是前缀+后缀=${CMAKE_SOURCE_DIR}/install/lib。
还可以从/开始直接指定绝对路径。
install(TARGETS mylib mylib-shared main
ARCHIVE DESTINATION lib #静态库
LIBRARY DESTINATION lib #动态库
RUNTIME DESTINATION bin #可执行文件
)
cmake执行完生成makefile, make install
cmake(8):install命令详解_install(targets_翔底的博客-CSDN博客
4.7 ADD_LIBRARY
生成链接库
将源文件创建为动态库so文件;ADD_LIBRARY(库名 类型 源文件);类型SHARED 表示动态STATIC是静态;
4.8 SET_TARGET_PROPERTIES
设置输出的名称,动态链接库还可以指定版本。
4.9 INCLUDE_DIRECTORIES
将指定目录添加到编译器的头文件搜索路径之下,指定的目录被解释成当前源码路径的相对路径
添加头文件目录,相当于g++ -I
include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...])
4.10 TARGET_LINK_LIBRARY
添加链接动态链接库
动态链接库要写在ADD_EXECULABLE之下,第一个参数表示要将库中的内容加载到可执行文件。<target> 由 add_execuable()或者add_library()之类的命令创建
link_libraries()添加需要链接的库文件路径,是全路径
#添加头文件目录, 相当于g++ -I
include_directories(/home/larry/myproject/myc++proj/muduostd)
# 添加库文件目录, 相当于g++ -L
link_directories(/home/larry/myproject/myc++proj/muduostd/build1/lib)
# 添加库链接
link_libraries(pthread)
#或在目标文件中链接
target_link_libraries(muduo_http muduo_net muduo_base pthread)
4.11 MESSAGE
message([<mode>] "message text" ...) # General messages
message(<checkState> "message text" ...) # Reporting checks
FATAL_Error:停止处理和生产
WARNING:继续处理
STATUS:用户可能感兴趣的主要信息
NOTICE:重要信息
CHECK_START:记录关于将要执行的检查简明信息
CHECK_PASS:记录检查的成功结果
CHECK_FAIL:记录检查不成功的结果
4.12 option
一般与if配合使用,options可以给变量赋值,然后被if条件语句引用
用于控制编译流程,相当于C语言中的宏条件编译
option(<variable> "<help_text>" [value])
variable 定义选项名称
help text说明选项含义
value 一般是OFF ON
4.13 configure_file
一般用于自定义编译选项或者自定义宏使用场景
configure_file(input output options)
configure_file会根据options指定的规则对input中cmakedefine关键字进行转换
将@var@ 或 ${var} 换成cmake指定的值
将input文件#cmakedefine换成#define var 或 #undef var
示例
CMakeList.txt
option(var1 "set var1.." ON)
set(var2 "varstring")
set(var3 11)
config.h.in
#cmakedefine var1
#cmakedefine var2 "@var2@"
#cmakedefine var3 "${var3}"
cmake后生成config.h
#define var1
#define var2 "varstring"
#define var3 "11"
4.14 Set
将一个CMake变量variable设置为给定值value;
set(<variable> <value>... [PARENT_SCOPE])
set( <variable> <value> [[CACHE <type> <docstring> [FORCE]] | PARENT_SCOPE])
如果采用 set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions) 可以继续添加库名称变量。
4.15 find_package
find_package引入外部包, cmake在安装路径(比如/usr/local/share/cmake-3.16/Modules$
)已经提供了一些官方依赖包, 以.cmake结尾可以直接用find_pakcage进行引用
find_package(<PackageName> [version] [EXACT] [QUIET] [MODULE]
在指定目录下寻找头文件和动态库文件位置,可以指定多个目标路径,然后用某个变量名表示
查找头文件路径 find_path(路径变量别名 文件名 路径1 路径2 ...);
查找库 find_library(变量名 NAMES HINTS 路径);
- NAMES 为库指定一个或多个可能的名称
- HINTS, PATHS 除了默认位置,还指定要搜索的目录。该子选项读取系统环境变量的路径
- DOC 指定缓存条目的文档字符串
find_library(ADD_LIBRARY NAMES add PATHS /usr/lib/add /usr/local/lib/add ${CMAKE_SOURCE_DIR}/ModuleMode)
4.16 add_dependencies
ADD_DEPENDENCIES(main a.so b.so) 提醒编译器先生成main依赖的a.so b.so再去生成main
4.17 cmake package
可以通过对应的.c查看源码,如何使用:
#引入
include (${CMAKE_ROOT}/Modules/CheckFunctionExists.cmake)
# 检查系统是否支持 pow 函数
check_function_exists (pow HAVE_POW)
if(NOT HAVE_POW)
# add something
endif(NOT HAVE_POW)
五、CMake实例
5.1 多文件编译
math中的CMakeList.txt如下:
# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_LIB_SRCS 变量
aux_source_directory(. DIR_LIB_SRCS)
# 指定生成 MathFunctions 链接库
add_library (MathFunctions ${DIR_LIB_SRCS})
5.2 配置选项
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)
# 项目信息
project (Demo4)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# 是否使用自己的 MathFunctions 库
option (USE_MYMATH
"Use provided math implementation" ON)
# 加入一个配置头文件,用于处理 CMake 对源码的设置
configure_file (
"${PROJECT_SOURCE_DIR}/config.h.in"
"${PROJECT_BINARY_DIR}/config.h"
)
# 是否加入 MathFunctions 库
if (USE_MYMATH)
include_directories ("${PROJECT_SOURCE_DIR}/math")
add_subdirectory (math)
set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions)
endif (USE_MYMATH)
message("EXTRA_LIBS: " ${EXTRA_LIBS})
# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_SRCS 变量
aux_source_directory(. DIR_SRCS)
# 指定生成目标
add_executable (Demo ${DIR_SRCS})
target_link_libraries (Demo ${EXTRA_LIBS})
宏定义定义在CMakeList.txt中
set(HAVE_POW 0)
set(HAVE_ADD 1)
set(HAVE_SUB 0)
在config.h.in中
// does the platform provide pow function?
#cmakedefine HAVE_POW
#cmakedefine HAVE_ADD
#cmakedefine HAVE_SUB
使用CMake .. 生成config.h
// does the platform provide pow function?
/* #undef HAVE_POW */
#define HAVE_ADD
/* #undef HAVE_SUB */
5.3 CTest (cmake test)
enable_testing() 启用test 功能,测试该CMakeList.txt 所在目录及其子文件夹
第一步:
add_test()定义一个新测试,并设置测试名称和运行命令
Add a test to the project to be run by ``ctest(1)``.
add_test(NAME <name> COMMAND <command> [<arg>...]
[CONFIGURATIONS <config>...]
[WORKING_DIRECTORY <dir>]
[COMMAND_EXPAND_LISTS])
Adds a test called ``<name>``. The test name may contain arbitrary
characters, expressed as a :ref:`Quoted Argument` or :ref:`Bracket Argument`
if necessary. See policy ``CMP0110``. The options are:
``COMMAND``
Specify the test command-line. If ``<command>`` specifies an
executable target (created by ``add_executable()``) it will
automatically be replaced by the location of the executable created
at build time.
add_test(测试用例名字 可执行文件名字 传参1 传参2)
第二步:设置测试用例属性或者环境变量set_tests_properties
Set a property of the tests.
set_tests_properties(test1 [test2...] PROPERTIES prop1 value1 prop2 value2)
Sets a property for the tests. If the test is not found, CMake
will report an error.
Test property values may be specified using
``generator expressions``
for tests created by the ``add_test(NAME)`` signature.
set_tests_properties(名字(同add_test),属性 值)
第三步:执行 make test 或者 ctest -v 或者nmake test
# CMake 最低版本号要求
cmake_minimum_required (VERSION 2.8)
# 项目信息
project (Demo5)
set (CMAKE_INCLUDE_CURRENT_DIR ON)
# 是否使用自己的 MathFunctions 库
option (USE_MYMATH
"Use provided math implementation" ON)
# 加入一个配置头文件,用于处理 CMake 对源码的设置
configure_file (
"${PROJECT_SOURCE_DIR}/config.h.in"
"${PROJECT_BINARY_DIR}/config.h"
)
# 是否加入 MathFunctions 库
if (USE_MYMATH)
include_directories ("${PROJECT_SOURCE_DIR}/math")
add_subdirectory (math)
set (EXTRA_LIBS ${EXTRA_LIBS} MathFunctions)
endif (USE_MYMATH)
# 查找当前目录下的所有源文件
# 并将名称保存到 DIR_SRCS 变量
aux_source_directory(. DIR_SRCS)
# 指定生成目标
add_executable(Demo ${DIR_SRCS})
target_link_libraries (Demo ${EXTRA_LIBS})
#设置安装路径前缀
SET(CMAKE_INSTALL_PREFIX ./)
# 指定安装路径
install (TARGETS Demo DESTINATION bin)
install (FILES "${PROJECT_BINARY_DIR}/config.h"
DESTINATION include)
# 启用测试
enable_testing()
# 测试程序是否成功运行
add_test (NAME test_run COMMAND 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")
]]
# 定义一个宏,用来简化测试工作
macro (do_test arg1 arg2 result)
add_test (test_${arg1}_${arg2} Demo ${arg1} ${arg2})
set_tests_properties (test_${arg1}_${arg2}
PROPERTIES PASS_REGULAR_EXPRESSION ${result})
endmacro (do_test)
# 利用 do_test 宏,测试一系列数据
do_test (5 2 "is 25")
do_test (10 5 "is 100000")
do_test (2 10 "is 1024")
5.4 gbd调试
GDB是GNU开源组织发布的在linux操作系统下基于命令行的调试工具。sudo apt-get install gdb
Windows平台安装GDB调试器 (biancheng.net)
gdb 可执行程序 进入调试模式,基本调试命令:
n 执行一行代码,不会进入函数内部
s执行一行代码,进入函数内部
disp查看全局变量
watch n观察变量
break + filename +行号
break +行号 + if +条件
CMakeLists设置gdb的方法:
set(CMAKE_BUILD_TYPE "Debug")
set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb")
set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAGS} -O3 -Wall")
GDB调试器的简单使用(图文) - 知乎 (zhihu.com)
Linux下 gdb 调试-打断点的方法_gdb打断点_凌雪舞的博客-CSDN博客
5.5 CPack
下载NISS
cpack是打包程序,生成不同形式的可按照exe。
#包含该模块来搜索实时库,添加安装规则
include (InstallRequiredSystemLibraries)
#将license嵌入到安装程序中
set (CPACK_RESOURCE_FILE_LICENSE
"${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
#设置package版本号
set (CPACK_PACKAGE_VERSION_MAJOR "${Demo_VERSION_MAJOR}")
set (CPACK_PACKAGE_VERSION_MINOR "${Demo_VERSION_MINOR}")
#include(CPack)会在构建路径(Build tree)下生成两个cpack的配置文件,CPackConfig.cmake和#CPackSourceConfig.cmake,其实也就对应了两个构建目标:package和package_source;
include (CPack)
参考:
CMake 入门实战 | HaHack
cmake gdb 编译调试详解 - 知乎 (zhihu.com)