CMake(二):一个最小的项目

所有的CMake项目都以一个名为CMakeLists.txt的文件开始,它被放置在源代码树的顶部。可以把它想象成CMake项目文件,它定义了所有关于构建的内容,从源代码和目标,到测试、打包和其他定制任务。它可以简单到只有几行代码,也可以非常复杂,从其他目录中插入更多的文件。CMakeLists.txt只是一个普通的文本文件,通常是直接编辑的,就像项目中的其他源文件一样。

​继续与源代码的类比,CMake定义了自己的语言,它有许多程序员熟悉的东西,如变量、函数、宏、条件逻辑、循环、代码注释等等。下面是一个简单的、格式良好的CMakeLists.txt文件,它生成了一个基本的可执行文件。

cmake_minimum_required(VERSION 3.2)
project(MyApp)
add_executable(myExe main.cpp)

​上面例子中的每一行都执行一个内置的CMake命令。在CMake中,命令类似于其他语言的函数调用,除了它们支持参数之外,它们不直接返回值(但是后面的章节展示了如何以其他方式将值传递回调用者)。参数之间用空格分隔,可以跨行分割:

add_executable(myExe
  main.cpp
  src1.cpp
  src2.cpp
)

​命令名也不区分大小写,所以下面的命令都是等价的:

add_executable(myExe main.cpp)
ADD_EXECUTABLE(myExe main.cpp)
Add_Executable(myExe main.cpp)

​典型的风格各不相同,但现在更常见的约定是命令名都使用小写(这也是CMake文档中内置命令遵循的约定)。

2.1 管理CMake版本

​CMake不断更新和扩展,以添加对新工具、平台和特性的支持。CMake背后的开发人员非常小心地维护与每个新版本的向后兼容性,所以当用户更新到一个新的CMake版本时,项目应该继续像以前那样构建。有时,特定的CMake行为需要更改,或者在新版本中可能引入更严格的检查和警告。而不是要求所有的项目立即处理这个问题,CMake提供了策略机制,允许项目说“像CMake版本X.Y.Z一样行事”。这允许CMake内部修复bug并引入新特性,但仍然保持任何特定过去版本的预期行为。

​项目指定预期CMake版本行为的主要方式是使用cmake_minimum_required()命令。这应该是cmakellists .txt文件的第一行,以便在做其他事情之前检查和建立项目的需求。这个命令做了两件事:

  • 它指定了项目所需的CMake的最小版本。如果CMakeLists.txt文件被处理时使用的CMake版本比指定的版本更旧,它将立即停止并出现错误。这确保了在继续之前有一个特定的最小的CMake功能集可用。
  • 它强制策略设置匹配指定版本的CMake行为。

​使用这个命令非常重要,如果CMakeLists.txt文件没有在任何其他命令之前调用cmake_minimum_required(), CMake将会发出警告。它需要知道如何为所有后续处理设置策略行为。对于大多数项目来说,把cmake_minimum_required()当作简单地指定所需的最低CMake版本就足够了,正如它的名字所暗示的那样。它还意味着CMake的行为应该与那个特定版本相同,这一事实可以被认为是一个有用的附带好处。

​cmake_minimum_required()命令的典型形式很简单:

cmake_minimum_required(VERSION major.minor[.patch[.tweak]])

​VERSION关键字必须始终存在,提供的版本详细信息必须至少有major.minor的部分。在大多数项目中,没有必要指定补丁和调整部分,因为新特性通常只出现在较小的版本更新中(这是从3.0版本开始的官方CMake行为)。只有在需要修复特定的bug时,项目才需要指定补丁部分。此外,由于在已经发布的3.x系列已经使用了一个微调编号,项目也不需要指定一个。

​开发人员应该仔细考虑他们的项目需要的最小CMake版本。3.2版本可能是任何新项目都应该考虑的最古老的版本,因为它为现代CMake技术提供了一个相当完整的特性集。版本2.8.12的特性覆盖率较低,缺少一些有用的特性,但它对于较老的项目可能是可行的。之前的版本缺乏实质性的特性,使得使用许多现代CMake技术是不可能的。如果在iOS等快速移动的平台上工作,为了支持最新的操作系统版本,可能需要相当新版本的CMake。

​一般的经验法则是,选择不会给那些构建项目的人带来重大问题的最新的CMake版本。最大的困难通常是那些需要支持旧平台的项目,其中系统提供的CMake版本可能非常旧。对于这种情况,如果可能的话,开发人员应该考虑安装一个最新的版本,而不是局限于非常旧的CMake版本。另一方面,如果项目本身依赖于其他项目,那么选择一个较新的CMake版本可能会成为采用的障碍。在这种情况下,最好是要求最老的CMake版本提供所需的最小CMake特性,但如果可用的话,可以使用最新的CMake版本的特性。这将防止其他项目被迫需要比其目标环境通常允许或提供的新版本。相关的项目总是需要一个更新的版本,如果他们愿意的话,但是他们不能需要一个旧的版本。使用最老的可行版本的主要缺点是,它可能会导致更多的弃用警告,因为较新的CMake版本会警告旧的行为,以鼓励项目更新cmake。

2.2project()命令

​每个CMake项目都应该包含一个project()命令,它应该在调用cmake_minimum_required()之后出现。该命令最常用的选项有以下形式:

project(projectName
  [VERSION major[.minor[.patch[.tweak]]]]
  [LANGUAGES languageName ...]
)

​projectName是必需的,它可能只包含字母、数字、下划线(_)和中划线(-),尽管在实践中通常只使用字母和下划线。因为不允许使用空格,所以项目名称不必用引号括起来。这个名字用于项目的顶层一些项目gernertor(如Xcode和Visual Studio),它也被运用于各种项目的其他部分,比如打包默认参数和文档元数据,提供具体项目变量等等。project是project()命令的唯一强制参数。

​可选的VERSION细节仅在CMake 3.0及以后版本中支持。像projectName一样,版本细节被CMake用来填充一些变量,并作为默认的包元数据,但除此之外,版本细节没有任何其他意义。尽管如此,一个好的习惯是在这里定义项目的版本,以便项目的其他部分可以引用它。

​可选的LANGUAGES参数定义了应该为项目启用的编程语言。支持的值包括C、CXX、Fortran、ASM、Java等。如果指定了多种语言,请用空格分隔。在某些特殊情况下,项目可能希望指示没有使用任何语言,这可以使用languages NONE来完成。如果没有语言选项,CMake将默认为C和CXX。3.0之前的CMake版本不支持LANGUAGES关键字,但是LANGUAGES仍然可以用旧的命令形式在项目名后面指定,像这样:

project(myProj C CXX)

​新项目被鼓励指定至少3.0的CMake版本,并使用新的forms和LANGUAGES关键字代替。

​project()命令不仅仅是填充几个变量。它的重要职责之一是检查每种启用的语言的编译器,并确保它们能够成功编译和链接。编译器和链接器设置的问题会很早就被发现。一旦这些检查通过,CMake就会设置一些变量和属性来控制所启用语言的构建。如果CMakeLists.txt文件没有调用project()或者调用的时间不够早,CMake会在内部隐式地为默认语言C和CXX调用它,以确保编译器和链接器为其他依赖于它们的命令正确设置。

​当CMake执行的编译器和链接器检查成功时,它们的结果被缓存,这样它们就不必在以后的CMake运行中重复了。这些缓存的详细信息存储在CMakeCache.txt文件的构建目录中。关于检查的其他细节可以在构建区域的子目录中找到,但是开发人员通常只需要在使用新的或不常见的编译器时或在设置交叉编译的工具链文件时查看那里。

2.3 构建一个基本的可执行文件

​为了完成我们的最小示例,add_executable()命令告诉CMake从一组源文件创建一个可执行文件。该命令的基本形式为:

add_executable(targetName source1 [source2 ...])

​这将创建一个可执行文件,它可以在CMake项目中被称为targetName。该名称可以包含字母、数字、“_”和“-”。在构建项目时,将在构建目录中创建一个具有平台相关名称的可执行文件,默认名称基于目标名称。考虑下面这个简单的示例命令:

add_executable(myApp main.cpp)

​ 默认情况下,可执行文件的名称在Windows上是myApp.exe,在基于unix的平台(如macOS、Linux等)上是myApp。可执行文件名可以用目标属性来定制。通过使用不同的目标名称多次调用add_executable(),可以在一个CMakeLists.txt文件中定义多个可执行文件。如果同一个目标名称在多个add_executable()命令中使用,CMake将失败并突出显示错误。

2.4 注解

​注释在本书中被广泛使用,并且鼓励开发人员也养成注释他们的项目的习惯,就像他们注释普通的源代码一样。CMake遵循与Unix shell脚本类似的注释约定。任何以#字符开头的行都被视为注释。除了在带引号的字符串中,在CMakeLists.txt文件中,任何行中#之后的内容都被视为注释。下面展示了一些注释示例,将本章介绍的概念结合在一起:

cmake_minimum_required(VERSION 3.2)
# We don't use the C++ compiler, so don't let project()
# test for it in case the platform doesn't have one
project(MyApp VERSION 4.7.2 LANGUAGES C)
# Primary tool for this project
add_executable(mainTool
  main.c
  debug.c # Optimized away for release builds
)
# Helpful diagnostic tool for development and testing
add_executable(testTool testTool.c)

更多请关注微信公众号【Hope Hut】:
在这里插入图片描述

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值