【CMake】CMake入门(三)常见的cmake脚本指令 日志输出 CMake内置的变量

本篇文章不是新手入门教学文章,主要是记录笔者个人的学习笔记

CMake入门(三)

  • 一、CMake中的脚本指令
    • 1. 设置CMake最低版本要求
    • 2、指定项目名称
    • 3、添加生成的可执行文件
    • 4、添加生成库文件
    • 5、搜索文件
    • 6、生成文件
    • 7、添加子目录
    • 8、添加头文件的搜索路径
    • 9、添加要链接库的路径
    • 10、添加要连接的库
    • 11、添加依赖
    • 12、添加自定义目标
    • 13、属性设置
    • 14、为目标追加源文件
    • 15、将 cmake 缓存变量标记为高级
  • 二、日志输出
  • 三、CMake内置的变量

一、CMake中的脚本指令

1. 设置CMake最低版本要求

# 用法
cmake_minimum_required(VERSION <版本号>)# 示例
cmake_minimum_required(VERSION 3.10)

2、指定项目名称

如果不做特殊配置,最终生成的可执行文件名与项目名称保持一致。

# 用法
project(<项目名>)# 示例 指定项目名称为Tutorial
project(Tutorial)

3、添加生成的可执行文件

利用指定的源文件在项目中添加可执行文件

# 用法: 源文件可以有多个,用空格隔开
add_executable(<可执行文件名> <源文件列表>)# 示例: 可执行文件名为Tutorial,用到的源文件为tutorial.cxx
add_executable(Tutorial tutorial.cxx)

4、添加生成库文件

# 用法
add_library(<name> [<type>]  <sources>...)
# 示例
add_library(MathFunctions SHARED mysqrt.cxx MathFunctions.h)

这里的type可以使用

  • STATIC 生成静态库
  • SHARED 生成动态库

5、搜索文件

如果一个项目里边的源文件很多,在编写CMakeLists.txt文件的时候不可能将项目目录的各个文件一一罗列出来,这样太麻烦也不现实。所以,在CMake中为我们提供了搜索文件的命令,可以使用aux_source_directory命令或者file命令。

  • aux_source_directory 命令可以查找某个路径下的所有源文件(.c .cpp .cc .cxx .c++) ,它不会递归查找子目录中的文件
# 用法
aux_source_directory(< dir > < variable >)
# 示例
aux_source_directory(${CMAKE_CURRENT_SOURCE_DIR}/src SRC_LIST)  # 搜索 src 目录下的源文件

  • file命令用于搜索指定类型的文件
# 用法
file(GLOB/GLOB_RECURSE 变量名 要搜索的文件路径和文件类型)

GLOB: 将指定目录下搜索到的满足条件的所有文件名生成一个列表,并将其存储到变量中。

GLOB_RECURSE:递归搜索指定目录,将搜索到的满足条件的文件名生成一个列表,并将其存储到变量中。

# 示例
# 搜索当前目录的src目录下所有的源文件,并存储到变量中
file(GLOB MAIN_SRC ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)
# 示例
# 搜索当前目录的include目录下所有的头文件,并存储到变量中
file(GLOB MAIN_HEAD ${CMAKE_CURRENT_SOURCE_DIR}/include/*.{h,hpp})

6、生成文件

configure_file 是 CMake 中的一个命令,这个命令将一个.in文件作为模板,将.in文件复制为输出文件,并把其中的变量引用替换为CMakeLists.txt中定义的变量,如果变量未定义,则替换为空串。

  • 输入文件中的变量引用CMakeLists.txt中变量的方式为: @变量名@ 或者 ${变量名}

  • 输入文件默认路径为CMakeLists.txt所在的路径,输出文件的路径默认为cmake生成文件所在的路径。


# 用法
configure_file(<inputfile> <outputfile>)# 示例
configure_file(TutorialConfig.h.in TutorialConfig.h)

在TutorialConfig.h.in 文件中

// 在CMakeLists.txt文件中,Tutorial_VERSION_MAJOR = 1  Tutorial_VERSION_MINOR = 0  STR_VAR = hello world
#define Tutorial_VERSION_MAJOR @Tutorial_VERSION_MAJOR@
#define Tutorial_VERSION_MINOR ${Tutorial_VERSION_MINOR}// 因为CMakeLists.txt中定义的字符串都是裸的,所以如果想要最终生成的头文件中变量的值为字符串,需要用双引号包起来
#define STR_VAR "@STR_VAR@"

经过configure_file(TutorialConfig.h.in TutorialConfig.h) 之后会生成一个TutorialConfig.h的头文件,头文件中的内容是:

#define Tutorial_VERSION_MAJOR 1
#define Tutorial_VERSION_MINOR 0
#define STR_VAR "hello world"

通过这样的方式:我们可以将CMakeLists.txt中的信息写入到头文件中,再编译到so库文件或者可执行程序中,这样,就可以通过提供库文件的接口或者可执行程序的打印中得到这些值了。

扩展1:
在模板文件.in 中支持一种语法叫#cmakedefine, 其用法与#define相同,用在configure_file的输入文件当中进行宏定义,不同点在于:

  • #define本身就是C/C++当中的宏定义,所以不论对应的变量是否在CMakeLists.txt中有定义,都会在输出文件中定义一个宏。
  • #cmakedfine则会根据变量在CMakeLists.txt中的定义情况来确定是否会在输出文件中定义宏。
    • 如果变量在CMakeLists.txt中没有定义或已定义但是一个判断为假的布尔值,则不会在输出文件中定义对应的宏。
    • 如果变量在CMakeLists.txt中有定义且不为布尔值、或者为布尔值但判断为真,则会在输出文件中定义对应的宏。

扩展2:
configure_file 中有很多参数,这些参数这里只进行简单介绍,不在演示

  • NO_SOURCE_PERMISSIONS 生成文件时,不拷贝源文件的权限,对于新生成的文件,采用默认的普通文本权限。
  • USE_SOURCE_PERMISSIONS 生成文件时,拷贝源文件的权限(默认)。
  • COPYONLY 只拷贝文本,不进行任何替换
  • ESCAPE_QUOTES 对于使用\进行转义,防止出现问题
  • @ONLY 只替换@变量名@形式的变量
  • NEWLINE_STYLE <style> 指定文件的换行符

7、添加子目录

为当前项目添加子目录。子目录当中必须包含一个CMakeLists.txt文件,其中可以不写cmake_minimum_requiredproject

# 用法
add_subdirectory(<source_dir>)
# 示例
add_subdirectory(MathFunctions)

8、添加头文件的搜索路径

  • include_directories
    这是一个全局命令,它将路径添加到所有目标的头文件查找路径中。这意味着在这个命令后定义的所有目标(不论是库还是可执行目标)都能找到这个路径下的头文件。同样,子目录下定义的所有目标也都可以。尽管这个命令很方便,但在大型项目中,它可能会导致不必要的文件包含或者头文件命名冲突。
# 用法
include_directories(dir1 dir2 ...)
# 示例
include_directories(include)

  • target_include_directories
    是一个目标级命令,它只影响一个特定的目标。这个命令允许你为一个特定的构建目标(例如一个库或一个可执行文件)指定头文件查找路径。
# 用法
target_include_directories(<target> <INTERFACE|PUBLIC|PRIVATE> <dir1 dir2 ...>)# 示例
target_include_directories(Tutorial PUBLIC ${PROJECT_BINARY_DIR})
  • PUBLIC 表示本目标需要用,依赖这个目标的其他目标也需要。
  • INTERFACE 表示本目标不需要,依赖本目标的其他目标需要。
  • PRIVATE表示本目标需要,依赖这个目标的其他目标不需要。

9、添加要链接库的路径

  • link_directories(directory1 directory2 …)
    同理这也是一个全局命令,它将路径添加到所有目标的库文件查找路径中。
# 用法
link_directories(directory1 directory2 ...)
# 示例
link_directories(/path/to/my/library)
  • target_link_directories
    是一个目标级命令,它只影响一个特定的目标。
# 用法
target_link_directories(target <PRIVATE|PUBLIC|INTERFACE> dir1 [dir2 ...])
# 示例
target_link_directories(MyExecutable PRIVATE ${CMAKE_SOURCE_DIR}/libs)

10、添加要连接的库

注意target_link_libraries此命令必须在add_executableadd_library 后面使用,因为此命令用于为特定目标添加链接库,所以在你使用它之前,你需要先定义这个目标,而add_executableadd_library 这两个命令就是用来定义目标的。

# 用法
target_link_libraries(<target><PRIVATE|PUBLIC|INTERFACE> <item>...[<PRIVATE|PUBLIC|INTERFACE> <item>...]...)# 示例
target_link_libraries(Tutorial PUBLIC MathFunctions)

11、添加依赖

使用add_dependencies可以给添加同级目标之间的相互依赖,保证依赖先生成, 其基本格式如下:

# 用法
add_dependencies(<target> [<target-dependency>]...)
# 示例
add_executable(Tutorial2 tutorial.cxx)
add_dependencies(Tutorial2 Tutorial) # 加上这句可以保证Tutorial 先于Tutorial2  生成
add_executable(Tutorial tutorial.cxx)

12、添加自定义目标

add_custom_target(Name [ALL] [command1 [args1...]][COMMAND command2 [args2...] ...][DEPENDS depend depend depend ... ][WORKING_DIRECTORY dir])

使用add_custom_target可以添加一个自定义目标,对于自定义目标在Linux下可以使用make help 来查看可以执行的目标。

  • ALL 添加了ALL以后,当执行ALL目标(默认目标)时,会自动执行该自定义目标。
  • COMMAND 后面跟上要执行的命令以及参数
  • DEPENDS 后面加上该目标的依赖
  • WORKING_DIRECTORY 设置该目标的工作目录
# 示例
add_custom_target(my_target1 ALL COMMAND echo "hello world")
add_custom_target(my_target2 COMMAND dir  WORKING_DIRECTORY  ../../)

13、属性设置

(这里有些复杂,可以不看)

属性的设置可以使用下面的指令:

set_property(<GLOBAL                      | # 设置全局属性DIRECTORY [<dir>]           | # 设置目录的属性TARGET    [<target1> ...]   | # 设置目标的属性SOURCE    [<src1> ...]		# 设置源文件的属性[DIRECTORY <dirs> ...][TARGET_DIRECTORY <targets> ...] |INSTALL   [<file1> ...]     | # 设置安装目录的属性TEST      [<test1> ...]     | # 设置测试的属性CACHE     [<entry1> ...]    > # 设置缓存的属性[APPEND] [APPEND_STRING] 		# 添加属性PROPERTY <name> [<value1> ...])

读取属性:

get_property(<variable><GLOBAL             |DIRECTORY [<dir>]  |TARGET    <target> |SOURCE    <source>[DIRECTORY <dir> | TARGET_DIRECTORY <target>] |INSTALL   <file>   |TEST      <test>   |CACHE     <entry>  |VARIABLE           >PROPERTY <name>[SET | DEFINED | BRIEF_DOCS | FULL_DOCS])
  • SET:将<variable>设为该属性是否已设置

  • DEFINED:将<variable>设为该属性是否已定义


全局属性

set_property(GLOBAL PROPERTY <name> [<value1> ...])get_property(<variable> GLOBAL  PROPERTY <name>)
get_cmake_property(<var> <property>)

目录属性

set_property(DIRECTORY [<dir>] PROPERTY <name> [<value1> ...])
set_directory_properties(PROPERTIES prop1 value1 [prop2 value2] ...)get_property(<variable> DIRECTORY [<dir>]  PROPERTY <name>)
get_directory_property(<variable> [DIRECTORY <dir>] <prop-name>)

目标属性

set_property(TARGET <target1> PROPERTY <name> [<value1> ...])
set_target_properties(target1... PROPERTIES prop1 value1 prop2 value2 ...)get_property(<variable> TARGET <target>  PROPERTY <name>)
get_target_property(<VAR> target property)

源文件属性

set_property(SOURCE [<src1> ...] [DIRECTORY <dirs> ...] [TARGET_DIRECTORY <targets> ...] PROPERTY <name> [<value1> ...])
set_source_files_properties(<files> ...[DIRECTORY <dirs> ...][TARGET_DIRECTORY <targets> ...]PROPERTIES <prop1> <value1>[<prop2> <value2>] ...)get_property(<variable> SOURCE <source>  PROPERTY <name>)
get_source_file_property(<variable> <file>[DIRECTORY <dir> | TARGET_DIRECTORY <target>]<property>)

测试属性

set_tests_properties(test1 [test2...] PROPERTIES prop1 value1 prop2 value2)get_test_property(test property VAR)

14、为目标追加源文件

target_sources 的基本格式如下:

# 用法
target_sources(<target><INTERFACE|PUBLIC|PRIVATE> [items1...][<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
# 示例
# add the executable
add_executable(Tutorial )target_sources(Tutorial PUBLIC tutorial.cxx)

15、将 cmake 缓存变量标记为高级

使用的命令如下:

mark_as_advanced([CLEAR|FORCE] <var1> ...)

设置完毕以后,除非cmake GUI 将show advanced 选项处于打开状态,否则高级变量不会显示在gui中。在脚本模式下,“高级/非高级”状态不起作用。

二、日志输出

在CMake中可以用用户显示一条日志消息,该命令的名字为message

message([STATUS|WARNING|AUTHOR_WARNING|FATAL_ERROR|SEND_ERROR] "message to display" ...)
  • (无) :重要消息
  • STATUS :非重要消息
  • WARNING:CMake 警告, 会继续执行
  • AUTHOR_WARNING:CMake 警告 (dev), 会继续执行
  • SEND_ERROR:CMake 错误, 继续执行,但是会跳过生成的步骤
  • FATAL_ERROR:CMake 错误, 终止所有处理过程

CMake的命令行工具会在stdout上显示STATUS消息,在stderr上显示其他所有消息。CMake的GUI会在它的log区域显示所有消息。

CMake警告和错误消息的文本显示使用的是一种简单的标记语言。文本没有缩进,超过长度的行会回卷,段落之间以新行做为分隔符。

# 示例
# 输出一般日志信息
message(STATUS "source path: ${PROJECT_SOURCE_DIR}")
# 输出警告信息
message(WARNING "source path: ${PROJECT_SOURCE_DIR}")
# 输出错误信息
message(FATAL_ERROR "source path: ${PROJECT_SOURCE_DIR}")

三、CMake内置的变量

cmake内置的变量有很多,详细介绍可以查看官方文档

这里只介绍一些关于编译器和系统相关的内置变量,通过这些变量我们能够根据编译器和系统进行条件编译。

  • ANDROID 安卓平台
  • APPLE 苹果平台(macOS, iOS, tvOS, visionOS or watchOS)
  • IOS ios平台
  • LINUX Linux平台
  • WIN32 windows平台
  • MINGW MINGW编译器
  • MSVC MSVC编译器

对于gcc, clang由于没有内置的变量,如果想要判断需要采用下面的方式:

if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU")message(STATUS "当前编译器是 G++ 或 MinGW")
elseif (CMAKE_CXX_COMPILER_ID STREQUAL "Clang")message(STATUS "当前编译器是 Clang")

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/15780.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【GESP试卷】2024年03月Scratch四级试卷

2024年GESP03月认证Scratch四级试卷 分数&#xff1a;100 题数&#xff1a;27 一、单选题(共15题&#xff0c;每题2分&#xff0c;共30分) 010203040506070809101112131415CDBBACBCDCDADBA 1、小杨的父母最近刚刚给他买了一块华为手表&#xff0c;他说手表上跑的是鸿蒙&…

【雷丰阳-谷粒商城 】【分布式基础篇-全栈开发篇】【00】补充

持续学习&持续更新中… 守破离 【雷丰阳-谷粒商城 】【分布式基础篇-全栈开发篇】【00】补充 插件IDEAVsCode MavenvagrantDocker解决MySQL连接慢问题启动&#xff08;自动&#xff09;Docker注意切换到root用户远程访问MySQL MyBatisPlus代码地址参考 插件 IDEA Mybati…

【数据挖掘】四分位数识别数据中的异常值(附代码)

写在前面&#xff1a; 首先感谢兄弟们的订阅&#xff0c;让我有创作的动力&#xff0c;在创作过程我会尽最大能力&#xff0c;保证作品的质量&#xff0c;如果有问题&#xff0c;可以私信我&#xff0c;让我们携手共进&#xff0c;共创辉煌。 路虽远&#xff0c;行则将至&#…

c++11 auto类型推导的使用建议和注意事项

概述: 首先c是强类型语言&#xff0c;也就是在定义变量的时候必须指定具体的类型。 像我们常用的int&#xff0c;float&#xff0c;char等等都是类型&#xff0c;auto关键字原本的意思是说明某个变量是自动变量&#xff0c;c11提升了它的功能。 在c11之后&#xff0c;我们可以使…

STM32F1之OV7725摄像头

目录 1. 摄像头简介 2. OV7725 摄像头简介 3. OV7725 引脚 4. OV7725 功能框架图 5. SCCB时序 5.1 SCCB 的起始、停止信号及数据有效性 5.2 SCCB 数据读写过程 1. 摄像头简介 在各类信息中&#xff0c;图像含有最丰富的信息&#xff0c;作为机…

SVM原问题与对偶问题

目的&#xff1a;求出我们的f(X)&#xff0c;它代表着我们X映射到多维的情况&#xff0c;能够帮我们在多维中招到超平面进行分类。 1.优化问题&#xff1a; 1.1推荐好书&#xff1a; 1.2 优化理论中的原问题&#xff1a; 原问题和限制条件如下&#xff1a; 这是一个泛化性…

MATLAB算法实战应用案例精讲-【数模应用】KANO模型

目录 前言 发展历程 几个相关概念 算法原理 什么是KANO模型?

【漏洞复现】英飞达医学影像存档与通信系统 WebJobUpload 任意文件上传漏洞

0x01 产品简介 英飞达医学影像存档与通信系统 Picture Archiving and Communicaton System&#xff0c;它是应用在医院影像科室的系统&#xff0c;主要的任务就是把日常产生的各种医学影像(包括核磁&#xff0c;CT&#xff0c;超声&#xff0c;各种X光机&#xff0c;各种红外仪…

LeetCode - 数组 - 四数之和

题目地址 描述 给你一个由 n 个整数组成的数组 nums &#xff0c;和一个目标值 target 。请你找出并返回满足下述全部条件且不重复的四元组 [nums[a], nums[b], nums[c], nums[d]] &#xff08;若两个四元组元素一一对应&#xff0c;则认为两个四元组重复&#xff09;&#x…

python从入门到精通02

一、平均油耗计算 total float(input("请输入加油的总金额&#xff1a;")) kilometers int(input("请输入行驶的总里程&#xff1a;")) average total / kilometers print("平均油耗是&#xff1a;", average,"元/公里") 二、华氏…

删除当前磁盘空文件夹小工具

删除当前磁盘空文件夹小工具 chcp 65001 >nulecho off setlocal EnableDelayedExpansionecho 正在扫描空文件夹&#xff0c;请稍候...for /f "delims" %%d in (dir /ad /b /s "\*") do (set "folder%%d"dir /a /b "!folder!" | fi…

个人学习之路

大学的时候在学校学习的是java&#xff0c;没有兴趣&#xff0c;且罢 快毕业了&#xff0c;为了工作学了C和C&#xff0c;每每也是在煎熬之中度过&#xff0c;总是否定自己&#xff0c;想要放弃又重新拾起来&#xff0c;做了相关的工作 后面换了工作&#xff0c;转到了python…

Spring IOC深度解析:IOC容器的原理与高级特性详解

1. Spring IOC容器概述 Spring框架是Java企业级应用开发中的重量级选手&#xff0c;其中IOC&#xff08;控制反转&#xff09;是其核心功能之一。通过引入IOC容器&#xff0c;Spring改变了对象的创建方式及其依赖关系的管理&#xff0c;进而带来了应用程序设计的革命。 1.1 什…

cs与msf权限传递以及mimikatz抓取win2012明文密码

简单的介绍 cs与msf的简单介绍 我查找过资料得出&#xff0c;Cobalt Strike 的前身是 Armitage&#xff0c;而 Armitage 又可以理解为 Metasploit Framework 的图形界面版&#xff0c;因此 Cobalt Strike 与 Metasploit Framework 在很多地方都是兼容的&#xff0c;所以我们便…

【电子信息(工程)】电子通信创新创业教育综合

电子通信创新创业教育 阐述电磁场、电磁波和电磁频谱及应用一、电磁场 法拉第根据电流与磁场的关系,提出了电磁感应定律:如果电磁场中有处于运动状态下的闭合回路导体存在,流经该导体磁场的磁场强度和磁场量,通常都会出现相应的变化,电磁感应电流由此而产生。随后,英国的…

人工智能 框架 paddlepaddle 飞桨 使用指南 使用例子 线性回归模型demo 详解

安装过程&使用指南&线性回归模型 使用例子 本来预想 是安装 到 conda 版本的 11.7的 但是电脑没有gpu 所以 安装过程稍有变动,下面简单讲下 conda create -n paddle_env117 python=3.9 由于想安装11.7版本 py 是3.9 所以虚拟环境名称也是 paddle_env117 activa…

下载和安装AD19 - Altium Designer 19.1.9 Build 167

虽然有AD24 的安装资源&#xff0c;但是我比较喜欢19 这个数字[doge] 下载 仍然是从毛子网站源头进货&#xff1a;https://rutracker.net/forum/viewtopic.php?t5754276&#xff0c;网盘: https://pan.baidu.com/s/1ic31N4h7HS2FBu7JFll0YQ?pwdvjum 提取码: vjum 安装 压…

如何用pyecharts工具制作地图

# # 导入地图构建使用的包 # from pyecharts.charts import Map # from pyecharts.options import VisualMapOpts # # # 创建一个地图 # China_map Map() # # # 给地图准备数据 # data [ # ("北京市", 100), # ("上海市", 95), # ("深圳…

【DevOps】深入了解RabbitMQ:AMQP协议基础、消息队列工作原理和应用场景

目录 一、核心功能 二、优势 三、核心概念 四、工作原理 五、交换机类型 六、消息确认 七、持久性和可靠性 八、插件和扩展 九、集群和镜像队列 十、客户端库 十一、管理界面 十二、应用场景 RabbitMQ是一个基于AMQP协议的消息队列中间件&#xff0c;提供高可用、可…

[MRCTF2020]Xor

32位程序 主要逻辑 flagMSAWB~FXZ:J:tQJ"N bpdd}8g for i in range(len(flag)):print(chr(ord(flag[i])^i),end)