目录
1.CMAKE_ARCHIVE_OUTPUT_DIRECTORY
2.CMAKE_LIBRARY_OUTPUT_DIRECTORY
3.CMAKE_RUNTIME_OUTPUT_DIRECTORY
一、输出目录
可执行文件总是被作为RUNTIME target,静态库总是被作为ARCHIVE target,Module库总是被作为LIBRARY target。
在windows端,shared library的DLL部分作为RUNTIME target,Import library的DLL部分作为ARCHIVE target。
1.CMAKE_ARCHIVE_OUTPUT_DIRECTORY
存放构建时的所有归档目标文件。
2.CMAKE_LIBRARY_OUTPUT_DIRECTORY
存放构建时的所有库目标文件。
3.CMAKE_RUNTIME_OUTPUT_DIRECTORY
存放构建时的所有运行时目标文件。
二、GNUInstallDirs.cmake模块
使用 GNUInstallDirs.cmake 定义目标安装的标准位置。
GNUInstallDirs.cmake模块定义了一组变量,这些变量是安装不同类型文件的子目录的名称,有助于将已安装的文件放置到所选安装前缀的子目录中。
- CMAKE_INSTALL_BINDIR:这将用于定义用户可执行文件所在的子目录,即所选安装目录下的 bin 目录。
- CMAKE_INSTALL_LIBDIR:这将扩展到目标代码库(即静态库和动态库)所在的子目录。在64位系统上,它是 lib64 ,而在32位系统上,它只是 lib 。
- CMAKE_INSTALL_INCLUDEDIR:使用这个变量为头文件获取正确的子目录,该变量为 include。
include(GNUInstallDirs)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_LIBDIR})
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${PROJECT_BINARY_DIR}/${CMAKE_INSTALL_BINDIR})
三、file(TO_NATIVE_PATH "<path>" <variable>)
TO_NATIVE_PATH模式将cmake样式<PATH>转换为带有特定于平台的斜杠的本机路径(在Windows平台为\;其他平台为/),存储在<variable>中。
扩展:
file(TO_CMAKE_PATH "<path>" <variable>)
TO_CMAKE_PATH模式将本机<PATH>转换为带有正斜杠(/)的CMAKE样式路径,存储在<variable>中。输入可以是单个路径,也可以是系统搜索路径,比如$ENV{path}。搜索路径将转换为cmake样式列表,以;分隔。
注意:两个模式中,在<path>周围使用双引号可以确保它被视为此命令的单个参数。
foreach(p LIB BIN INCLUDE CMAKE)
file(TO_NATIVE_PATH ${CMAKE_INSTALL_PREFIX}/${INSTALL_${p}DIR} _path )
message(STATUS "Installing ${p} components to ${_path}")
unset(_path)
endforeach()
#message输出:
# Installing LIB components to C:\Program Files (x86)\recipe-01\lib
# Installing BIN components to C:\Program Files (x86)\recipe-01\bin
# Installing INCLUDE components to C:\Program Files (x86)\recipe-01\include
# Installing CMAKE components to C:\Program Files (x86)\recipe-01\CMake
四、file(RELATIVE_PATH <variable> <directory> <file>)
计算从<directory>到<file>的相对路径,并将其存储在<variable>中。
file(RELATIVE_PATH _rel ${CMAKE_INSTALL_PREFIX}/${INSTALL_BINDIR} ${CMAKE_INSTALL_PREFIX})
五、set_target_properties
set_target_properties函数的含义可参考该文章,属性值可参考该文章。
set_target_properties(message-shared
PROPERTIES
POSITION_INDEPENDENT_CODE 1 #设置生成位置无关代码所需的编译器标志
SOVERSION ${PROJECT_VERSION_MAJOR}
OUTPUT_NAME "message" #CMake库的名称:message
DEBUG_POSTFIX "_d" #如果我们以Debug配置构建项目,则将_d后缀添加到生成的动态库
PUBLIC_HEADER "Message.hpp"
MACOSX_RPATH ON
WINDOWS_EXPORT_ALL_SYMBOLS ON #强制在Windows上编译以导出所有符号
)
五、RPATH
Linux的可执行文件包括共享对象库文件里面有一个标记,叫做rpath,它是运行时库的搜索目录。换而言之rpath能告诉Linux当执行这个文件的时候如果需要加载其它的共享对象库要去哪个目录下找。(windows下一个程序的dll搜索路径首先是程序目录,然后是一些系统目录)
Cmake默认把rpath设置成构建时生成的共享对象库的绝对路径,而不是安装后的共享对象库的路径。这样直接执行在构建目录中的可执行程序是没问题的,但是安装在特定路径后加载的还是构建目录中的共享对象库,如果构建目录被删除程序就执行不了了。
Cmake有一个参数,CMAKE_INSTALL_RPATH,它可以改写安装的可执行程序和共享对象库的rpath。
1.CMAKE_INSTALL_RPATH
这用于初始化所有目标的目标属性INSTALL_RPATH。
2.INSTALL_RPATH
以分号分隔的列表,指定要在已安装目标中使用的rpath(对于支持它的平台)。如果在创建目标时设置了变量CMAKE_INSTALL_RPATH,则该属性由CMAKE_INSTALL_RPATH变量的值初始化。
file(RELATIVE_PATH _rel ${CMAKE_INSTALL_PREFIX}/${INSTALL_BINDIR} ${CMAKE_INSTALL_PREFIX})
#查找与可执行文件本身位置相关的路径
if(APPLE)
set(_rpath "@loader_path/${_rel}")
else()
set(_rpath "\$ORIGIN/${_rel}")
endif()
file(TO_NATIVE_PATH "${_rpath}/${INSTALL_LIBDIR}" message_RPATH)
#设置可执行目标 hello-world_wDSO 的 RPATH
set_target_properties(hello-world_wDSO
PROPERTIES
MACOSX_RPATH ON
SKIP_BUILD_RPATH OFF #告诉CMake生成适当的 RPATH ,以便能够在构建树中运行可执行文件。
BUILD_WITH_INSTALL_RPATH OFF #关闭生成可执行目标,使其 RPATH 调整为与安装树的 RPATH 相同。在构建树中不运行可执行文件。
INSTALL_RPATH "${message_RPATH}"#将已安装的可执行目标的 RPATH 设置为先前的路径。
INSTALL_RPATH_USE_LINK_PATH ON #告诉CMake将链接器搜索路径附加到可执行文件的 RPATH 中。
)
六、install
此命令生成项目的安装规则。在源目录中调用Install()命令指定的安装规则在安装过程中按顺序执行。install命令有多个签名。其中一些定义了文件和目标的安装选项。我们先介绍一些常见选项,它们仅对指定它们的签名有效。
1.常见选项
(1)DESTINATION
指定将安装文件的磁盘目录。参数可以是相对路径或绝对路径。
- 如果给出了相对路径(推荐),则会根据CMAKE_INSTALL_PREFIX变量的值来解释它。可以在安装时使用CMAKE_install_prefix变量文档中介绍的DESTDIR机制重新定位前缀。
- 如果给出了绝对路径(带前导斜杠或驱动器号),则会逐字使用。
(2)PERMISSIONS
指定已安装文件的权限。有效权限包括OWNER_READ, OWNER_WRITE, OWNER_EXECUTE, GROUP_READ, GROUP_WRITE, GROUP_EXECUTE, WORLD_READ, WORLD_WRITE, WORLD_EXECUTE, SETUID和SETGID。在某些平台上没有意义的权限会被忽略。
(3)CONFIGURATIONS
指定安装规则适用的生成配置列表(调试、发布等)。请注意,为该选项指定的值仅适用于“配置”选项之后列出的选项。
(4)COMPONENT
指定与安装规则关联的安装组件名称,例如“runtime”或“development”。
(5)EXCLUDE_FROM_ALL
指定从完整安装中排除该文件,并且仅作为特定于组件的安装的一部分进行安装。
(6)RENAME
为安装的文件指定可能与原始文件不同的名称。仅当命令安装了单个文件时才允许重命名。
(7)OPTIONAL
允许安装的文件不存在。
2.install(TARGET<target>... [...])
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>] [DESTINATION <dir>] [PERMISSIONS permissions...] [CONFIGURATIONS [Debug|Release|...]] [COMPONENT <component>] [NAMELINK_COMPONENT <component>] [OPTIONAL] [EXCLUDE_FROM_ALL] [NAMELINK_ONLY|NAMELINK_SKIP] ] [...] [INCLUDES DESTINATION [<dir> ...]] )
参数中的
TARGET
可以是很多种目标文件,最常见的是通过ADD_EXECUTABLE或者ADD_LIBRARY定义的目标文件,即可执行二进制、动态库、静态库。
具体参数可参考:install — CMake 3.23.0-rc3 Documentation
install(
TARGETS
message-shared #动态库
hello-world_wDSO #可执行文件
ARCHIVE
DESTINATION ${INSTALL_LIBDIR}
COMPONENT lib
RUNTIME
DESTINATION ${INSTALL_BINDIR}
COMPONENT bin
LIBRARY
DESTINATION ${INSTALL_LIBDIR}
COMPONENT lib
PUBLIC_HEADER
DESTINATION ${INSTALL_INCLUDEDIR}/message
COMPONENT dev
)