<svg xmlns="http://www.w3.org/2000/svg" style="display: none;"> <path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path> </svg> <p><font size="4">前言:</font></p>
讯享网
学习笔记,随时更新。如有谬误,欢迎指正。
说明:
- 红色字体为较为重要部分。
- 绿色字体为个人理解部分。
软件通常安装到与源和构建树不同的目录中。这让它以干净的形式分发,并将用户与构建过程的细节隔离开来。 CMake 提供 install 命令来指定项目的安装方式。此命令由 CMakeLists 文件中的项目调用,并告知 CMake 如何生成安装脚本。脚本在安装时执行,以执行文件的实际安装。对于 Makefile 生成器( UNIX 、 NMake 、 MinGW 等),用户只需运行 make install (或 nmake install ), make 工具将调用 CMake 的安装模块。对于基于 GUI 的系统( Visual Studio , Xcode 等),用户只需构建名为 INSTALL 的目标。
每次调用 install 命令都会定义一些安装规则。在一个 CMakeLists 文件(源目录)中,将按照调用相应命令的顺序计算这些规则。但跨多个目录的顺序在 CMake 3.14 中改变了。
install 命令具有多个专为常见安装用例设计的签名。命令的特定调用将签名指定为第一个参数。签名分别为 TARGETS 、 FILES 、 PROGRAMS 、 DIRECTORY 、 SCRIPT 、 CODE 和 EXPORT 。
install(TARGETS …)
- 安装项目内生成的目标所对应的二进制文件。
install(FILES …)
- 通用文件安装。通常用于软件所需的头文件、文档和数据文件。
install(PROGRAMS …)
- 安装不是由项目生成的可执行文件,例如 shell 脚本。除了安装文件的默认权限(文件权限包括可读、可写、可执行等)包括可执行位之外,它与 install(FILES) 是相同的。
install(DIRECTORIES …)
- 此参数安装整个目录树。它可用于安装带有资源(如图标和图像)的目录。
install(SCRIPTS …)
- 指定要在安装过程中执行的用户提供的 CMake 脚本文件。这通常用于定义其他规则的安装前或安装后的操作。
install(CODE …)
- 指定要在安装过程中执行的用户提供的 CMake 代码。这类似于 install(SCRIPT) ,但代码在调用中以字符串形式内联提供。
install(EXPORT …)
- 生成并安装一个 CMake 文件,其中包含从安装树导入目标到另一个项目的代码。
TARGETS 、 FILES 、 PROGRAMS 和 DIRECTORY 签名都用于为文件创建安装规则。要安装的目标、文件或目录紧跟在签名名称参数之后。可以使用关键字参数后跟相应的值来指定其他详细信息。大多数签名提供的关键字参数如下所示。
DESTINITION
- 指定安装规则将要放置文件的位置。此参数后必须紧跟着(指定)目录路径来表明位置。如果目录被指定为完整路径,它将在安装时按绝对路径进行处理。如果目录被指定为相对路径,它将被认为是相对于安装前缀(的路径)。前缀可以由用户通过 CMAKE_INSTALL_PREFIX 缓存变量进行设置。特定于平台的默认值由CMake提供:在 UNIX上 是“ /usr/local ”。在Windows上是“ <SystemDrive>/Program Files/ ”,其中 SystemDrive 类似于“ C: ”, ProjectName 是最顶层的 project 命令指定的名称。
PERMISSIONS
- 指定要设置在被安装文件上的权限。此选项仅用于覆盖由 install 命令签名选择的默认权限。可用的此权限有 OWNER_READ 、 OWNER_WRITE 、 OWNER_EXECUTE 、 GROUP_READ 、 GROUP_WRITE 、 GROUP_EXECUTE 、 WORLD_READ 、 WORLD_WRITE 、 WORLD_EXECUTE 、 SETUID 和 SETGID 。有些平台并不支持以上所有权限,在此类平台上,这些(不支持的)权限名称将被忽略。
CONFIGURATIONS
- 指定构建配置的列表,该列表被安装规则所应用( Debug 、 Release 等)。对于 MakeFile 生成器,则构建配置由 CMAKE_BUILD_TYPE 缓存变量指定。对于 Visual Studio 和 Xcode 生成器,则在构建 install 目标时选择配置。只有当前构建配置与此参数提供的列表中的某项相匹配时,安装规则才会被评估(执行)。配置名称的比较不区分大小写。
COMPONENT
- 指定安装规所应用的安装组件。有些项目将其安装划分为多个组件,以进行单独的打包。例如,一个项目可以定义一个 Runtime 组件,其中包含运行工具所需的文件; Development 组件,包含构建工具扩展所需的文件;以及包含手册页和其他帮助文件的 Documentation 组件。然后,项目可以通过一次只安装一个组件的方式,将每个组件分别打包分发。默认情况下,会安装所有组件。特定于组件的安装是一种高级特性,旨在供包维护人员使用。它需要手动调用安装脚本,并使用一个参数以定义 COMPONENT 变量来命名所需的组件。注意,组件名称不是由 CMake 定义的。每个项目都可以定义自己的组件集。
OPTIONAL - 指定如果要安装的输入文件不存在,这不是错误。如果输入文件存在,将按要求安装它。如果它不存在,它将不被安装。
项目通常会安装一些在构建过程中创建的库和可执行文件。 install 命令为此目的提供了TARGETS签名。
TARGETS 关键字后面紧跟着使用 add_executable 或 add_library 创建的目标列表,这些目标将被安装。与每个目标对应的一个或多个文件将会被安装。
使用此签名安装的文件可以分为三类: ARCHIVE 、 LIBRARY 和 RUNTIME 。这些类别旨在按典型安装目的地对目标文件进行分组。对应的关键字参数是可选的,但如果存在,则指定在它们后面的其他参数只会应用于该类型的目标文件。目标文件分类如下:
可执行文件 - RUNTIME
- 由 add_executable 创建(在 Windows 上是 .exe ,在 UNIX 上没有扩展名)。
可加载模块 - LIBRARY
- 由带有选项 MODULE 的 add_library 创建(在 Windows 上是 .dll , 在 UNIX 上是 .so )。
共享库 - LIBRARY
- 在类 UNIX 平台上,由带有选项 SHARED 的 add_library 创建(大多数 UNIX 上是 .so , Mac 上是 .dylib )。
动态链接库 - RUNTIME
- 在 Windows 平台上,由带有 SHARED 选项的 add_library 创建( .dll )。
导入库 - ARCHIEVE
- 由导出符号的动态链接库创建的可链接文件(大多数 Windows 上是 .lib , Cygwin 和 MinGW 上是 .dll.a )。
静态库 - ARCHIEVE
- 由带有 STATIC 选项的 add_library 创建( Windows 上是 .lib , UNIX 、 Cygwin 和 MinGW 上是 .a )。
来看这样一个项目,它定义了一个可执行文件 myExecutable ,它链接到一个共享库 mySharedLib 。它还提供了一个静态库 myStaticLib ,以及一个名为 myPlugin 的可执行文件插件模块,该模块也链接到共享库。可执行文件、静态库和插件文件可以使用如下命令单独安装:
讯享网
在可执行文件链接到的共享库也被安装之前,该可执行文件将无法从已安装的位置运行。为了支持所有平台,库的安装需要注意更多(的东西)。它必须安装在每个平台上的动态链接器搜索的位置。在类 UNIX 平台上,库通常安装到 lib 中,而在 Windows 上,它应该放在 bin 中可执行文件的旁边。另一个挑战是,与 Windows 上的共享库相关联的导入库应该像静态库一样对待,并安装到 lib/myproject 中。换句话说,我们用一个目标名称创建了三种不同类型的文件,必须将它们安装到三个不同的目的地。幸运的是,这个问题可以使用类别关键字参数解决。可以使用以下命令安装共享库:
这告诉 CMake RUNTIME 文件( .dll )应该安装到 bin 中, LIBRARY 文件( .so )应该安装到 lib 中, ARCHIVE 文件( .lib )应该安装到 lib/myproject 中。在 UNIX 上, LIBRARY 文件将被安装;在 Windows 上, RUNTIME 和 ARCHIVE 文件将被安装。
如果要将上面的示例项目打包到单独的运行时和开发组件中,我们必须为安装的每个目标文件分配适当的组件。可执行文件、共享库和插件是运行应用程序所必需的,因此它们属于一个 Runtime 组件。同时,导入库(对应于 Windows 上的共享库)和静态库仅用于开发应用程序的扩展,因此属于 Development 组件。
组件分配可以通过向上面的每个命令添加 COMPONENT 参数来指定。你还可以将所有安装规则组合到一个命令调用中,这相当于添加了组件的上述所有命令。每个目标生成的文件使用它们的类别的规则进行安装。
讯享网
可以将 NAMELINK_ONLY 或 NAMELINK_SKIP 指定为 LIBRARY 选项。在某些平台上,版本化的共享库具有一个符号链接,例如:
lib<name>.so.1 是库的 soname,lib<name>.so 是一个“名称链接“,当给定 -l<name> 时,它帮助链接器找到库。 NAMELINK_ONLY 选项导致在安装库目标时只安装名称链接。 NAMELINK_SKIP 选项导致在安装库目标时安装名称链接以外的库文件。如果没有给出任何选项,则两个部分都会被安装。在版本控制的共享库没有名称链接的平台上,或者当库没有版本控制时, NAMELINK_SKIP 选项会安装库,而 NAMELINK_ONLY 选项什么也不安装。有关创建版本共享库的详细信息,请参阅 VERSION 和 SOVERSION 目标属性。
项目可以安装使用 add_executable 或 add_library 创建的文件以外的文件,例如头文件或文档。文件的通用安装是使用 FILES 签名指定的。
FILES 关键字后面紧跟着要安装的文件列表。相对路径相对于当前源目录求值。文件将被安装到给定的 DESTINATION 目录。例如,命令
讯享网
从源码树安装 my-api.h 文件,从构建树安装 my-config.h 文件到安装前缀(目录)下的 include 目录。默认情况下,安装文件的权限为 OWNER_WRITE 、 OWNER_READ 、 GROUP_READ 和 WORLD_READ ,但是可以通过指定 PERMISSIONS 选项来覆盖这些权限。考虑这样的情况:用户希望在 UNIX 系统上安装只有其所有者(例如 root )可读的全局配置文件。我们使用下面命令来完成这一任务:
上述操作将具有所有者读/写权限的文件 my-rc 安装到绝对路径 /etc 中。
RENAME 参数指定已安装文件的名称,该名称可能与原始文件不同。只有当命令安装单个文件时才允许重命名。例如,命令
讯享网
将从源目录中将文件 version.h 安装为安装前缀(目录)下的 include/my-version.h 。
项目还可能安装辅助程序,例如 shell 脚本或 python 脚本,这些脚本实际上并不是作为目标编译的。这些文件可以使用 FILES 签名来安装,并且通过 PERMISSIONS 选项添加执行权限。然而,这种情况很常见,因此需要一个更简单的接口。 CMake 为此目的提供了 PROGRAMS 签名。
PROGRAMS 关键字后面紧跟着要安装的脚本列表。该命令与 FILES 签名相同,不同之处是默认权限额外包括 OWNER_EXECUTE 、 GROUP_EXECUTE 和 WORLD_EXECUTE 。例如,我们可以用如下命令安装一个 Python 工具脚本:
它将 my-util.py 安装到安装前缀(目录)下的 bin 目录下,并赋予它 owner 、 group 、 world 级别的读取和执行权限,以及 owner 级别的写权限。
项目还可能提供一个充满资源文件的完整目录,如图标或 html 文档。可以使用 DIRECTORY 签名安装整个目录。
DIRECTORY 关键字后面紧跟着要安装的目录列表。相对路径相对于当前源目录求值。每个命名目录都安装到目标目录中。每个输入目录名的最后一个组件在复制目标目录时附加到该目录。例如,命令

讯享网
将源码树的 data/icons 目录安装到安装前缀(目录)下的 share/myproject/icons 中。尾部的斜杠将使最后一个组件为空,并将输入目录的内容安装到目标目录。命令
将源码目录 doc/html 中的内容安装到安装前缀(目录)下的 doc/myproject 中。如果没有给出输入目录名,将创建目标目录,但不会将任何内容安装到其中。如
讯享网
由 DIRECTORY 签名安装的文件被赋予与 FILE 签名相同的默认权限。由 DIRECTORY 签名安装的目录具有与 PROGRAMS 签名相同的默认权限。 FILE_PERMISSIONS 和 DIRECTORY_PERMISSIONS 选项可用于覆盖这些默认值。考虑这样一种情况:将一个充满示例 shell 脚本的目录安装到一个 owner 和 group 都可写的目录中。我们可以使用命令
它将目录 data/scripts 安装到 share/myproject/scripts 中,并设置所需的权限。在某些情况下,项目创建的完备的输入目录可能已经设置了所需的权限。 USE_SOURCE_PERMISSIONS 选项告诉 CMake 在安装期间使用来自输入目录的文件和目录权限。如果在前面的示例中输入目录已经准备好了正确的权限,那么可以使用以下命令:
讯享网
如果要安装的输入目录处于源码管理之中(意思是对源码使用版本控制工具,如 git ),则输入中可能有你不希望安装的额外子目录。也可能有特定的文件不应该安装,或者安装时具有不同的权限,而大多数文件获得默认权限。 PATTERN 和 REGEX 选项可用于此目的。 PATTERN 选项后面首先是一个全局模式,然后是一个 EXCLUDE 或 PERMISSIONS 选项。 REGEX 选项后面首先是一个正则表达式,然后是 EXCLUDE 或 PERMISSIONS 。 EXCLUDE 选项跳过与前面的模式或表达式匹配的文件或目录的安装,而 PERMISSIONS 选项为它们分配特定的权限。
每个输入文件和目录都将根据模式或正则表达式以带正斜杠的完整路径进行测试。模式将只匹配出现在完整路径末尾的完整文件或目录名,而正则表达式可以匹配任何部分。例如,模式 foo* 将匹配 …/foo.txt ,但不匹配 …/myfoo.txt 或 …/foo/bar.txt ;然而,正则表达式 foo 将匹配所有上述这些表达。
回到上面安装图标目录的例子,考虑这样一个情况:输入目录由 git 管理,还包含一些我们不想安装的额外文本文件。命令
安装图标目录,忽略包含任何 .git 的目录或文本文件。使用 REGEX 选项的等价命令是
讯享网
它使用’ / ‘和’ $ '以与模式相同的方式约束匹配。考虑一个类似的情况,其中输入目录包含 shell 脚本和文本文件,我们希望以不同于其他文件的权限安装它们。命令
将源码目录中 data/other 的内容安装到 share/myproject 中,忽略 .git 目录,并给予 .txt 和 .sh 文件特定的权限。
项目安装可能需要执行其他任务,而不仅仅是在安装树中放置文件。第三方包可能提供它们自己的机制来注册在项目安装期间必须调用的新插件。 SCRIPT 签名就是为此目的而提供的。
SCRIPT 关键字后面紧跟着 CMake 脚本的名称。 CMake 将在安装期间执行脚本。如果给定的文件名是一个相对路径,则它将相对于当前源目录求值。一个简单的用例是在安装期间打印一条消息。我们首先写一个 message.cmake 文件,其中包含以下代码:
讯享网
然后使用下面的命令引用这个脚本:
自定义安装脚本不会在主 CMakeLists 文件处理过程中执行,它们在安装过程本身期间执行。在包含 install(SCRIPT) 调用的代码中定义的变量和宏将不能从脚本中访问。但是,在脚本执行过程中定义了一些变量,可用于获取关于安装的信息。变量 CMAKE_INSTALL_PREFIX 被设置为实际的安装前缀。这可能与对应的缓存变量值不同,因为安装脚本可能由使用不同前缀的打包工具执行。环境变量 ENV{DESTDIR} 可以由用户或打包工具设置。它的值被添加到安装前缀和绝对安装路径前面,以确定文件安装的位置。为了引用磁盘上的安装位置,自定义脚本可以使用 {CMAKE_INSTALL_PREFIX} 作为路径的顶层部分。变量 CMAKE_INSTALL_CONFIG_NAME 设置为当前正在安装的构建配置的名称( Debug 、 Release 等)。在特定于组件的安装过程中,变量 CMAKE_INSTALL_COMPONENT 被设置为当前组件的名称。
自定义安装脚本,就像上面的消息一样简单,通过将脚本代码内联放置在对 install 命令的调用中,这样更简单。 CODE 签名就是为此目的而提供的。
CODE 关键字后面紧跟着一个字符串,其中包含要放在安装脚本中的代码。可以使用该命令创建安装时消息
讯享网
这和 message.cmake 脚本的效果是一样的,但包含内联代码。
8.6.1 安装先决的共享库
通常使用共享库作为构建块来构建可执行程序。当你安装这样一个可执行文件时,你还必须安装它的先决条件共享库,称为“先决条件”,因为可执行文件需要它们的存在才能正常加载和运行。共享库的三个主要来源是操作系统本身、你自己项目的构建产品和属于外部项目的第三方库。来自操作系统的文件可能不需要安装任何东西就会出现:它们位于可执行文件运行的基础平台上。你自己项目中的构建产品可能在 CMakeLists 文件中有 add_library 构建规则,因此为它们创建 CMake 安装规则应该很简单。当第三方库的数量有好几个,或者当它们的集合在第三方项目的不同版本之间波动时,第三方库常常成为一个高维护的项目。库可能被添加,代码可能被重组,第三方共享库本身实际上可能有额外的先决条件,这些条件乍一看并不明显。
CMake提供了一个模块,BundleUtilities 来来更容易地处理共享库的需求。 该模块提供了 fixup_bundle 函数,用于使用相对于可执行文件的定义良好的位置来复制和修复先决条件共享库。对于 Mac 包应用程序,它将库嵌入到包中,用 install_name_tool 修复它们,使其成为一个自包含的单元。在 Windows 上,它将库复制到与可执行文件相同的目录中,因为可执行文件将在自己的目录中搜索所需的 DLL (之前的 CMake 版本中还有一种方式:GetPrerequisites.cmake,它提供了 get_prerequisites 函数来分析和归类可执行文件所依赖的先决的共享库。给一个可执行文件作为输入,它将会提供一个该可执行文件运行所需的共享库,包括所发现的共享库本身的任何先决条件。它使用各种底层平台的原生工具来进行这个分析: dumpbin(Windows) 、 otools(Mac) 和 ldd(Linux) )。
fixup_bundle 函数帮助你创建可重定位的安装树。 Mac 用户喜欢自包含的包应用程序:你可以把它们拖到任何地方,双击它们,它们仍然可以工作。除了操作系统本身之外,它们不依赖于安装在某个位置的任何东西。类似地,没有管理权限的 Windows 用户喜欢可重定位的安装树,其中可执行文件和所有必需的 DLL 都安装在同一个目录中,这样无论在哪里安装都可以工作。你甚至可以在安装后移动它们,它仍然可以工作。
要使用 fixup_bundle ,首先安装一个可执行目标。然后,配置一个可以在安装时调用的 CMake 脚本。在配置的 CMake 脚本中,只需 include(BundleUtilities) 并使用适当的参数调用 fixup_bundle 函数。
在 CMakeLists.txt 中:
在 FixBundle.cmake.in 中:
讯享网
你负责验证你是否拥有复制和分发可执行文件的必要先决共享库的权限。有些库可能有限制性的软件许可,禁止使用 fixup_bundle 复制。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/144213.html