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