本篇文章不是新手入门教学文章,主要是记录笔者个人的学习笔记
CMake入门(五)
- 一、打包
- 二、使用CMake管理库
- 三、打包调试版和发行版
一、打包
发布程序可以有多种形式,比如安装包、压缩包、源文件等。CMake也提供了打包程序cpack
可将程序打包成多种形式。
在Windows上默认情况会打包成.exe文件,所以需要先安装一个exe打包程序
NSIS
(Null Soft Installer)
- NSIS下载地址:https://sourceforge.net/projects/nsis/
只需要在顶层CMakelists.txt
最后添加以下代码
include(InstallRequiredSystemLibraries)
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/License.txt")
set(CPACK_PACKAGE_VERSION_MAJOR "${Tutorial_VERSION_MAJOR}")
set(CPACK_PACKAGE_VERSION_MINOR "${Tutorial_VERSION_MINOR}")
# 设置打包的方式
set(CPACK_SOURCE_GENERATOR "TGZ")
include(CPack)
include(CPack)
会在构建路径(Build tree)下生成两个cpack的配置文件,CPackConfig.cmake
和CPackSourceConfig.cmake
,其实也就对应了两个构建目标:package
和package_source
;
关于打包的方式可以使用下面的命令查看
cpack --help
在项目构建完成之后,可以直接执行
cpack
也可以指定生成器打包成对应的格式
cpack -G ZIP # 打包成ZIP
对于多配置项目,可以指定打包配置
cpack -C Debug # 打包Debug版本
也可以打包源代码
cpack --config CPackSourceConfig.cmake
二、使用CMake管理库
我们先来看一下在CMake中使用第三方库的方法,MathFunctions
的库文件、头文件在其他路径当中,这时库的引入方式如下:
# CMakeLists.txt
cmake_minimum_required(VERSION 3.10)
project(Tutorial)
add_executable(Tutorial tutorial.cxx)
set(mathlib_DIR C:/Users/YAN/Desktop/cmake/mathlib)
# cmake中使用第三方库的一般步骤
# 1. 设置头文件位置
target_include_directories(Tutorial PRIVATE "${mathlib_DIR}/include")
# 2. 设置库文件搜索位置
target_link_directories(Tutorial PRIVATE "${mathlib_DIR}/lib")
# 3. 指定需要链接的库(libXXX.a libXXX.dll直接写成XXX的形式即可)
target_link_libraries(Tutorial PRIVATE MathFunctions)
现在的问题是,如果一个库不用CMake管理,那就是用如上方法来引用,可是这个库也是由CMake构建来的,还用同样的方法来引入,那CMake不是白用了吗?
用CMake管理简化后的版本为:
cmake_minimum_required(VERSION 3.10)
project(Tutorial)
add_executable(Tutorial tutorial.cxx)
# 如果库是安装在环境变量里有的位置,这行可以不用写
set(MathFunctions_DIR C:/Users/YAN/Desktop/cmake/mathlib/lib/cmake/MathFunctions)
# 第一个参数是库名称 第二个参数表名这个库是必须的
find_package(MathFunctions REQUIRED)
target_link_libraries(Tutorial PRIVATE MathFunctions)
可以看出使用CMake管理库之后,我们对库的使用也会更加方便,所以本节内容为如何导出一个用CMake管理的库。
- 给目标安装添加导出
install(TARGETS ${installable_libs}
EXPORT <导出的文件名>
DESTINATION lib)
EXPORT
可以生成一个导出的文件名.cmake
的文件,这里面描述了此处安装的这些目标的一些导出配置
- 要让导出文件配置的路径对其他项目也可用,而不是绑定当前项目路径,需要修改头文件搜索路径,构建时和安装后为不同值
target_include_directories(MathFunctions
INTERFACE
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
$<INSTALL_INTERFACE:include>
)
BUILD_INTERFACE
和 INSTALL_INTERFACE
一种生成器表达式中的值。
BUILD_INTERFACE
:这个表达式在构建阶段(也就是你在电脑上编译代码的时候)生效。INSTALL_INTERFACE
:这个表达式在安装阶段(也就是你运行cmake --install .
的时候)生效。
- 将第一步生成的
导出的文件名.cmake
文件安装
install(EXPORT <导出文件名>
FILE <导出文件名>.cmake
DESTINATION <依赖的目标>
)
- 在库级别的CMakeLists.txt目录下准备一个<库名>Config.cmake.in文件模板
用CMake管理的库需要用find_package
进行导入,为了让find_package
能正确找到对应的库,需要再准备一个<库名>Config.cmake
文件,通常由模板生成,模板格式固定,内容如下
@PACKAGE_INIT@
include("${CMAKE_CURRENT_LIST_DIR}/第一步导出的文件名.cmake" )
由configure_package_config_file
根据模板生成<库名>Config.cmake
文件。
然后在库级别的CMakeLists.txt
添加下面的代码:
include(CMakePackageConfigHelpers)
configure_package_config_file(${CMAKE_CURRENT_SOURCE_DIR}/<库名>Config.cmake.in
"${CMAKE_CURRENT_BINARY_DIR}/<库名>Config.cmake"
INSTALL_DESTINATION "lib/cmake/<库名>"
NO_SET_AND_CHECK_MACRO
NO_CHECK_REQUIRED_COMPONENTS_MACRO
)
- 生成版本文件(非必需)
在库级别的CMakeLists.txt
添加下面的代码:
write_basic_package_version_file(
"${CMAKE_CURRENT_BINARY_DIR}/<库名>ConfigVersion.cmake"
VERSION "${<项目名>_VERSION_MAJOR}.${<项目名>_VERSION_MINOR}"
COMPATIBILITY AnyNewerVersion
)
- 安装生成文件
在库级别的CMakeLists.txt
添加下面的代码:
install(FILES
${CMAKE_CURRENT_BINARY_DIR}/<库名>Config.cmake
${CMAKE_CURRENT_BINARY_DIR}/<库名>ConfigVersion.cmake
DESTINATION lib/cmake/<库名>
)
上面这样设置好以后,我们在使用上面CMake管理的库时,就很方便了,下面是一个示例:
假设我们对库MathFunctions
进行了上面的配置,那么我们在使用这个库时就可以按照下面的方式来使用。
cmake_minimum_required(VERSION 3.15)
project(Tutorial)
# 指定库的路径 后面的路径就是上面的设置形成以后,配置文件的生成路径
set(MathFunctions_DIR /home/pan/cmake-learing/Step11/install/lib/cmake/MathFunctions/)
# 引入库
find_package(MathFunctions REQUIRED)
# 生成可执行程序
add_executable(Tutorial tutorial.cxx)
# 连接可执行程序
target_link_libraries(Tutorial PRIVATE MathFunctions)
三、打包调试版和发行版
下面示例只针对单配置生成器,对多配置生成器(如Visual Studio)不生效。
CMake一个构建目录只能有一种配置,分别为Debug
,Release
,MinSizeRel
,RelWithDebInfo
。
对于需要指定的不同版本,只需要在配置时指明即可。
# 指定生成器、配置为Release版本
cmake -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release ..
如果需要让Debug版本生成的目标名称与Release版本不同,可以使用CMAKE_DEBUG_POSTFIX
为Debug版设置后缀。
set(CMAKE_DEBUG_POSTFIX d)
add_executable(Tutorial tutorial.cxx)
set_target_properties(Tutorial PROPERTIES DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
这样一来该目标及其依赖的目标生成的文件都会带有后缀d
。
通常来说会把Debug版与Release版分别放入两个debug
和release
目录中。如果只需要打包一版本,到对应目录中直接运行cpack
即可。如果需要同时打包两个版本的内容,则在debug
和release
同级目录下新建一个MultiCPackConfig.cmake
文件,内容如下:
include("release/CPackConfig.cmake")
set(CPACK_INSTALL_CMAKE_PROJECTS
"debug;可执行文件;库名;/"
"release;可执行文件;ALL;/"
)
CPACK_INSTALL_CMAKE_PROJECTS
用来指定要打包的内容,可以有多项,每一项里有4部分内容,分别为
- 项目路径:指定要打包的项目所在的路径
- 项目名称:指定要打包的项目的名称
- 安装组件:指定要打包的项目的安装组件。可以是ALL(所有组件)、DEFAULT(默认组件)或者是一个具体的组件名称
- 安装路径:指定要打包的项目的安装路径(相对整打包好的整个目录来说的)
完成之后在本目录下执行
cpack --config MultiCPackConfig.cmake
即可打包配置好的内容。