CMake中install的使用

Posted fengbingchun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CMake中install的使用相关的知识,希望对你有一定的参考价值。

      CMake中的install命令用于指定安装时要运行的规则,其格式如下:

install(TARGETS targets... [EXPORT <export-name>]
        [RUNTIME_DEPENDENCIES args...|RUNTIME_DEPENDENCY_SET <set-name>]
        [[ARCHIVE|LIBRARY|RUNTIME|OBJECTS|FRAMEWORK|BUNDLE|
          PRIVATE_HEADER|PUBLIC_HEADER|RESOURCE|FILE_SET <set-name>|CXX_MODULES_BMI]
         [DESTINATION <dir>]
         [PERMISSIONS permissions...]
         [CONFIGURATIONS [Debug|Release|...]]
         [COMPONENT <component>]
         [NAMELINK_COMPONENT <component>]
         [OPTIONAL] [EXCLUDE_FROM_ALL]
         [NAMELINK_ONLY|NAMELINK_SKIP]
        ] [...]
        [INCLUDES DESTINATION [<dir> ...]]) # Installing Targets

install(IMPORTED_RUNTIME_ARTIFACTS targets...
        [RUNTIME_DEPENDENCY_SET <set-name>]
        [[LIBRARY|RUNTIME|FRAMEWORK|BUNDLE]
         [DESTINATION <dir>]
         [PERMISSIONS permissions...]
         [CONFIGURATIONS [Debug|Release|...]]
         [COMPONENT <component>]
         [OPTIONAL] [EXCLUDE_FROM_ALL]
        ] [...]) # Installing Imported Runtime Artifacts

install(<FILES|PROGRAMS> files...
        TYPE <type> | DESTINATION <dir>
        [PERMISSIONS permissions...]
        [CONFIGURATIONS [Debug|Release|...]]
        [COMPONENT <component>]
        [RENAME <name>] [OPTIONAL] [EXCLUDE_FROM_ALL]) # Installing Files

install(DIRECTORY dirs...
        TYPE <type> | DESTINATION <dir>
        [FILE_PERMISSIONS permissions...]
        [DIRECTORY_PERMISSIONS permissions...]
        [USE_SOURCE_PERMISSIONS] [OPTIONAL] [MESSAGE_NEVER]
        [CONFIGURATIONS [Debug|Release|...]]
        [COMPONENT <component>] [EXCLUDE_FROM_ALL]
        [FILES_MATCHING]
        [[PATTERN <pattern> | REGEX <regex>]
         [EXCLUDE] [PERMISSIONS permissions...]] [...]) # Installing Directories

install([[SCRIPT <file>] [CODE <code>]]
        [ALL_COMPONENTS | COMPONENT <component>]
        [EXCLUDE_FROM_ALL] [...]) # Custom Installation Logic

install(EXPORT <export-name> DESTINATION <dir>
        [NAMESPACE <namespace>] [FILE <name>.cmake]
        [PERMISSIONS permissions...]
        [CONFIGURATIONS [Debug|Release|...]
        [CXX_MODULES_DIRECTORY <directory>]
        [EXPORT_LINK_INTERFACE_LIBRARIES]
        [COMPONENT <component>]
        [EXCLUDE_FROM_ALL])
install(EXPORT_android_MK <export-name> DESTINATION <dir> [...]) # Installing Exports

install(RUNTIME_DEPENDENCY_SET <set-name>
        [[LIBRARY|RUNTIME|FRAMEWORK]
         [DESTINATION <dir>]
         [PERMISSIONS permissions...]
         [CONFIGURATIONS [Debug|Release|...]]
         [COMPONENT <component>]
         [NAMELINK_COMPONENT <component>]
         [OPTIONAL] [EXCLUDE_FROM_ALL]
        ] [...]
        [PRE_INCLUDE_REGEXES regexes...]
        [PRE_EXCLUDE_REGEXES regexes...]
        [POST_INCLUDE_REGEXES regexes...]
        [POST_EXCLUDE_REGEXES regexes...]
        [POST_INCLUDE_FILES files...]
        [POST_EXCLUDE_FILES files...]
        [DIRECTORIES directories...]) # Installing Runtime Dependencies

      此命令为project生成安装规则。在安装期间按顺序执行在源目录中调用install命令指定的安装规则
      环境变量CMAKE_INSTALL_MODE可以覆盖install命令的默认拷贝行为。
      此命令有多个签名。其中一些定义了file和target的安装选项。此处涵盖了多个签名共有的选项,但它们仅对指定它们的签名有效。共有的选项:
      (1).DESTINATION:指定要安装文件的磁盘目录。参数可以是相对或绝对路径。
      如果给出了相对路径,则相对于CMAKE_INSTALL_PREFIX变量的值进行解释。可以使用CMAKE_INSTALL_PREFIX变量文档中解释的DESTDIR机制在安装时重新定位前缀。
      如果给出了绝对路径(带有前导斜杠或驱动器号),则逐字使用(it is used verbatim).
      由于cpack安装程序生成器不支持绝对路径,因此最好始终使用相对路径。
      (2).PERMISSIONS:指定安装文件的权限。有效权限是OWNER_READ, OWNER_WRITE, OWNER_EXECUTE, GROUP_READ, GROUP_WRITE, GROUP_EXECUTE, WORLD_READ, WORLD_WRITE, WORLD_EXECUTE, SETUID和SETGID。在某些平台上没有意义的权限将在那些平台上会被忽略。
      (3).CONFIGURATIONS:指定安装规则适用的构建配置列表(Debug, Release等)。注意:为此选项指定的值仅适用于在CONFIGURATIONS 选项之后列出的选项。
      注意:CONFIGURATIONS出现在RUNTIME DESTINATION之前。
      (4).COMPONENT:指定与安装规则关联的安装组件名称,例如Runtime或Development。在特定于组件的安装期间,只会执行与给定组件名称关联的安装规则。在完整安装过程中,所有组件都会安装,除非标有EXCLUDE_FROM_ALL。如果未提供COMPONENT,则会创建默认组件"Unspecified"。可以使用CMAKE_INSTALL_DEFAULT_COMPONENT_NAME变量控制默认组件名称。
      (5).EXCLUDE_FROM_ALL:指定该文件从完整安装中排除,仅作为特定组件安装的一部分安装。
      (6).RENAME:为安装的文件指定一个名称,该名称可能与原始文件不同。只有在命令安装单个文件时才允许重命名。
      (7).OPTIONAL:指定如果要安装的文件不存在,则不报错(it is not an error).
      安装文件的命令签名可能会在安装期间打印消息。使用CMAKE_INSTALL_MESSAGE变量控制打印哪些消息.
      许多install命令变体隐式创建包含已安装文件的目录。如果设置了CMAKE_INSTALL_DEFAULT_DIRECTORY_PERMISSIONS,将使用指定的权限创建这些目录。否则,它们将根据类Unix平台上的uname规则创建。Windows平台不受影响。

      1.Installing Targets:TARGETS形式指定从project安装target的规则。可以安装多种target输出工件(Output Artifacts):
      (1).ARCHIVE:包括静态库、DLL导入库。
      (2).LIBRARY:包括共享库(Shared libraries)。
      (3).RUNTIME:包括可执行文件、DLL。
      (4).OBJECTS:与object库关联的object文件。
      (5).FRAMEWORK:标有FRAMEWORK属性的静态库和共享库。
      (6).BUNDLE:标有MACOSX_BUNDLE属性的可执行文件在macOS上被视为BUNDLE targets。
      (7).PUBLIC_HEADER:在非Apple平台上,与库关联的所有PUBLIC_HEADER文件都安装在PUBLIC_HEADER参数指定的目标中。对于Apple平台上的FRAMEWORK库,将忽略此参数定义的规则。
      (8).PRIVATE_HEADER:类似于PUBLIC_HEADER,但用于PRIVATE_HEADER文件.
      (9).RESOURCE:与PUBLIC_HEADER和PRIVATE_HEADER类似,但用于RESOURCE文件.
      (10).FILE_SET <set>:文件集由target_sources(FILE_SET)命令定义。如果文件集<set>存在并且是PUBLIC或INTERFACE,则该集中的所有文件都安装在目标(destination)下。
      (11).CXX_MODULES_BMI:实验性的。
      (12).NAMELINK_COMPONENT:在某些平台上,版本化的共享库具有符号链接。
      (13).NAMELINK_ONLY:安装库target时,此选项会导致仅安装名称链接(namelink).在LIBRARY块之外使用此参数是错误的。
      (14).NAMELINK_SKIP:类似于NAMELINK_ONLY,但效果相反,在安装库target时,它会导致安装名称链接以外的库文件。当NAMELINK_ONLY和NAMELINK_SKIP都没有给出时,这两个部分都会被安装。在LIBRARY块之外使用此参数是错误的。
      (15).EXPORT:此选项将已安装的target文件与名为<export-name>的导出相关联。它必须出现在任何target选项之前。要实际安装导出文件本身,请调用install(EXPORT)。
      (16).INCLUDES_DESTINATION:此选项指定目录列表,当通过install(EXPORT)命令导出时,这些目录将被添加到<targets>的INTERFACE_INCLUDE_DIRECTORIES target属性中。
      (17).RUNTIME_DEPENDENCY_SET:此选项会导致将已安装的可执行文件、共享库和模块target的所有运行时依赖项添加到指定的运行时依赖项集中。然后可以使用install(RUNTIME_DEPENDENCY_SET)命令安装此集。
      此关键字和RUNTIME_DEPENDENCIES关键字是互斥的。
(18).RUNTIME_DEPENDENCIES:此选项会导致已安装的可执行文件、共享库和模块target的所有运行时依赖项与target本身一起安装。
      该RUNTIME_DEPENDENCIES和RUNTIME_DEPENDENCY_SET关键字是互斥的。

message("CMAKE_INSTALL_PREFIX: $CMAKE_INSTALL_PREFIX") # CMAKE_INSTALL_PREFIX: /usr/local

include(GNUInstallDirs)
message("CMAKE_INSTALL_BINDIR: $CMAKE_INSTALL_BINDIR") # CMAKE_INSTALL_BINDIR: bin
message("CMAKE_INSTALL_LIBDIR: $CMAKE_INSTALL_LIBDIR") # CMAKE_INSTALL_LIBDIR: lib
message("CMAKE_INSTALL_INCLUDEDIR: $CMAKE_INSTALL_INCLUDEDIR") # CMAKE_INSTALL_INCLUDEDIR: include

include_directories($CMAKE_CURRENT_SOURCE_DIR/include)
add_library(add STATIC $CMAKE_CURRENT_SOURCE_DIR/source/add.cpp)
install(TARGETS add DESTINATION $CMAKE_CURRENT_SOURCE_DIR/install/$CMAKE_INSTALL_LIBDIR) # -- Installing: /home/spring/GitHub/Linux_Code_Test/Samples_CMake/messy_usage/install/lib/libadd.a

      2.Installing Imported Runtime Artifacts:该IMPORTED_RUNTIME_ARTIFACTS形式指定安装导入target的运行时工件(runtime artifacts)的规则。如果project想在安装中捆绑外部可执行文件或模块,则可以这样做。LIBRARY、RUNTIME、FRAMEWORK和BUNDLE参数具有与它们在TARGETS模式中相同的语义。

      3.Installing Files:如果安装头文件,请考虑使用target_sources(FILE_SET)定义的文件集。文件集将头文件与target相关联,并将它们作为target的一部分安装。
      FILES形式指定了为project安装files的规则。相对路径给出的文件名将根据当前源目录进行解释。默认情况下,如果没有给出PERMISSIONS参数,则此形式安装的文件具有OWNER_WRITE, OWNER_READ, GROUP_READ和WORLD_READ权限。
      PROGRAMS形式与FILES形式相同,不同之处是安装文件的默认权限还包括OWNER_EXECUTE, GROUP_EXECUTE和WORLD_EXECUTE。此形式用于安装非target程序,例如shell脚本。
      FILES或PROGRAMS的files...可以使用语法为$<...>的"生成器表达式".
      必须提供TYPE或DESTINATION中的一个,但不能同时提供两个。TYPE参数指定要安装的文件的通用文件类型.然后,通过从GNUInstallDirs中获取相应的变量来自动设置目的地(destination),或者如果未定义该变量,则使用内置的默认值.

install(FILES CMakeLists.txt DESTINATION $CMAKE_CURRENT_SOURCE_DIR/install) # -- Installing: /home/spring/GitHub/Linux_Code_Test/Samples_CMake/messy_usage/install/CMakeLists.txt
install(PROGRAMS build.sh DESTINATION $CMAKE_CURRENT_SOURCE_DIR/install) # -- Installing: /home/spring/GitHub/Linux_Code_Test/Samples_CMake/messy_usage/install/build.sh

      4.Installing Directories:要安装头(headers)的目录子树(directory sub-tree),请考虑使用target_sources(FILE_SET)定义的文件集。文件集不仅保留目录结构,它们还将头与target相关联并作为target的一部分安装。
      DIRECTORY形式安装一个或多个目录的内容到给定的目的地(given destination)。目录结构被一字不差地复制到目的位置(destination)。相对路径给出的目录名是根据当前源目录进行解释的。如果未提供输入目录名,则将创建目的目录,但不会安装任何内容。FILE_PERMISSIONS和 DIRECTORY_PERMISSIONS选项指定给在目的地文件和目录的权限。
      可以使用PATTERN或REGEX选项以细粒度控制目录的安装
      某些选项可能遵循string(REGEX)下所述的PATTERN或REGEX表达式,并且仅应用于与之匹配的文件或目录。EXCLUDE选项将跳过(skip)匹配的文件或目录。PERMISSIONS选项覆盖(override)匹配的文件或目录权限设置。
      必须提供TYPE或DESTINATION中的一个,但不能同时提供两个。TYPE参数指定要安装的目录的通用文件类型.然后,通过从GNUInstallDirs中获取相应的变量来自动设置目的地(destination),或者如果未定义该变量,则使用内置的默认值.

# 注意以下两条语句的差异及执行结果的不同
install(DIRECTORY include DESTINATION $CMAKE_CURRENT_SOURCE_DIR/install FILES_MATCHING PATTERN "*.in") # -- Installing: /home/spring/GitHub/Linux_Code_Test/Samples_CMake/messy_usage/install/include/foo.h.in
install(DIRECTORY include/ DESTINATION $CMAKE_CURRENT_SOURCE_DIR/install FILES_MATCHING PATTERN "*.in") # -- Installing: /home/spring/GitHub/Linux_Code_Test/Samples_CMake/messy_usage/install/foo.h.in

# install/source下文件的权限将被修改,install/include下文件的权限保持不变
install(DIRECTORY include source DESTINATION $CMAKE_CURRENT_SOURCE_DIR/install
    PATTERN "*.in" EXCLUDE
    PATTERN "source/*" PERMISSIONS OWNER_EXECUTE OWNER_WRITE OWNER_READ GROUP_EXECUTE GROUP_READ)

      5.Custom Installation Logic:SCRIPT形式将在安装期间调用给定的CMake脚本文件。如果脚本文件名是相对路径,它将根据当前源目录进行解释。CODE形式在安装期间调用给定的CMake code。Code被指定为双引号字符串中的单个参数。

# print a message during installation
install(CODE "MESSAGE(WARNING \\"Sample install message.\\")") # CMake Warning at cmake_install.cmake:46 (MESSAGE):
                                                                #   Sample install message.

      6.Installing Exports:EXPORT形式生成并安装一个CMake文件,其中包含从安装树到另一个project的导入target的代码(The EXPORT form generates and installs a CMake file containing code to import targets from the installation tree into another project)。当target名写入导入文件时,NAMESPACE选项将在target名前加上<namespace>。默认情况下,生成的文件名为<export-name>.cmake,但FILE选项可用于指定不同的名。FILE选项的值必须是扩展名为.cmake的文件名。
      安装的<export-name>.cmake文件可能会附带额外配置的<export-name>-*.cmake文件,以便通过globbing加载。请勿将与包名称相同的导出名与安装<package-name>-config.cmake文件一起使用。
      EXPORT形式有助于外部project使用当前project构建和安装的target.

include_directories($CMAKE_CURRENT_SOURCE_DIR/include)
add_library(add STATIC $CMAKE_CURRENT_SOURCE_DIR/source/add.cpp)
install(TARGETS add EXPORT myproj DESTINATION $CMAKE_CURRENT_SOURCE_DIR/install)
# 将会在install/myproj目录下生成myproj.cmake和myproj-noconfig.cmake
install(EXPORT myproj NAMESPACE mp_ DESTINATION $CMAKE_CURRENT_SOURCE_DIR/install/myproj)

      7.Installing Runtime Dependencies:安装以前由一个或多个install(TARGETS)或install(IMPORTED_RUNTIME_ARTIFACTS)命令创建的运行时依赖集。属于运行时依赖集的target的依赖项在 DLL平台上安装在RUNTIME目的地和组件(destination and component)中,在非DLL平台上的安装在LIBRARY目的地和组件中。macOS框架安装在FRAMEWORK目的地和组件中。在构建树中构建的target永远不会作为运行时依赖项安装,它们自己的依赖项也不会安装,除非target本身是使用install(TARGETS)安装的。

      8.Generated Installation Script:不建议使用此功能。考虑改用cmake --install

      执行测试代码需要多个文件

      build.sh内容如下:

#! /bin/bash

# supported input parameters(cmake commands)
params=(function macro cmake_parse_arguments \\
		find_library find_path find_file find_program find_package \\
		cmake_policy cmake_minimum_required project include \\
		string list set foreach message option if while return \\
		math file configure_file \\
		include_directories add_executable add_library target_link_libraries install)

usage()

	echo "Error: $0 needs to have an input parameter"

	echo "supported input parameters:"
	for param in $params[@]; do
		echo "  $0 $param"
	done

	exit -1


if [ $# != 1 ]; then
	usage
fi

flag=0
for param in $params[@]; do
	if [ $1 == $param ]; then
		flag=1
		break
	fi
done

if [ $flag == 0 ]; then
	echo "Error: parameter \\"$1\\" is not supported"
	usage
	exit -1
fi

if [[ ! -d "build" ]]; then
	mkdir build
	cd build
else
	cd build
fi

echo "==== test $1 ===="

# test_set.cmake: cmake -DTEST_CMAKE_FEATURE=$1 --log-level=verbose ..
# test_option.cmake: cmake -DTEST_CMAKE_FEATURE=$1 -DBUILD_PYTORCH=ON ..
cmake -DTEST_CMAKE_FEATURE=$1 ..
# It can be executed directly on the terminal, no need to execute build.sh, for example: cmake -P test_set.cmake
make
make install # only used in cmake files with install command

      CMakeLists.txt内容如下:

cmake_minimum_required(VERSION 3.22)
project(cmake_feature_usage)

message("#### current cmake version: $CMAKE_MAJOR_VERSION.$CMAKE_MINOR_VERSION.$CMAKE_PATCH_VERSION")
include(test_$TEST_CMAKE_FEATURE.cmake)
message("==== test finish ====")

      test_install.cmake内容为上面的所有测试代码段。

      另外还包括三个目录:include,source,samples,它们都是非常简单的实现,仅用于测试,如下:

      可能的执行结果如下图所示: 

 

      GitHub: https://github.com/fengbingchun/Linux_Code_Test

以上是关于CMake中install的使用的主要内容,如果未能解决你的问题,请参考以下文章

CMAKE设置INSTALL工程,分别设置头文件Lib和DLL的输出路径

CMAKE_INSTALL_PREFIX 的介子等价物是啥?

如何使用多个目录设置 CMAKE_INSTALL_RPATH?

是否可以在 postinst 中读取 CMAKE_INSTALL_PREFIX 变量的值?

如何在Windows开发环境中用CMake改变CMAKE_INSTALL_PREFIX的值?

cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local ..