官网教程——Cmake 中的重要概念

news/2024/6/3 18:05:29 标签: c++, 机器人, 自动驾驶, stm32, 物联网, Cmake

文章目录

  • 前言
  • 一、重要概念——目标(Target)
    • 1.1 使用要求
    • 1.2 使用目标指定优化库或调试库
    • 1.3 对象库
    • 1.4 源文件
    • 1.5 目录、测试和属性
  • 二、Policies
    • 2.1 设计目标
    • 2.2 Setting Policies
  • 三、Modules(模块,组)
    • 3.1 使用模块
      • 3.1.2 查找模块
      • 3.1.3 公用模块
  • 四、Installing Files
  • `如果觉得内容不错,请点赞、收藏、关注`


前言

本章将介绍 CMake 的主要概念。在开始使用 CMake 时,您会遇到各种概念,如目标、生成器和命令。了解这些概念将为您提供创建有效 CMakeLists 文件所需的工作知识。许多 CMake 对象(如目标、目录和源文件)都有与之相关的属性。属性是附加到特定对象的键值对。访问属性的最通用方法是使用 set_property 和 get_property 命令。这些命令允许您设置或获取 CMake 中任何具有属性的对象的属性。有关支持的属性列表,请参阅 cmake-properties 手册。通过命令行运行 cmake 并使用 --help-property-list 选项,可获得 CMake 支持的全部属性列表。


一、重要概念——目标(Target)

最重要的一项可能是目标。目标代表 CMake 构建的可执行文件、库和实用程序。每一条 add_library、add_executable 和 add_custom_target 命令都会创建一个目标。例如,下面的命令将创建一个名为 "foo "的目标,它是一个静态库,源文件为 foo1.c 和 foo2.c。

add_library(foo STATIC foo1.c foo2.c)

现在,"foo "这个名字可以在项目的其他地方作为库名使用,CMake 知道如何在需要时将这个名字扩展到库中。库可以声明为 STATIC、SHARED、MODULE 等特定类型,也可以不声明。STATIC 表示该库必须作为静态库构建。同样,SHARED 表示必须作为共享库构建。MODULE 表示必须创建该库,以便动态加载到可执行文件中。在许多平台上,模块库都是作为共享库实现的,但并非所有平台都是如此。因此,CMake 不允许其他目标链接到模块。如果这些选项都未指定,则表明该库可作为共享或静态库构建。在这种情况下,CMake 会使用变量 BUILD_SHARED_LIBS 的设置来决定该库应该是共享的还是静态的。如果没有设置该变量,CMake 将默认联编静态库。

同样,可执行文件也有一些选项。默认情况下,可执行文件是一个具有主入口点的传统控制台应用程序。可以指定一个 WIN32 选项,在 Windows 系统上请求使用 WinMain 入口点,而在非 Windows 系统上保留 main 入口点。

除了存储其类型外,目标程序还会跟踪一般属性。这些属性可以使用 set_target_properties 和 get_target_property 命令,或更通用的 set_property 和 get_property 命令进行设置和检索。其中一个有用的属性是 LINK_FLAGS,用于指定特定目标的附加链接标志。目标存储了一个链接所针对的库列表,可以使用 target_link_libraries 命令进行设置。传入该命令的名称可以是库、库的完整路径或 add_library 命令中的库名。目标还存储了链接时要使用的链接目录,以及构建后要执行的自定义命令。

1.1 使用要求

CMake 还会传播链接库目标中的 “使用要求”。使用要求会影响 中源代码的编译。它们由链接目标上定义的属性指定。

例如,要指定链接到库时所需的包含目录,可以使用下面的方法:

add_library(foo foo.cxx)
target_include_directories(foo PUBLIC
                           "${CMAKE_CURRENT_BINARY_DIR}"
                           "${CMAKE_CURRENT_SOURCE_DIR}"
                           )

现在,任何指向目标 foo 的链接都会自动将 foo 的二进制文件和源代码作为包含目录。通过 "使用要求 "引入的 include 目录的顺序将与 target_link_libraries 调用中目标的顺序一致。

对于 CMake 创建的每个库或可执行文件,它都会使用 target_link_libraries 命令跟踪该目标所依赖的所有库。例如

add_library(foo foo.cxx)
target_link_libraries(foo bar)

add_executable(foobar foobar.cxx)
target_link_libraries(foobar foo)

会将库 "foo "和 "bar "链接到可执行文件 "foobar "中,即使只明确指定了 “foo”。

1.2 使用目标指定优化库或调试库

在 Windows 平台上,用户通常需要将调试库与调试库链接,将优化库与优化库链接。CMake 的 target_link_libraries 命令可帮助满足这一要求,该命令可接受一个标记为调试或优化的可选标志。如果一个库前面标有调试或优化,那么该库将只与相应的配置类型链接。例如

add_executable(foo foo.c)
target_link_libraries(foo debug libdebug optimized libopt)

在这种情况下,如果选择了调试构建,foo 将与 libdebug 链接;如果选择了优化构建,foo 将与 libopt 链接。

1.3 对象库

大型项目通常会将源文件组织成不同的组,这些组可能位于不同的子目录中,每个组都需要不同的包含目录和预处理器定义。针对这种情况,CMake 提出了对象库的概念。

对象库是编译成对象文件的源文件集合,它不会被链接到库文件中,也不会被制作成归档文件。相反,由 add_library 或 add_executable 创建的其他目标可以使用 $<TARGET_OBJECTS:name> 形式的表达式作为源引用对象,其中 "name "是由 add_library 调用创建的目标。例如

add_library(A OBJECT a.cpp)
add_library(B OBJECT b.cpp)
add_library(Combined $<TARGET_OBJECTS:A> $<TARGET_OBJECTS:B>)

将在一个名为 Combined 的库中包含 A 和 B 对象文件。对象库只能包含编译为对象文件的源代码(和头文件)。

1.4 源文件

源文件结构在很多方面与目标文件类似。它存储了文件名、扩展名以及与源文件相关的一些常规属性。与目标文件一样,可以使用 set_source_files_properties 和 get_source_file_property 或更通用的版本来设置和获取属性。

1.5 目录、测试和属性

除了目标和源文件外,您可能偶尔还会发现自己在处理目录和测试等其他对象。通常,这种交互方式是设置或获取这些对象的属性(如 set_directory_properties 或 set_tests_properties)。


二、Policies

CMake 有时会出现与旧版本不完全向后兼容的新功能或更改。当有人试图在新版 CMake 中使用旧版 CMakeLists 文件时,就会产生问题。为了帮助最终用户和开发人员解决这些问题,我们引入了 cmake-policies。策略是一种帮助提高向后兼容性和跟踪不同版本 CMake 之间兼容性问题的机制。

2.1 设计目标

CMake 策略机制有四个主要设计目标:

  1. 现有项目应使用比项目作者使用的 CMake 版本更新的 CMake 进行构建。(用户不需要编辑代码就能完成项目的联编。可能会发出警告,但项目应能联编。)

  2. 新界面的正确性或旧界面的错误修复不应受到兼容性要求的限制。任何降低最新界面正确性的做法对新项目都是不公平的。

  3. 对 CMake 所做的每一项更改都应记录在案,这些更改可能需要更改项目的 CMakeLists 文件。(每项变更都应有一个唯一的标识符,以便在警告和错误信息中引用。只有当项目以某种方式表示支持新行为时,新行为才会启用。)

  4. 我们必须能够最终删除实现与古老 CMake 版本兼容的代码。(为了保持代码的整洁并允许内部重构,删除这些代码是必要的。移除后,在尝试构建为旧版本编写的项目时,就会出现失败的提示信息。)

CMake 中的所有策略都以 CMPNNNN 的形式命名,其中 NNNN 是一个整数值。策略通常既支持与 CMake 早期版本兼容的旧行为,也支持被认为正确并优先用于新项目的新行为。每个策略都有文档详细说明更改的动机以及新旧行为。

2.2 Setting Policies

项目可配置每个策略的设置,以要求旧的或新的行为。当 CMake 遇到可能受特定策略影响的用户代码时,它会检查项目是否设置了该策略。如果已设置策略(旧或新),CMake 将遵循指定的行为。如果未设置策略,则使用旧的行为,但会发出警告,告知项目作者设置策略。

有几种方法可以设置策略的行为。最快捷的方法是将所有策略设置为与项目编写时的 CMake 发行版本相对应的版本。设置策略版本会要求在 CMake 的相应版本或更早版本中引入的所有策略都采用新的行为。以后版本中引入的策略会被标记为 “未设置”,以便生成适当的警告信息。策略版本使用 cmake_policy 命令的 VERSION 签名来设置。例如,代码

cmake_policy(VERSION 3.20)

将请求 CMake 3.20 或更早版本中引入的所有策略的新行为。

cmake_minimum_required 命令将要求 CMake 的最低版本,并调用 cmake_policy。项目应始终以开头

cmake_minimum_required(VERSION 3.20)
project(MyProject)
# ...code using CMake 3.20 policies

这表明运行 CMake 的人必须至少有 3.20 版本。如果运行的是旧版本的 CMake,则会显示一条错误信息,告诉他们项目至少需要指定版本的 CMake。

当然,"3.20 "应替换为您当前编写的 CMake 版本。如果愿意,您也可以单独设置每项策略;这有时对项目作者很有帮助,因为他们希望逐步转换项目以使用新行为,或消除对旧行为依赖性的警告。cmake_policy 命令的 SET 选项可用于明确请求特定策略的新旧行为。

例如,CMake 2.6 引入了 CMP0002 策略,它要求所有逻辑目标名称必须是全局唯一的(以前在某些情况下,重复的目标名称会意外工作,但不会被诊断出来)。使用重复目标名称并意外运行的项目将收到引用该策略的警告。可以使用代码

cmake_policy(SET CMP0002 OLD)

明确告诉 CMake 使用旧的策略行为(默许目标名称重复)。另一种方法是使用代码

cmake_policy(SET CMP0002 NEW)

来明确告诉 CMake 使用新的行为,并在创建重复目标时产生错误。一旦将此添加到项目中,在作者删除任何重复的目标名称之前,项目将无法编译。

CMake 发布新版本时,会引入一些新策略,这些新策略仍然可以编译旧项目,因为默认情况下,它们不会请求任何新策略的新行为。启动新项目时,应始终使用 cmake_minimum_required 命令指定 CMake 支持的最新版本。这将确保编写的项目使用该版本 CMake 的策略,而不是使用任何旧的行为。如果没有设置策略版本,CMake 将发出警告并假定策略版本为 2.4。这将允许未指定 cmake_minimum_required 的现有项目按照 CMake 2.4 版本进行编译。

三、Modules(模块,组)

3.1 使用模块

代码重用是软件开发中的一项重要技术,CMake 就是为支持代码重用而设计的。允许 CMakeLists 文件使用可重复使用的模块,能让整个社区共享可重复使用的代码段。对于 CMake 而言,这些代码段被称为 cmake-modules,可在安装的 Modules 子目录中找到。

可以使用模块文件的完整路径指定模块的位置,也可以让 CMake 自行查找模块。CMake 会在 CMAKE_MODULE_PATH 所指定的目录中查找模块;如果找不到,就会在 Modules 子目录中查找。这样,项目就可以覆盖 CMake 提供的模块,并根据自己的需要进行定制。模块可分为几大类:

3.1.2 查找模块

这些模块支持 find_package 命令,用于确定属于特定软件包的软件元素(如头文件或库)的位置。不要直接包含它们。请使用 find_package 命令。每个模块都附有文档,说明它所查找的软件包以及提供结果的变量。

3.1.3 公用模块

实用程序模块是 CMake 命令的一部分,被放入一个文件中;然后可以使用 include 命令将它们包含到其他 CMakeLists 文件中。例如,以下命令将包含 CMake 中的 CheckTypeSize 模块,然后使用它定义的宏。

include(CheckTypeSize)
check_type_size(long SIZEOF_LONG)

这些模块对系统进行测试,以提供有关目标平台或编译器的信息,例如浮点数的大小或对 ANSI C++ 流的支持。其中许多模块的名称都以 Test 或 Check 为前缀,如 TestBigEndian 和 CheckTypeSize。其中有些模块会尝试编译代码,以确定正确的结果。在这种情况下,源代码的名称通常与模块相同,但扩展名为 .c 或 .cxx。实用工具模块还提供有用的宏和函数,这些宏和函数用 CMake 语言实现,用于特定的常用情况。详情请参见各模块的文档。


四、Installing Files

软件通常安装在一个独立于源代码和构建树的目录中。这样可以使软件以简洁的形式发布,并将用户与构建过程的细节隔离开来。CMake 提供 install 命令来指定项目的安装方式。该命令由 CMakeLists 文件中的项目调用,并告诉 CMake 如何生成安装脚本。这些脚本会在安装时被执行,以完成文件的实际安装。对于 Makefile 生成器(UNIX、NMake、MinGW 等),用户只需运行 make install(或 nmake install),make 工具就会调用 CMake 的安装模块。对于基于图形用户界面的系统(Visual Studio、Xcode 等),用户只需构建名为 INSTALL 的目标即可。

每次调用 install 命令都会定义一些安装规则。在一个 CMakeLists 文件(源代码目录)中,这些规则将按照调用相应命令的顺序进行评估。在 CMake 3.14 中,跨多个目录的顺序发生了变化。

install 命令有几个签名,是为常见的安装用例而设计的。命令的特定调用会指定签名作为第一个参数。签名包括 TARGETS、FILES 或 PROGRAMS、DIRECTORY、SCRIPT、CODE 和 EXPORT。

如果觉得内容不错,请点赞、收藏、关注


http://www.niftyadmin.cn/n/5154851.html

相关文章

CDR2024免费版服装设计工具

cdr是CorelDRAW的简称&#xff0c;一款专注排版和矢量图形编辑的平面设计软件。这款软件的设计界面精微细致、简洁易懂。功能尤其强大&#xff0c;图标设计&#xff0c;印刷排版&#xff0c;服装设计等都可以胜任。还有多种模板使得设计相当的轻松&#xff0c;今天简单介绍一下…

【工具】【Windows】【SecureCrt】SecureCRT下载与安装

SecureCRT下载与安装 下载SecureCRT-6.2.0-PortableSecureCRT-7.0.0_SecureFX_HH_x64-PortableSecureCRT-8.1.3SecureCRT-8.1.4SecureCRT-8.7.1_SecureFXSecureCRT-9.2.3_SecureFXSecureCRT 8.x注册机使用说明SecureCRTSecureFX 安装 下载 SecureCRT-6.2.0-Portable 链接&…

使用合成数据训练语义分割模型

计算机视觉应用现在在各个科技领域无处不在。 这些模型高效且有效&#xff0c;研究人员每年都会尝试新想法。 新的前沿是试图消除深度学习的最大负担&#xff1a;需要大量的标记数据。 正如本文所述&#xff0c;此问题的解决方案是使用合成数据。 从这些研究中获益最多的计算机…

Java序列化和Json格式的转化

Java序列化和JSON格式的转换都是在不同格式之间实现对象的传输&#xff0c;并在数据节点之间方便地进行信息交换&#xff0c;其中主要区别在于它们的工作原理和应用场景。 Java序列化是将 Java 对象转换为字节流&#xff08;二进制格式的数据&#xff09;&#xff0c;以便在网…

策略模式在数据接收和发送场景的应用

在本篇文章中&#xff0c;我们介绍了策略模式&#xff0c;并在数据接收和发送场景中使用了策略模式。 背景 在最近项目中&#xff0c;需要与外部系统进行数据交互&#xff0c;刚开始交互的系统较为单一&#xff0c;刚开始设计方案时打算使用了if else 进行判断&#xff1a; if(…

海康Visionmaster-全局脚本:方案加载完成信号发给通 信设备的方法

需要在方案加载完成后&#xff0c;发送加载完成信号到全局变量&#xff0c;发送给通信设备。 全局脚本的使用可以通过打开示例&#xff0c;完成常用的基本功能开发。 打开全局通信代码后&#xff0c;在脚本中添加代码

Danswer 接入 Llama 2 模型 | 免费在 Google Colab 上托管 Llama 2 API

一、前言 前面在介绍本地部署免费开源的知识库方案时&#xff0c;已经简单介绍过 Danswer《Danswer 快速指南&#xff1a;不到15分钟打造您的企业级开源知识问答系统》&#xff0c;它支持即插即用不同的 LLM 模型&#xff0c;可以很方便的将本地知识文档通过不同的连接器接入到…

【JavaScript】零碎知识点总结_2

1. 引入网站图标 可以直接放在根目录 还可以 link 引入&#xff08;推荐&#xff09; <linkrel"shortcut icon"href"./assets/favicon.ico"type"image/x-icon">2. 转换为数字 123 -> 123 除 做字符串拼接&#xff0c;算术运算符都…