CMake常用指令

news2024/9/26 1:27:29

CMake常用指令

  • 一、前言
  • 二、基本指令
    • 2.1、ADD_DEFINITIONS
    • 2.2、ADD_DEPENDENCIES
    • 2.3、ADD_TEST 与ENABLE_TESTING 指令。
    • 2.4、AUX_SOURCE_DIRECTORY
    • 2.5、CMAKE_MINIMUM_REQUIRED
    • 2.6、EXEC_PROGRAM
    • 2.7、FILE 指令
    • 2.8、INCLUDE 指令
    • 2.9、其他指令
  • 三、FIND_系列指令
  • 四、控制指令
    • 4.1、IF 指令
    • 4.2、WHILE
    • 4.3、FOREACH
  • 总结

一、前言

cmake 比autotools 要简单很多。接下来集中的看一看 cmake 所提供的常用指令。在前面的文章我们已经讨论了很多指令的用法,如PROJECT,ADD_EXECUTABLE,INSTALL,ADD_SUBDIRECTORY,SUBDIRS,INCLUDE _DIRECTORIES,LINK_DIRECTORIES,TARGET_LINK_LIBRARIES,SET 等。

本节介绍更多的cmake 指令,为了编写的方便,将按照 cmake man page 的顺序来介绍各种指令,不再推荐使用的指令将不再介绍,INSTALL 系列指令在安装部分已经做了非常详细的说明,这里不在提及。

二、基本指令

2.1、ADD_DEFINITIONS

向C/C++编译器添加-D 定义,比如:

ADD_DEFINITIONS(-DENABLE_DEBUG -DABC)

参数之间用空格分割。

如果你的代码中定义了

#ifdef ENABLE_DEBUG 
// ...
#endif

这个代码块就会生效。

如果要添加其他的编译器开关,可以通过 CMAKE_C_FLAGS 变量和CMAKE_CXX_FLAGS 变量设置。

2.2、ADD_DEPENDENCIES

定义target 依赖的其他target,确保在编译本target 之前,其他的target 已经被构建。

ADD_DEPENDENCIES(target-name depend-target1 depend-target2 ...)

2.3、ADD_TEST 与ENABLE_TESTING 指令。

ENABLE_TESTING 指令用来控制 Makefile 是否构建test 目标,涉及工程所有目录。语法很简单,没有任何参数:

ENABLE_TESTING()

一般情况这个指令放在工程的主 CMakeLists.txt 中。

ADD_TEST 指令的语法是:

ADD_TEST(testname Exename arg1 arg2 ...)

testname 是自定义的test 名称,Exename 可以是构建的目标文件也可以是外部脚本等等。后面连接传递给可执行文件的参数。如果没有在同一个 CMakeLists.txt 中打开ENABLE_TESTING()指令,任何 ADD_TEST 都是无效的。

比如:

ADD_TEST(mytest ${PROJECT_BINARY_DIR}/bin/main) 
ENABLE_TESTING()

生成Makefile 后,就可以运行 make test 来执行测试了。

2.4、AUX_SOURCE_DIRECTORY

基本语法是:

AUX_SOURCE_DIRECTORY(dir VARIABLE)

作用是发现一个目录下所有的源代码文件并将列表存储在一个变量中,这个指令临时被用来自动构建源文件列表。因为目前cmake 还不能自动发现新添加的源文件。

比如:

AUX_SOURCE_DIRECTORY(. SRC_LIST)
ADD_EXECUTABLE(main ${SRC_LIST})

也可以通过后面提到的FOREACH 指令来处理这个LIST

2.5、CMAKE_MINIMUM_REQUIRED

其语法为:

CMAKE_MINIMUM_REQUIRED(VERSION versionNumber [FATAL_ERROR])

比如:

CMAKE_MINIMUM_REQUIRED(VERSION 2.5 FATAL_ERROR)

如果cmake 版本小与2.5,则出现严重错误,整个过程中止。

2.6、EXEC_PROGRAM

在 CMakeLists.txt 处理过程中执行命令,并不会在生成的 Makefile 中执行。具体语法为:

EXEC_PROGRAM(Executable [directory in which to run]
[ARGS <arguments to executable>]
[OUTPUT_VARIABLE <var>]
[RETURN_VALUE <var>])

用于在指定的目录运行某个程序,通过 ARGS 添加参数,如果要获取输出和返回值,可通过 OUTPUT_VARIABLE 和RETURN_VALUE 分别定义两个变量。

这个指令可以帮助你在CMakeLists.txt 处理过程中支持任何命令,比如根据系统情况去修改代码文件等等。

举个简单的例子,我们要在src 目录执行 ls 命令,并把结果和返回值存下来。

可以直接在src/CMakeLists.txt 中添加:

EXEC_PROGRAM(ls ARGS "*.c" OUTPUT_VARIABLE LS_OUTPUT RETURN_VALUE LS_RVALUE)
IF(not LS_RVALUE)
 
MESSAGE(STATUS "ls result: " ${LS_OUTPUT})
 
ENDIF(not LS_RVALUE)

在 cmake 生成 Makefile 的过程中,就会执行ls 命令,如果返回0,则说明成功执行,那么就输出ls *.c 的结果。关于IF 语句,后面的控制指令会提到。

2.7、FILE 指令

文件操作指令,基本语法为:

FILE(WRITE filename "message to write"... )

FILE(APPEND filename "message to write"... )

FILE(READ filename variable)
 
FILE(GLOB variable [RELATIVE path] [globbing expressions]...)

FILE(GLOB_RECURSE variable [RELATIVE path] [globbing expressions]...)

FILE(REMOVE [directory]...)
 
FILE(REMOVE_RECURSE [directory]...)
 
FILE(MAKE_DIRECTORY [directory]...)
 
FILE(RELATIVE_PATH variable directory file)
 
FILE(TO_CMAKE_PATH path result)
 
FILE(TO_NATIVE_PATH path result)

这里的语法都比较简单,不在展开介绍了。

2.8、INCLUDE 指令

用来载入CMakeLists.txt 文件,也用于载入预定义的cmake 模块:

INCLUDE(file1 [OPTIONAL])
 
INCLUDE(module [OPTIONAL])

OPTIONAL 参数的作用是文件不存在也不会产生错误。

你可以指定载入一个文件,如果定义的是一个模块,那么将在 CMAKE_MODULE_PATH 中搜索这个模块并载入。

载入的内容将在处理到INCLUDE 语句是直接执行。

2.9、其他指令

ADD_EXECUTABLE、ADD_LIBRARY、ADD_SUBDIRECTORY 前面已经介绍过了,这里不再罗唆。

INSTALL 系列指令已经在前面的文章有非常详细的说明,这里不在赘述,可参考前面的文章。

三、FIND_系列指令

FIND_系列指令主要包含一下指令:

FIND_FILE(<VAR> name1 path1 path2 ...)

VAR 变量代表找到的文件全路径,包含文件名。

FIND_LIBRARY(<VAR> name1 path1 path2 ...)

VAR 变量表示找到的库全路径,包含库文件名。

FIND_PATH(<VAR> name1 path1 path2 ...)

VAR 变量代表包含这个文件的路径。

FIND_PROGRAM(<VAR> name1 path1 path2 ...)

VAR 变量代表包含这个程序的全路径。

FIND_PACKAGE(<name> [major.minor] [QUIET] [NO_MODULE] [[REQUIRED|COMPONENTS] [componets...]])

用来调用预定义在CMAKE_MODULE_PATH 下的Find< name >.cmake 模块,你也可以自己定义Find模块,通过SET(CMAKE_MODULE_PATH dir)将其放入工程的某个目录中供工程使用。

FIND_LIBRARY 示例:

FIND_LIBRARY(libX X11 /usr/lib)
IF(NOT libX)
MESSAGE(FATAL_ERROR “libX not found”)
ENDIF(NOT libX)

四、控制指令

4.1、IF 指令

基本语法为:

IF(expression)
#  THEN section. COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
...
ELSE(expression)
#  ELSE section. COMMAND1(ARGS ...) COMMAND2(ARGS ...)
...
ENDIF(expression)

另外一个指令是ELSEIF,总体把握一个原则,凡是出现IF 的地方一定要有对应的ENDIF,出现 ELSEIF 的地方,ENDIF 是可选的。

表达式的使用方法如下:

  • IF(var),如果变量不是:空,0,N, NO, OFF, FALSE, NOTFOUND 或 < var >_NOTFOUND 时,表达式为真。
  • IF(NOT var ),与上述条件相反。
  • IF(var1 AND var2),当两个变量都为真是为真。
  • IF(var1 OR var2),当两个变量其中一个为真时为真。
  • IF(COMMAND cmd),当给定的 cmd 确实是命令并可以调用是为真。
  • IF(EXISTS dir)或者IF(EXISTS file),当目录名或者文件名存在时为真。
  • IF(file1 IS_NEWER_THAN file2),当file1 比file2 新,或者file1/file2 其中有一个不存在时为真,文件名请使用完整路径。
  • IF(IS_DIRECTORY dirname),当 dirname 是目录时,为真。、
  • IF(variable MATCHES regex)。
  • IF(string MATCHES regex)。

当给定的变量或者字符串能够匹配正则表达式 regex 时为真。比如:

IF("hello" MATCHES "ell")
MESSAGE("true")
 
ENDIF("hello" MATCHES "ell")

IF(variable LESS number)
 
IF(string LESS number)
 
IF(variable GREATER number)
 
IF(string GREATER number)
 
IF(variable EQUAL number)
 
IF(string EQUAL number)

数字比较表达式:

IF(variable STRLESS string)
 
IF(string STRLESS string)
 
IF(variable STRGREATER string)
 
IF(string STRGREATER string)
 
IF(variable STREQUAL string)
 
IF(string STREQUAL string)

按照字母序的排列进行比较:

IF(DEFINED variable),如果变量被定义,为真。

一个小例子,用来判断平台差异:

IF(WIN32)
MESSAGE(STATUS “This is windows.”)
#作一些Windows 相关的操作
ELSE(WIN32)
MESSAGE(STATUS “This is not windows”)
#作一些非Windows 相关的操作
ENDIF(WIN32)

上述代码用来控制在不同的平台进行不同的控制,但是,阅读起来却并不是那么舒服,ELSE(WIN32)之类的语句很容易引起歧义。

这就用到了我们在“常用变量”一节提到的 CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS 开关。

可以SET(CMAKE_ALLOW_LOOSE_LOOP_CONSTRUCTS ON)

这时候就可以写成:

IF(WIN32)
ELSE()
ENDIF()

如果配合ELSEIF 使用,可能的写法是这样:

IF(WIN32)
#do something related to WIN32
ELSEIF(UNIX)
#do something related to UNIX
ELSEIF(APPLE)
#do something related to APPLE
ENDIF(WIN32)

4.2、WHILE

WHILE 指令的语法是:

WHILE(condition)
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
...
ENDWHILE(condition)

其真假判断条件可以参考IF 指令。

4.3、FOREACH

FOREACH 指令的使用方法有三种形式:

(1)列表:

FOREACH(loop_var arg1 arg2 ...)
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
...
ENDFOREACH(loop_var)

像我们前面使用的AUX_SOURCE_DIRECTORY 的例子:

AUX_SOURCE_DIRECTORY(. SRC_LIST) FOREACH(F ${SRC_LIST})
MESSAGE(${F})
ENDFOREACH(F)

(2)范围:

FOREACH(loop_var RANGE total)
ENDFOREACH(loop_var)

从 0 到 total 以1为步进。

举例如下:

FOREACH(VAR RANGE 10)
MESSAGE(${VAR})
ENDFOREACH(VAR)

最终得到的输出是:

0
1
2
3
4
5
6
7
8
9
10

(3)范围和步进:

FOREACH(loop_var RANGE start stop [step])
ENDFOREACH(loop_var)

从 start 开始到stop 结束,以step 为步进。

举例如下:

FOREACH(A RANGE 5 15 3)
MESSAGE(${A})
ENDFOREACH(A)

最终得到的结果是:

5
8
11 
14

这个指令需要注意的是,知道遇到ENDFOREACH 指令,整个语句块才会得到真正的执行。

总结

  1. 基本涵盖了常用的cmake 指令,包括基本指令、查找指令、安装指令以及控制语句等,特别需要注意的是,在控制语句条件中使用变量,不能用${}引用,而是直接应用变量名。
  2. 掌握了以上的各种控制指令,应该完全可以通过 cmake 管理复杂的程序了。

在这里插入图片描述

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

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

相关文章

云计算 概念与技术

如果我倡导的计算机在未来得到使用&#xff0c;那么有一天&#xff0c;计算也可能像电话一样成为共用设施。计算机应用将成为一全新的、重要的产业的基础。 ——John McCarthy 云计算的概念 定义 Garther公司的定义 一种计算方式&#xff0c;能通过Internet技术将可扩展的和…

内核模块调试常用命令整理

一、 模块加载 1.1 最简单的一个驱动 static int __init my_driver_init( void ) {printk("init my_driver\n");return 0; }static void __exit my_driver_exit( void ) {printk("exit my_driver\n"); }module_init( my_driver_init ); module_exit( my_…

Xamarin.Forsm for Android 显示 PDF

背景 某些情况下&#xff0c;需要让用户阅读下发的文件&#xff0c;特别是红头文件&#xff0c;这些文件一般都是使用PDF格式下发&#xff0c;这种文件有很重要的一点就是不能更改。这时候就需要使用原文件进行展示。 Xamarin.Forms Android 中的 WebView 控件是不能直接显示的…

R统计绘图-NMDS、环境因子拟合(线性和非线性)、多元统计(adonis2和ANOSIM)及绘图(双因素自定义图例)

这个推文也在电脑里待了快一年了&#xff0c;拖延症患者&#xff0c;今天终于把它发出来了。NMDS分析过程已经R统计-PCA/PCoA/db-RDA/NMDS/CA/CCA/DCA等排序分析教程中写过了。最近又重新看了《Numerical Ecology with R》一书,巩固一下知识&#xff0c;正好重新整理了一下发出…

火山引擎推出一站式小程序监控方案

背景 小程序作为轻量级的应用发展迅速&#xff0c;国内已有多家小程序厂商相继推出。为了洞察用户真实体验及程序自身运行状况&#xff0c;监控已成为开发套件中必不可少的一环。随着业务愈来愈复杂&#xff0c;各厂商小程序管理后台免费提供的监控能力逐渐满足不了大部分业务…

软考中级之数据库系统(重点)

涉及考点:数据库模式,ER模型,关系代数与元祖演算,规范化理论,并发控制,分布式数据库系统,数据仓库和数据挖掘 数据库模式 三级模式-二级映射 常考选择题 三级模式,两种映射的这种涉及属于层次架构体的设计,这种设计为我们在应用数据库的时候提供了很多便利,同时提高了整个体…

功能性材料深入超级赛道,赋能多行业迭代升级

中国国际胶粘剂及密封剂展览会深耕胶粘剂、密封剂和胶粘带行业26年&#xff0c;是行业认可的、优质的贸易与技术交流平台。展会连接了十几个行业的买家和卖家&#xff0c;包括汽车、电子、新能源、轨道交通、工业等重要领域&#xff0c;为客户提供封装、粘合、散热、装配制造等…

拿下宁王、迪王的湖南裕能,还能“狂飙”多远?

文|智能相对论作者|Kinki近日&#xff0c;磷酸铁锂正极材料龙头湖南裕能正式登陆A股&#xff0c;上市当天市值超过了400亿元&#xff0c;投资者中一签可赚1.49万元&#xff0c;可谓近年低迷的资本市场中一支“大肉签”。不过在 “开门红”之后&#xff0c;湖南裕能的股价便一路…

leetcode16. 最接近的三数之和

给你一个长度为 n 的整数数组 nums 和 一个目标值 target。请你从 nums 中选出三个整数&#xff0c;使它们的和与 target 最接近。 返回这三个数的和。 假定每组输入只存在恰好一个解。 示例 1&#xff1a; 输入&#xff1a;nums [-1,2,1,-4], target 1 输出&#xff1a;2 …

linux服务器上Docker中安装jenkins

前言 Jenkins是开源CI&CD软件领导者&#xff0c; 提供超过1000个插件来支持构建、部署、自动化&#xff0c; 满足任何项目的需要。 本文主要提供通过docker安装jenkins镜像&#xff0c;并配置nginx反向代理页面配置和使用。通过jenkins完成项目的自动部署。 我在安装之前…

ThinkPHP ^6图片操作进阶

图片裁剪、缩略、水印不再是TP框架系统内置的功能&#xff0c;需要安装。 目录 安装 图片处理 1.创建图片对象 2.获取图片属性 3.裁剪图像 4.生成缩略图 6.保存图像 7.水印 安装 使用composer在项目根目录打开命令行执行&#xff1a; composer require topthink/think…

Simulink 电机控制:单电阻三相电流重构算法仿真总结

目录 理论基础 仿真实现 硬件实现 总结 理论基础 参考Microchip AN1299 《PMSM 无传感器 FOC的单分流三相电流重构算法》&#xff0c;详细的理论可以参考这个文档&#xff0c;这里只简单总结一下。单电阻采样的核心就是要在一个周期内实现两相电流的采样并通过基尔霍夫定…

【UE4 制作自己的载具】3-载具蓝图实现(基本)

效果步骤新建一个蓝图&#xff0c;继承“WheeledVehicle&#xff08;轮式载具&#xff09;”命名为“Vehicle_BP”&#xff0c;双击打开该蓝图选中“Mesh&#xff08;继承&#xff09;”&#xff0c;然后在细节中&#xff0c;骨架网格体选择“Vehicle”添加一个弹簧臂和摄像机组…

Windows下mysql8.0.32安装配置方法图文教程

Windows下mysql8.0.31安装配置方法图文教程 1、下载可以到官网的地址下载即可 https://dev.mysql.com/downloads/file/?id516465 2、解压缩并重命名mysql-8.0.32-winx64为mysql 3、创建my.ini配置文件&#xff0c;创建data文件夹。 4、打开记事本另存为my.ini并且使用ANSI编…

23年了,GOPATH和go.mod 还在冲突!

现在 新配了 go环境 设置了GOROOT&#xff0c;GOPATH &#xff0c;发现引用别的包会出问题。一直会报 package XX not in GOROOT &#xff08;xxxx&#xff09;我的目录&#xff1a;我的开发目录&#xff1a; /home/fate/go_projects/老样子&#xff0c;下面有 /home/fate/go_…

元宇宙与ChatGPT结合 一场颠覆式场景革命或将到来?

元宇宙和ChatGPT都是当前数字化领域中非常热门的技术和应用&#xff0c;两者之间也存在一定的关系&#xff0c;结合起来&#xff0c;可以为企业提供更加智能化、个性化的服务和支持&#xff0c;同时也可以拓展企业的市场和品牌影响力&#xff0c;提高企业的效率和创新能力。 元…

公司新来一00后说我不会自动化测试,3个问题直接给他问趴下...

今天我们公司刚入职一小伙&#xff0c;听说是00后&#xff0c;今天在办公室交流了一下&#xff0c;他问我会不会自动化测试&#xff0c;我直呼好家伙&#xff0c;直接问了他3个开展自动化测试问题....一问3不知.....还有待加强呀我们在制定自动化测试实施策略时&#xff0c;首先…

java servlet详解

一、Servlet实现方式 1、实现Servlet接口&#xff0c;接口中的方法必须全部实现。此种方式支持最大程度的自定义。 2、继承GenericServlet&#xff0c;service方法必须重写&#xff0c;其他方可根据需求&#xff0c;选择性重写。 使用此种方式&#xff0c;表示只在接收和响应…

作为通信人,你知道国内有哪些通信领域的博物馆吗?

众所周知&#xff0c;博物馆是收藏、展示和研究历史文物的地方。参观博物馆&#xff0c;既可以回顾历史往事&#xff0c;也可以学习知识。 那么&#xff0c;作为通信人&#xff0c;你知道国内有哪些通信领域的博物馆吗&#xff1f; 今天&#xff0c;就让小编给大家介绍介绍。█…

微鳄365,可私有化部署的企业管理软件,让数据更安全让管理更方便

编者按&#xff1a;本文分析了企业数字化转型中常遇到的一些困难&#xff0c;并进一步指出微鳄365一体化解决方案&#xff0c;可以帮助企业克服这些困难。关键词&#xff1a;免安装&#xff0c;免维护&#xff0c;成本低&#xff0c;数据安全&#xff0c;共享协作&#xff0c;个…