当前位置:网站首页 > 云服务教程 > 正文

cmake 教程(cmake教程pdf下载)



前言:

学习笔记,随时更新。如有谬误,欢迎指正。


说明:

  1. 红色字体为较为重要部分。
  2. 绿色字体为个人理解部分。

本章将涵盖为你的软件编写有效的 CMakeLists 文件的基础内容。它将包含你在大部分工程中都需要处理的基础命令和问题。由于 CMake 能处理极其复杂的项目,因此对大部分工程来说,你会发现本章内容将告诉你所有你想要知道的。 CMake 被为一个软件项目所写的 CMakeLists 文件所驱动。 CMakeLists 文件决定了从向用户提供哪些选项到编译哪些源文件的所有事情。本章除了讨论如何写一个 CMakeLists 文件之外,还包含了如何使它们变得健壮且可维护。

CMakefiles 文件可以被几乎任何一个文本编辑器编辑。一些编辑器,如 Notepad++ ,内置支持 CMake 语法高亮和缩进。 Emacs 或者 Vim 等编辑器中, CMake 包含了缩进和语法高亮模式。这些可以在源分布的 Auxiliary 目录中找到,或者从 CMake 的下载页下载(在下载页面中的 Editor Syntax Files 部分去下载 CMake 语法支持扩展)。

在所有 CMake 支持的生成器( Makefiles 、 Visual Studio 等)中,如果你编辑了 CMakeLists 文件并且重新构建了,有一些规则会自动调用 CMake 来更新生成的文件(如 Makefiles 或者工程文件)。这会确保你的生成文件总是与你的 CMakeLists 文件保持同步

CMake 语法由注释命令变量所组成。

注释由#字符开始直到该行的最后一个字符。更多细节见 cmake-language 手册。

CMakeLists 文件使用变量的方式非常像编程语言。变量被用来存储值以便以后使用。 CMake 变量名区分大小写,只能包含字母、数字和下划线

许多非常有用的变量是由 CMake 自动定义的,并在 cmake-variables 手册中进行了介绍。这些变量以 CMAKE_ 开头。对于特定于项目的变量,避免使用这种命名约定(理想情况下,建立自己的命名约定)

尽管 CMake 变量在使用时可能被解释为其他类型,但都字符串的形式存储在内部。

使用 set 命令设置变量值。在最简单的形式中, set 的第一个参数是变量的名称,其余参数是值。多个值参数被打包成一个以分号分隔的列表,并作为字符串存储在变量中。例如:

 

变量可以在命令参数中使用语法 ${VAR} 引用,其中 VAR 是变量名。如果未定义命名变量,则引用将被替换为空字符串;否则,它将被变量的值所替换。替换操作在展开未加引号的参数之前执行,因此包含分号的变量值将被分割为零个或多个参数,以代替原始的未加引号的参数。例如:

 

系统环境变量和 Windows 注册表的值可以在 CMake 中直接访问。可以使用 $ENV{VAR} 语法来访问环境变量。在 CMake 的许多命令中,都可以使用 [HKEY_CURRENT_USERSoftwarepath1path2;key] 形式的语法来访问注册表项,路径由注册表树和关键字组成。

3.4.1 变量的范围

在 CMake 中,变量的(作用)范围与大部分语言有一点点不同。当你设置了一个变量,它对当前的 CMakeLists 文件或者函数时可见的,也对任何的子目录的 CMakeLists 文件、任何被调用的函数或者宏、任何被使用 include 命令包含进来的文件都可见(也就是说,从定义变量开始往下直到本 CMakeLists 文件结束,在这当中所有的地方,包括在此期间被引入的文件里,都可以使用该变量,该变量都是有效的)。当处理新的子目录(或者函数调用)时,一个新的变量(作用)范围被创建出来,并且这些变量被调用(方)范围内的相应变量的当前值所初始化。任何的在子(作用)范围被新创建出来的变量、或者对已存在变量做的修改,将不会影响父作用范围的变量。请看以下例子:

 

在某些情况下,你可能想一个函数或者子目录来设置父(作用)范围内的变量。这是 CMake 从一个函数返回一个值的方式之一,这可以通过使用 set 命令的 PARENT_SCOPE 选项来实现。我们可以如下修改先前的例子,让函数 foo 改变其父(作用)范围内的 test (变量)的值:

 

CMake 中的变量是按照 set 命令的执行顺序定义的。请看下面的例子:

 

为理解变量的(作用)范围,请看下面的例子:

 

在这个例子中,由于变量 foo 在最开始被定义,它将会在处理 dir1 和 dir2 时都被定义(有效)。相比较而言, bar 将仅仅在处理 dir2 时才被定义(有效)。同理, foo 将在处理 file1.cmake 和 file2.cmake 时都被定义(有效),而 bar 将仅仅在处理 file2.cmake 时才被定义(有效)。

一个命令由命令名称、开始括号、空格分隔的参数和结束括号组成。每个命令都按照它在 CMakeLists 文件中出现的顺序进行计算。有关 CMake 命令的完整列表,请参阅 cmake-commands 手册。

CMake 对命令名不再区分大小写( CMake 2.2 版本之前接受大写的命令),所以当你看到 command 时,你可以使用 COMMAND 或 Command 来代替。使用小写命令被认为是最佳实践
除了用于分隔参数之外,所有的空白(空格、换行、制表符)会被忽略。因此,只要命令名和左括号在同一行,命令就可以跨多行

CMake 命令参数是空格分隔的,区分大小写。命令参数可以加引号,也可以不加引号。带引号的参数以双引号开始和结束,并且总是只表示一个参数。值中包含的任何双引号都必须用反斜杠转义。考虑对需要转义的参数使用括号,详情请参阅 cmake-language 手册。未加引号的参数以双引号以外的任意字符开始,并通过在值中以分号分隔自动展开为零个或多个参数。例如:

 

3.5.1 基础命令

正如我们前面看到的, set 和 unset 命令显式地设置或取消设置变量。 string 、 list 和 separate_arguments 命令提供了对字符串和列表的基本操作。

add_executable 和 add_library 命令是用来定义构建什么库和可执行文件以及它们由什么源文件所组成的主要命令。 Visual Studio 项目正常情况下源文件将会展示在 IDE 中,但是项目所使用到的任何头文件将不会在这(展示)。为了让头文件也展示出来,你简单地在可执行文件或者库中的源文件列表中添加他们。对于所有生成器都可以这样做。任何不直接使用头文件的的生成器(如基于 Makefile 的生成器)将会简单地忽略它们(即不会默认将头文件展示在里面)。

CMake 语言提供了三种流控制结构来帮助组织 CMakeLists 文件并保持它们的可维护性。

  • 条件语句(如 if )
  • 循环结构(如 foreach 和 while )
  • 程序定义(如 macro 和 function )

3.6.1 条件语句

首先我们来看 if 命令。 CMake 中的 if 命令在很多方面很像其他任何语言中的 if 命令。它计算它的表达并以此为依据(来决定)是执行它的主体中的还是 else 分句中的代码。例如:

 

CMake 还支持 elseif 来帮助顺序测试多个条件。例如:

 

if 的命令文档记录了它可以测试的许多条件。

3.6.2 循环结构

foreach 和 while 命令允许你处理按顺序发生的重复任务。 break 命令在 foreach 和 while 循环通常结束之前将其中断。

foreach 命令让你在一个列表中对其成员重复地执行一组 CMake 命令。请看下面改编自 VTK 的例子:

 

foreach 命令的第一个参数是在每一次迭代循环中会承接不同的值的变量的名称。剩下的参数是要被遍历的列表中的值。在这个例子中, foreach 循环的主体仅仅是一个 CMake 的 add_test 命令。在 foreach 的主体中,每一次循环的变量(例子中是 tfile )在被引用的时候,它将会被替换为列表中的当前值。在第一次迭代中, ${tfile} 的出现将会被替换为 TestAnsiotropicDiffusion2D 。下一次迭代中, ${tfile} 的出现将会被替换为 TestButterworthLowPass 。 foreach 循环将会一直循环到所有参数都被处理过为止。

值得一提的是 foreach 循环可以被嵌套,并且循环变量会先于任何其他变量而被展开。这意味着在 foreach 循环主主体中你可以使用循环变量来构建其他变量。在下面的代码中,循环变量 tfile 被展开然后与 _TEST_RESULT 相连接。然后新变量名称被展开并且测试是否与 FAILED 相匹配。

 

while 命令提供了一个基于一个测试条件的循环。 while 命令中的测试表达式的格式与先前介绍的 if 命令相同。请看下面的被 CTest 所使用的例子。请注意, CTest 在内部会更新 CTEST_ELAPSED_TIME 的值。

 

3.6.3 程序定义

marco 和 function 命令支持可能分散在 CMakeLists 文件中的重复的任务。一旦一个宏或者函数被定义了,在它被定义之后,所有的 CMakeLists 的处理都可以使用它

CMake 中的函数非常像 C 或者 C++ 中的函数。你可以对它传参,并且传入的参数变成了函数内的变量。同样地,一些标准参数如 ARGC 、 ARGV 、 ARGN 和 ARG0 、 ARG1 等被定义出来。函数调用具有动态作用域。在函数里,你是在一个新的变量(作用)范围中,这非常像当你使用 add_subdirectory 命令进入一个子目录,也就进了一个新的变量(作用)范围。在函数被调用时已被定义的变量仍然会被定义,但是任何对变量的修改以及新的变量将只会存在于这个函数中。当函数返回,这些变量也将消失。更简单的来说,当你调用一个函数时,一个新的变量(作用)范围被推入,当函数返回时那个变量(作用)范围被弹出。

function 命令用来定义一个新函数。( function 命令的)第一个参数定义了函数名。所有其他的参数都是函数的形式参数(形参)

 

请注意,在例子中, _time 被用来传递返回变量的名称。 set 命令被调用时使用的是 _time 的值,在这个例子中是 current_time 。最后, set 命令使用 PARENT_SCOPE 选项来在父范围而不是当前范围中设置变量的值。

宏的定义和调用的方式与函数类似。主要的区别是宏不会推入和弹出一个新的变量(作用)范围,在执行之前,宏的参数不会被当作变量,而是被当作字符串替代。这就非常像 C 和 C++ 中的宏和函数中的区别。第一个参数是宏的名称。所有额外(除第一个之外)的参数都是宏的形参。

 

上面的简单例子中创建了一个名为 assert 的宏。这个宏被定义为接受两个参数。第一个参数是测试的结果,第二个参数是如果测试失败打印的注释。宏的主体是一个其中有一个 message 命令的 if 命令。遇到 endmacro 命令时宏的主体就结束了。宏可以像函数一样简单地使用它的名字来调用。在上面的例子中,如果 FOO_LIB 没找到,一个信息将会被打印出来来说明错误条件。

macro 命令也支持定义有参数列表的宏。如果你想定义一个有可选参数或者多个签名的宏,这就非常有用的。变量参数可以使用 ARGC 、 ARGV0 、 ARGV1 等等来代替使用形式参数。 ARGV0 代表宏的第一个参数, ARGV1 代表下一个,以此类推。你也可以混合使用形式参数和变量参数,如下例所示。

 

在这个例子中,两个必要参数是 TEST 和 COMMENT 。这些必要参数可以像例子中那样使用通过名称类引用,它们也可以使用 ARGV0 和 ARGV1 来引用。 ARGV (相对于 ARGV0 、 ARGV1 等等)是宏的参数列表, ARGN 是形式参数之后的参数列表。在宏中你可以根据需要通过 foreach 命令来迭代 ARGV 或者 ARGN 。

return 命令从函数、目录或文件返回。请注意,宏与函数不同,它是就地展开的,因此不能处理 return

一些 CMake 命令,如 if 和 string ,(支持)使用正则表达式,或者可以使用正则表达式作为参数。简单来说,正则表达式是一列字符串,它用于搜索精确的字符匹配。然而很多时候这些需要被发现的确切序列尚不清楚,或者只需要匹配字符串的开头或者结尾。指定正则表达式(的格式)有几种不同的协议, CMake 的标准在 string 命令文档中有描述。描述是依据德州仪器公司开源的正则表达式类, CMake 使用它来解析正则表达式。

有一些命令可能非常有用,但不经常用于编写 CMakeLists 文件。本节将讨论其中的一些命令以及它们何时有用。

首先,来看 add_dependencies 命令,它在两个目标之间创建依赖(关系)。当 CMake 能够确定目标时,它会自动创建目标之间的依赖(关系)。例如, CMake 会自动为可执行目标创建依赖于库目标的依赖(关系)。 add_dependencies 命令通常用于指定目标之间的目标间依赖关系,其中至少有一个目标是自定义目标(见自定义命令节)。

include_regular_expression 命令也与依赖性有关。此命令控制用于跟踪源代码依赖项的正则表达式。默认情况下, CMake 将跟踪源文件的所有依赖项,包括 stdio.h 等系统文件。如果使用 include_regular_expression 命令指定正则表达式,则该正则表达式将用于限制处理哪些包含文件。例如,如果你的软件项目的包含文件都以 foo 开头(例如 foomain.c 、 fooStruct.h 等),你可以指定一个 ^foo.*$ 的正则表达式将依赖项检查限制为仅对项目的文件。

到此这篇cmake 教程(cmake教程pdf下载)的文章就介绍到这了,更多相关内容请继续浏览下面的相关推荐文章,希望大家都能在编程的领域有一番成就!

版权声明


相关文章:

  • 电脑剪辑视频网站(剪辑视频的教程视频电脑)2025-04-15 15:27:06
  • 爱普生c7000打印机使用教程视频(爱普生v700使用教程)2025-04-15 15:27:06
  • ad10安装及破解教程(ad20安装及破解教程)2025-04-15 15:27:06
  • b站怎么弄视频链接(b站怎么弄视频链接教程)2025-04-15 15:27:06
  • 操作系统教程电子版(操作系统教程电子版pdf)2025-04-15 15:27:06
  • 操作系统教程第一版(操作系统教程第二版)2025-04-15 15:27:06
  • 启动盘u盘制作教程视频(u盘启动盘制作教程制作u盘启动盘)2025-04-15 15:27:06
  • awvs安装教程(awvs14安装教程)2025-04-15 15:27:06
  • 个人服务器怎么搭建网站(个人服务器搭建教程)2025-04-15 15:27:06
  • 如何安装虚拟机win11(如何安装虚拟机教程)2025-04-15 15:27:06
  • 全屏图片