<<Modern CMake>> 翻译 2. CMake 基础
<<Modern CMake>> 翻译 2. CMake 基础
最低版本
这是每个 CMakeLists.txt 文件的第一行。CMakeLists.txt 是 CMake 所需的配置文件名称:
cmake_minimum_required(VERSION 3.1)
我们来了解一点 CMake 语法。 命令名称 cmake_minimum_required 不区分大小写,因此通常的做法是使用小写。1 这里 VERSION 是该命令所需的特殊关键字。 版本号紧跟在 VERSION 关键字之后。 与本书中的任何其他地方一样,你只需单击命令名称即可链接到官方文档,然后可以使用下拉列表切换不同版本的 CMake 文档。
这一行很特别!2 版本号也同时指明了 CMake 的行为变化。 因此,如果你设置 minimum_required 为 VERSION 2.8,在macOS上你就会获得错误的链接行为, 例如,在最新的 CMake 版本中也是如此。 如果你把版本设置为 3.3 或更低,你会得到错误的符号隐藏行为,等等。 在 policies 有一个策略和版本列表。
在 CMake 3.12 中,可以这样写来指定支持的 CMake 版本范围,例如 VERSION 3.1...3.12; 这意味着您最低支持 3.1,同时也测试过并支持到 3.12 的新策略。 这对于需要更好设置的用户来说很不错,并且由于语法上的技巧,它向后兼容旧版本的 CMake(尽管实际运行 CMake 3.2-3.11 只会在此示例中设置 3.1 版本的策略)。 新版本的策略对于 macOS 和 Windows 用户来说往往是最重要的,他们通常也有最新版本的 CMake。
新项目应该这样写:
cmake_minimum_required(VERSION 3.1...3.15)
if(${CMAKE_VERSION} VERSION_LESS 3.12)
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
endif()
如果 CMake 版本小于 3.12,则 if 块将为 true,并且策略将设置为当前 CMake 版本。 如果 CMake 为 3.12 或更高,if 块将为 false,此时新语法 cmake_minimum_required 将起作用,这将能够正常工作!
警告:MSVC 的 CMake 服务器模式最初在读取此格式时有一个 bug, 因此如果您需要支持旧版 MSVC 的非命令行 Windows 版本,则需要执行以下操作:
cmake_minimum_required(VERSION 3.1)
if(${CMAKE_VERSION} VERSION_LESS 3.15)
cmake_policy(VERSION ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION})
else()
cmake_policy(VERSION 3.15)
endif()
如果您确实需要在此处设置较低的版本,则可以使用 cmake_policy 有条件地增加策略级别或设置特定策略。 请至少为您的 macOS 用户执行此操作!
设置项目
现在,每个顶级 CMake 文件(CMakeLists.txt)都有下面这一行:
project(MyProject VERSION 1.0
DESCRIPTION "非常出色的项目"
LANGUAGES CXX)
现在我们看到了更多的新语法。 字符串被引号包围起来,空格可多可少,项目名称是第一个参数(位置参数)。 这里的所有的关键字参数都是可选的。 通过 VERSION 参数,这会设置了一堆变量,比如 MyProject_VERSION 和 PROJECT_VERSION。 LANGUAGE 可以是 C,CXX,Fortran 和 CUDA(CMake 3.7+)。 C CXX 是默认值。 在 CMake 3.9 中,DESCRIPTION 添加进来设置对项目的描述。 你可以参考 project 这个文档。
你可以通过使用 # 开头来添加 注释。 CMake 也有注释的内联语法,但很少需要,因为空格并不重要。
项目名称没什么特别之处。此时不添加任何目标。
生成可执行文件
虽然链接库更有趣,通常我们大部分时间都在生成链接库,但这里我们要从一个简单的可执行文件开始。
add_executable(one two.cpp three.h)
这里有几件要说明的事情。 one 是生成的可执行文件的名称,同时也是创建的 CMake 目标的名称(我保证你会很快听到很多关于目标的信息)。 可执行文件名称后紧接的是源文件列表,您可以根据需要列出任意数量的源文件列表。 CMake 很聪明,会根据文件扩展名正确识别源文件,所以列表中的头文件会被 CMake 理解并忽略。 大多数时候,我们在源文件列表中列出头文件的唯一原因是让它们出现在 IDE 中。 有关通用构建系统和目标的更多信息,请参见 buildsystem。
生成链接库
使用 add_library 生成链接库, 也是非常简单:
add_library(one STATIC two.cpp three.h)
您可以选择链接库类型:STATIC,SHARED 或 MODULE。 如果没有设置,CMake 会根据变量 BUILD_SHARED_LIBS 的值在 STATIC 和 SHARED 之间选择。
正如您将在下一节中看到的那样,通常您需要创建一个伪目标,也就是一个不需要编译任何文件的目标,例如,对于仅包含头文件的库。这也可以称为 INTERFACE 库; 唯一的区别是接口库不能跟文件名。
您还可以用一个现有的链接库生成一个 ALIAS 链接库,该库简单地为您提供目标的新名称。这样做的一个好处是你可以生成一个名称中带 :: 的链接库(稍后会看到)。3
配置构建目标
现在我们已经指定了目标,然后我们怎么给它添加相关信息呢?例如,它可能需要一个 include 目录:
target_include_directories(one PUBLIC include)
target_include_directories 将 include 目录添加到目标. PUBLIC 对可执行文件来说意义不大; 对于一个链接库,它让 CMake 知道链接到这个目标的任何目标也必须包含该目录。 其他选项是 PRIVATE(仅影响当前目标,而不影响依赖项)和 INTERFACE(仅限依赖项所需)。
现在,我们可以把目标串联起来:
add_library(another STATIC another.cpp another.h)
target_link_libraries(another PUBLIC one)
target_link_libraries 可能是 CMake 中最有用也最令人困惑的命令。 它需要一个target(another)并添加依赖目标项。 如果名为 one 的目标不存在,则它会添加指向路径上的一个叫做 one 链接库(即命令的名称)。 或者你可以给它一个完整的链接库路径。或链接器标志。 最后还有一点容易混淆的东西,那就是经典的 CMake 允许你忽略关键字 PUBLIC,等等。 如果目标已经链接完成,尝试在链中进一步混合样式,你会收到错误。
主要关注在任何地方使用目标和关键字,这就对了。
目标可以包含目录,链接库(或链接目标),编译选项,编译定义,编译特征(参见 C++11 章节)等。 正如您将在两个包括项目章节中看到的那样,您通常可以使用目标(并始终制作目标)来表示所有你使用的链接库。 即使那不是真正的链接库的,比如 OpenMP,也可以用目标来表示。 这就是现代 CMake 很棒的原因!
开始动手实践
看看您是否可以理解以下文件操作。 它创建了一个简单的 C++11 链接库和一个使用它的程序。 没有依赖。 我稍后将使用 CMake 3.8 系统讨论更多 C++ 标准选项。
cmake_minimum_required(VERSION 3.8)
project(Calculator LANGUAGES CXX)
add_library(calclib STATIC src/calclib.cpp include/calc/lib.hpp)
target_include_directories(calclib PUBLIC include)
target_compile_features(calclib PUBLIC cxx_std_11)
add_executable(calc apps/calc.cpp)
target_link_libraries(calc PUBLIC calclib)
1. 在这本书中,我将尽可能避免向你展示错误的做事方式; 你可以在网上找到很多这方面的例子。我偶尔会提到替代做法,但除非绝对必要,否则不推荐这些。通常它们只是帮助您阅读较老的 CMake 代码。↩
2. 你有时会看到
FATAL_ERROR, 在 CMake <2.6 版本中,需要使用它来支持失败,现在已经不需要了。↩
3.
::语法最初用来生成INTERFACE IMPORTED链接库, 但是,正因为如此,大多数target_*命令都不适用于IMPORTED链接库。这使得它们很难自行设置。所以现在不要使用IMPORTED关键字,请使用ALIAS构件目标; 这在你导出目标前都能正常工作。此限制已经在 CMake 3.11 中修复。↩
<<Modern CMake>> 翻译 2. CMake 基础的更多相关文章
- <<Modern CMake>> 翻译 1. CMake 介绍
<<Modern CMake>> 翻译 1. CMake 介绍 人们喜欢讨厌构建系统. 仅仅观看 CppCon17 上的演讲,就可以看到开发人员因为构建系统而闹笑话的例子. 这 ...
- <<Modern CMake>> 翻译 2.2 CMake 编程
<<Modern CMake>> 翻译 2.2 CMake 编程 流程控制 CMake有一个 if 语句, 经年累月之后,现在它已经相当复杂. 您可以在 if 语句中使用全大写 ...
- <<Modern CMake>> 翻译 2.3 与代码通信
<<Modern CMake>> 翻译 2.3 与代码通信 配置文件 CMake 允许您使用代码通过 configure_file 存取 CMake 变量. 此命令复制一个文件 ...
- <<Modern CMake>> 翻译 2.4 项目目录结构
<<Modern CMake>> 翻译 2.4 项目目录结构 本节内容有点跑题.但我认为这是一个很好的方法. 我将告诉你如何规划项目的目录. 这是基于惯例,但将帮助您: 轻松阅 ...
- 【转载】CMake 简介和 CMake 模板
转载自我的博客: CMake 简介和 CMake 模板 . 如果你用 Linux 操作系统,使用 cmake 会简单很多,可以参考一个很好的教程: CMake 入门实战 | HaHack .如果你用 ...
- Effective Modern C++翻译(1):序言
/*********************************************************** 关于书: 书是我从网上找到的effective Modern C++的样章,内 ...
- Cmake实践(Cmake Practice)第一部分
参考资料地址:https://github.com/Akagi201/learning-cmake/blob/master/docs/cmake-practice.pdf 一.初识cmake 1. C ...
- mysqlQL 5.7 安装报错CMake Error at cmake/boost.cmake:81 (MESSAGE)
CMake Error at cmake/boost.cmake:81 (MESSAGE): You can download it with -DDOWNLOAD_BOOST=1 -DWITH_BO ...
- CMake Error at cmake/OpenCVUtils.cmake
CMake Error at cmake/OpenCVUtils.cmake:1047 (message): Failed to download . Status= Call Stack (most ...
随机推荐
- 2019年5月23日 AY 程序员调侃语录
我是AY,杨洋,做wpf开发的,最近得了一种病,程序员患得患失综合征.同事说,我年纪在变大,技术跟不上.业余之间,我原创了写了一些语录,给大家中午休息,累疲惫的时候,开心放松下. 1.有很多公司找我谈 ...
- Java虚拟机详解(一)------简介
本系列博客我们将以当前默认的主流虚拟机HotSpot 为例,详细介绍 Java虚拟机.以 JDK1.7 为主,同时介绍与 JDK1.8 的不同之处,通过Oracle官网以及各种文献进行整理,并加以验证 ...
- 29 z-index
这个东西非常简单,它有四大特性,每个特性你记住了,页面布局就不会出现找不到盒子的情况. z-index 值表示谁压着谁,数值大的压盖住数值小的, 只有定位了的元素,才能有z-index,也就是说,不管 ...
- 关于C# 异步
关于C# 异步操作整理 按照个人的理解, 写一个接口用Task异步操作(态度:接受并且学习,您提出宝贵的经验与理解,我会认真学习): 在主线程中调用异步方法,如果主线程依赖异步方法的返回值那么你一定会 ...
- [UWP]从头开始创建并发布一个番茄钟
1. 自己用的番茄钟自己做 在PC上我一直使用"小番茄"作为我的番茄钟软件,我把它打开后放在副显示器最大化,这样不仅可以让它尽到本分,而且还可以告诉我的同事"我正在专心工 ...
- Java中到底是值传递还是引用传递?
Java中到底是值传递还是引用传递? 我们先回顾一下基本概念 实参和形参 参数在编程语言中是执行程序需要的数据,这个数据一般保存在变量中.在Java中定义一个方法时,可以定义一些参数, 举个例子: p ...
- HTTP&HTTPS
主要参考文档:<图解HTTP> HTTP简介 什么是HTTP? HTTP:(HyperText Transfer Protocol),超文本传输协议,是一个基于请求和响应,无状态的,应用层 ...
- 思维导图xmind的使用方法
什么是Xmind Xmind是一款简单好用的思维导图软件,除了可以轻松绘制基本逻辑图,还支持组织结构图(竖直).树状图(水平+竖直).思维导图(辐射).鱼骨图.二维图(表格)模型.免费版可以把思维导图 ...
- springboot+redis+Interceptor+自定义annotation实现接口自动幂等
前言: 在实际的开发项目中,一个对外暴露的接口往往会面临很多次请求,我们来解释一下幂等的概念:任意多次执行所产生的影响均与一次执行的影响相同.按照这个含义,最终的含义就是 对数据库的影响只能是一次性的 ...
- Go - Map 集合
目录 概述 声明 Map 生成 JSON 编辑和删除 推荐阅读 概述 Map 集合是无序的 key-value 数据结构. Map 集合中的 key / value 可以是任意类型,但所有的 key ...