使用CMake的CPack工具打包项目

news2024/12/24 8:43:38

为了介绍如何使用CMake的CPack工具进行项目打包,这里使用了前文CMake项目使用ctest+gtest进行单元测试中的示例。

为了更接近实际开发中项目的情况,自行下载gtest并进行源码编译来模拟实际项目中的依赖项;在实际的开发中,可能会有各种各样的配置文件需要在打包的时候一起发布出去,这里在根目录下创建一个bin目录(将所有项目生成的文件全部指定生成到此目录下的各个项目目录中),下面再创建一个demo目录(根据项目来取名),在demo目录中创建一个config.ini文件。
在这里插入图片描述

根目录的CMakeLists.txt如下:

cmake_minimum_required(VERSION 3.12.0)
project(demo VERSION 0.1.0)

# 这里不管系统有没安装GTest都从网络上下载源码进行编译,使用自己编译的GTest
cmake_policy(SET CMP0135 NEW)
message("download GTest...")
include(FetchContent)
FetchContent_Declare(googletest URL https://github.com/google/googletest/archive/refs/heads/main.zip)
FetchContent_MakeAvailable(googletest)

include(CTest)

enable_testing()
#设置编译后的可执行文件存放路径
set(BIN_DIR ${CMAKE_CURRENT_SOURCE_DIR}/bin)

add_subdirectory(test)

# 根据项目存放到以项目名命名的目录中
set(EXECUTABLE_OUTPUT_PATH ${BIN_DIR}/${PROJECT_NAME})
add_executable(${PROJECT_NAME} main.cpp)

# 设置需要安装的文件
install(DIRECTORY ${BIN_DIR}
	DESTINATION ./
	FILES_MATCHING
	PATTERN "*.exe"
	PATTERN "*.ini"
)

# 设置包的模式,可以是7Z、ZIP等等,参见cpack --help
set(CPACK_GENERATOR 7Z)
include(CPack)

为了让各个项目都将编译后的可执行文件按指定要求存放,需要在每个子项目中(project后)添加如下指令:set(EXECUTABLE_OUTPUT_PATH ${BIN_DIR}/${PROJECT_NAME})

本例中需要在test目录中修改CMakeLists.txt

project(t)

set(EXECUTABLE_OUTPUT_PATH ${BIN_DIR}/${PROJECT_NAME})

add_executable(${PROJECT_NAME} test.cpp ../func.cpp)
target_link_libraries(${PROJECT_NAME} PRIVATE gtest gtest_main)

include(GoogleTest)
gtest_discover_tests(t)

然后设置需要安装的文件,根据前面的设定,这里使用目录的方式设定安装文件:

install(DIRECTORY ${BIN_DIR}
	DESTINATION ./
	FILES_MATCHING
	PATTERN "*.exe"
	PATTERN "*.ini"
)

即将所有输出目录中的exe文件以及ini文件打包。

此时编译后的目录结构如下:
在这里插入图片描述
在build目录(有CMakeCache.txt的目录),运行cpack,即可得到打包后的文件,笔者的为demo-0.1.0-win64.7z

可以在build_CPack_Packages\win64\7Z\demo-0.1.0-win64查看打包的情况,这里有额外的include与lib,并不是想要的,是因为使用的GTest为自行编译的库,如果不想让它们出现在包中,可以在引入GTest之前设置INSTALL_GTESTOFF

在这里插入图片描述

现在很多项目都是使用的Git来管理项目,可以在打包的时候以Git的分支名时期时间,SHA组合的方式来命名包。

在根CMakeLists.txt中的install指令前添加如下指令:

string(TIMESTAMP vTimeStamp "%Y%m%d%H%M%S")
execute_process(
	COMMAND git log -1 --format=%h
	WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
	OUTPUT_VARIABLE vGitCommit
	OUTPUT_STRIP_TRAILING_WHITESPACE
)

execute_process(
	COMMAND git rev-parse --abbrev-ref HEAD
	WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
	OUTPUT_VARIABLE vGitBranch
	OUTPUT_STRIP_TRAILING_WHITESPACE
)

include(CPack)前加上set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${vGitBranch}-${vTimeStamp}-${vGitCommit}")即可。

附上最终根CMakeLists.txt

cmake_minimum_required(VERSION 3.12.0)
project(demo VERSION 0.1.0)

set(INSTALL_GTEST OFF)
cmake_policy(SET CMP0135 NEW)
message("GTest not found, download it...")
include(FetchContent)
FetchContent_Declare(googletest URL https://github.com/google/googletest/archive/refs/heads/main.zip)
FetchContent_MakeAvailable(googletest)
include(CTest)

enable_testing()

set(BIN_DIR ${CMAKE_CURRENT_SOURCE_DIR}/bin)

add_subdirectory(test)

set(EXECUTABLE_OUTPUT_PATH ${BIN_DIR}/${PROJECT_NAME})
add_executable(${PROJECT_NAME} main.cpp)

string(TIMESTAMP vTimeStamp "%Y%m%d%H%M%S")
execute_process(
	COMMAND git log -1 --format=%h
	WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
	OUTPUT_VARIABLE vGitCommit
	OUTPUT_STRIP_TRAILING_WHITESPACE
)

execute_process(
	COMMAND git rev-parse --abbrev-ref HEAD
	WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
	OUTPUT_VARIABLE vGitBranch
	OUTPUT_STRIP_TRAILING_WHITESPACE
)

install(DIRECTORY ${BIN_DIR}
	DESTINATION ./
	FILES_MATCHING
	PATTERN "*.exe"
	PATTERN "*.ini"
)

set(CPACK_GENERATOR 7Z)
set(CPACK_PACKAGE_FILE_NAME "${PROJECT_NAME}-${vGitBranch}-${vTimeStamp}-${vGitCommit}")
include(CPack)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/449446.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

chatgpt智能提效职场办公-ppt怎么压缩文件大小

作者:虚坏叔叔 博客:https://xuhss.com 早餐店不会开到晚上,想吃的人早就来了!😄 压缩PPT文件大小有以下几种方法: 压缩图片大小:在PPT当中,图片是占用存储空间最大的部分&#xff0…

物联网多协议、多场景自定义测试|XMeter Cloud 更新

近日,全球首个物联网 MQTT 负载测试云服务 XMeter Cloud 推出了自定义场景测试功能。 该功能将满足用户自主定义测试场景和测试更广泛协议的需求,实现对除 MQTT 以外的 TCP、WebSocket、HTTP 等其他网络协议的测试,帮助用户构建更复杂的测试…

mybatis模糊查询以及结果封装详解

mybatis模糊查询以及结果封装详解 创建maven项目&#xff1a;项目结构如图所示 准备数据库表&#xff1a; 准备pom.xml所需的依赖&#xff1a; <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0…

程序地址空间(下)

目录 &#xff1a; 1.接上部分内容再谈谈地址空间是什么&#xff1f;&#xff1f; 2.页表MMU&#xff08;硬件设备&#xff09; 3.为什么要搞个虚拟地址映射到物理地址 4.解释为什么最开始的问题&#xff1f;&#xff1f;&#xff1f; ---------------------------------------…

Spring 的 IoC(控制反转)

IoC 是 Inversion of Control 的简写&#xff0c;译为“控制反转”&#xff0c;它不是一门技术&#xff0c;而是一种设计思想&#xff0c;也是一个概念&#xff0c;同时是一个重要的面向对象编程法则&#xff0c;能够指导我们如何设计出松耦合、更优良的程序。 在这里说 IoC 之…

Java ---包装类

&#xff08;一&#xff09;包装类概念 官方说法&#xff1a; Java是面向对象的语言&#xff0c;但是为了便于开发者的使用&#xff0c;Java中却沿用了C语言的基本数据类型&#xff0c;在进行基本的数据计算时&#xff0c;开发者可以直接使用基础类。但是当需要和Java其他对象…

如何理解ThreadLocal

ThreadLocal的基本概念 在并发编程中&#xff0c;多个线程访问同一个变量&#xff0c;可能会出现线程安全问题、为了保证在多线程环境下访问共享变量的安全性&#xff0c;通常在访问共享变量的时候加锁&#xff0c;以实现线程同步的效果。 使用同步锁机制保证多线程访问共享变…

ChatGPT | 一文详解ChatGPT(学习必备)

本文概要 本篇文章主要介绍ChatGPT的产生和使用体验&#xff0c;适合不了解ChatGPT或者了解不够透彻的小伙伴&#xff0c;文中的描述非常详细&#xff0c;干货满满&#xff0c;感兴趣的小伙伴快来一起学习吧&#xff01; &#x1f31f;个人简介 ☀️大家好&#xff01;我是新人…

信息的相关性和冗余度:信息在整个文明中的作用

文章目录 I 古埃及的象形文字1.1 罗塞塔石碑1.2 古埃及文字音节和希腊字母的对应表1.3 破解古埃及文字 I 古埃及的象形文字 1.1 罗塞塔石碑 这个石碑是在公元前196年埃及国王托勒密五世加冕一周年的诏书。 在此前大约一百年&#xff0c;埃及已经被来自希腊北方城邦的亚历山大…

C++------引用

一、 引用概念 引用不是新定义一个变量&#xff0c;而是给已存在变量取了一个别名&#xff0c;编译器不会为引用变量开辟内存空间&#xff0c;它和它引用的变量共用同一块内存空间。 类型& 引用变量名(对象名) 引用实体&#xff1b; int main() {//一个变量可以有多个引用…

LWIP协议与TCP/IP

1. 学习一个东西&#xff0c;先了解这个东西是干什么用的&#xff0c;哪些场景会用到它&#xff0c;与自己已经掌握的其他知识的联系 a. 例如&#xff1a;LWIP这个东西是干什么用的&#xff1a;他就是一个裁剪后保持大部分TCP/IP功能的协议。用少量的资源消耗实现一个较为完整的…

大数据实战 --- 淘宝用户行为数据分析

目录 开发环境 数据描述 功能需求 数据准备 数据清洗 用户行为分析 找出有价值的用户 开发环境 HadoopHiveSparkHBase 启动Hadoop&#xff1a;start-all.sh 启动zookeeper&#xff1a;zkServer.sh start 启动Hive&#xff1a; nohup hiveserver2 1>/dev/null 2>…

从零开始的ChatGLM 配置详细教程

从零开始的ChatGLM配置教程 文章目录 从零开始的ChatGLM配置教程一&#xff0c;前言二&#xff0c;环境配置1、下载ChatGLM项目2、配置程序运行环境 三、在HuggingFace下载chatGLM-6B模型1&#xff0c;安装 Git Lfs2&#xff0c;下载相关文件3&#xff0c;在HuggingFace中下载相…

什么是隔离放大器

隔离放大器&#xff08;也称为单位增益放大器&#xff09;是一种提供隔离的运算放大器电路电路的一部分与另一部分电路不同&#xff0c;这样就不会在电路的一部分中使用、消耗或浪费功率。 现在将对此进行彻底解释&#xff0c;因为这乍一看似乎是一个令人生畏的话题&#xff0c…

【TCP Wrappers】

目录 一、保护原理二、TCP Wrappers 保护机制的两种方式三、TCP Wrappers 的访问策略四、TCP Wrappers 机制的基本原则1、允许所有&#xff0c;拒绝个别2、允许个别&#xff0c;拒绝所有实列 一、保护原理 二、TCP Wrappers 保护机制的两种方式 1.直接使用 tcpd 程序对其他服务…

JavaFx 自定义封装 DateTimePicker 时间选择组件(支持时分秒)

JavaFx DateTimePicker 时间选择组件 javaFx 自定义时间选择组件 DateTimePicker&#xff0c; javaFx 源代码不支持时分秒选择&#xff0c;该代码组件支持时分秒选择&#xff0c;同时也支持清空、取消、此刻等操作&#xff01; 效果如下图所示&#xff1a; 源码地址&#xff…

AXI4总线学习笔记

AXI4 总线是 ARM 公司开发的一种总线&#xff0c;广泛应用于 Xilinx 的 IP 核中&#xff0c;比如笔者近期涉及 DDR 的读写控制&#xff0c;需要用到 MIG IP 核&#xff0c;这个 IP 核就通过 AXI4 总线进行控制。 AXI4 共有 5 种通道&#xff1a;读地址通道 ARC&#xff0c;读数…

虽然音视频开发只是功能组件开发,但薪资远高于普通开发岗……

首先要明白一件事情&#xff0c;音视频开发是功能组件开发而不是应用开发。应用开发的具体需求基本上是定制化的&#xff0c;而且需求一直在改&#xff0c;比如今天加个按钮&#xff0c;明天改个风格&#xff0c;只要应用还在天天都有活干。而功能组件开发的需求大多都比较统一…

一文详解过滤器Filter、拦截器Interceptor和切面Aspect的区别

目录 Filter过滤器 作用 应用场景 拦截器Interceptor Aspect切片 三者对比 执行顺序 拦截层面 过滤器Filter和拦截器Interceptor的区别 Filter过滤器 Filter 过滤器它是 JavaWeb 的三大组件之一 三大组件分别是&#xff1a;Servlet 程序、Listener 监听器、Filter 过滤…

vue3组件间怎么通信?简述一下通信方式

在写 vue3 的项目中&#xff0c;我们都会进行组件通信&#xff0c;除了使用 pinia 公共数据源的方式除外&#xff0c;我们还可采用那些更简单的API方法呢&#xff1f;给大家介绍介绍几种父子组件和子父组件通信的方式。 1、父子组件通信 1.1 defineProps 父子组件通信我们第一…