CMake——从入门到百公里加速6.7s

目录

一、前言

二、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.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文件,如下图所示:

CMake——从入门到百公里加速6.7s_第1张图片

 编写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

CMake——从入门到百公里加速6.7s_第2张图片

在vscode下Cmake快捷键ctrl+shift+p,打印cmake

CMake——从入门到百公里加速6.7s_第3张图片

如果在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是⼀组由字⺟和符号组成的特殊⽂本。

CMake——从入门到百公里加速6.7s_第4张图片

CMake——从入门到百公里加速6.7s_第5张图片

3.2 GUI构建

打开GUI界面,添加源码路径,二进制路径,点击configure,Generate即可

CMake——从入门到百公里加速6.7s_第6张图片

 四 关键字

4.1 add_library

add_library( [STATIC | SHARED | MODULE]
            [EXCLUDE_FROM_ALL]
            [...])
add_library根据源码来生成库。是个逻辑名称,在项目中必须唯一。完整的库名依赖于具体构建方式(可能为lib.a or .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( [WIN32] [MACOSX_BUNDLE]
               [EXCLUDE_FROM_ALL]
               [source1] [source2 ...])
是可执行文件的名称,在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( IMPORTED [GLOBAL])
将工程外部的可执行目标文件导入进来,不会有任何构建可执行目标文件的动作发生
name:导入可执行文件目标的名字
GLOBAL:可执行目标文件的范围为文件创建的目录及子目录;指定GLOBAL则会将范围扩大到整个工程。
IMPORTED:选项指定后,属性IMPORTED会被置为TRUE,在工程内构建的可执行目标文件的属性IMPORTED会被置为FALSE。

# 第三种:Alias Executables
add_executable( ALIAS )
为可执行目标文件创建一个别名。创建该别名后,可以使用别名进行可执行目标的读、测试操作,但是不能利用别名对可执行目标的修改属性操作


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(  )

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 ... [...]) 二进制、动态库、静态库
install({FILES | PROGRAMS} ... [...]) 文件
install(DIRECTORY ... [...]) 目录
install(SCRIPT  [...])脚步
install(CODE  [...])  安装时要执行的代码
install(EXPORT  [...]) 用于将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 ...])

添加链接动态链接库

动态链接库要写在ADD_EXECULABLE之下,第一个参数表示要将库中的内容加载到可执行文件。 由 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([] "message text" ...) # General messages
message( "message text" ...) # Reporting checks

FATAL_Error:停止处理和生产

WARNING:继续处理

STATUS:用户可能感兴趣的主要信息

NOTICE:重要信息

CHECK_START:记录关于将要执行的检查简明信息

CHECK_PASS:记录检查的成功结果

CHECK_FAIL:记录检查不成功的结果

4.12 option

一般与if配合使用,options可以给变量赋值,然后被if条件语句引用

用于控制编译流程,相当于C语言中的宏条件编译
option( "" [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( ... [PARENT_SCOPE])
set(      [[CACHE      [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( [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

CMake——从入门到百公里加速6.7s_第7张图片

 可以通过对应的.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 多文件编译

CMake——从入门到百公里加速6.7s_第8张图片

 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  COMMAND  [...]
          [CONFIGURATIONS ...]
          [WORKING_DIRECTORY ]
          [COMMAND_EXPAND_LISTS])

Adds a test called ````.  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 ```` 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——从入门到百公里加速6.7s_第9张图片

 

# 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 +条件

CMake——从入门到百公里加速6.7s_第10张图片

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)

你可能感兴趣的:(单元测试,软件构建)