【C++】使用 CMake 在 Windows 上自动化发布 C++/Qt 应用程序

对于使用 MinGW 编译 C++/Qt 项目的开发者来说,发布程序时常常面临目标机器缺少必要运行时库(DLL)的情况。传统方法需要手动收集依赖文件,不仅繁琐,还容易遗漏。本文将展示如何利用 CMake 构建系统,结合 Qt 官方部署工具,实现从编译到发布的自动化流程,既能生成静态链接的单一 exe 文件,也能自动打包 MinGW 动态库,极大提高发布效率。

CMake 基础配置

最小化项目结构

一个典型的 CMake 项目结构如下:

ProjectRoot/
├── CMakeLists.txt    # 构建规则核心文件
├── main.cpp          # 程序入口文件
└── build/            # 构建产物目录(建议加入 .gitignore)

基础 CMakeLists.txt 配置

在项目根目录下创建 CMakeLists.txt,内容如下:

cmake_minimum_required(VERSION 3.10)
project(MyApp LANGUAGES CXX)set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)add_executable(${PROJECT_NAME} main.cpp)

构建命令优化

建议使用以下现代化构建命令:

cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --config Release

这种方式不仅能生成 Release 版本,还能在生成目录和编译配置上做到分离,便于后续扩展和维护。

规范化输出路径

为了方便管理构建产物,我们统一配置二进制文件、库文件的输出目录:

# 统一设置输出目录
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)# 针对不同构建类型设置输出路径
foreach(config DEBUG RELEASE RELWITHDEBINFO MINSIZEREL)string(TOUPPER ${config} config_upper)set_target_properties(${PROJECT_NAME} PROPERTIESRUNTIME_OUTPUT_DIRECTORY_${config_upper} ${CMAKE_BINARY_DIR}/bin/${config})
endforeach()

MinGW 的动态链接与静态链接

静态链接策略

如果希望生成一个单一的 exe 文件,可以采用完全静态链接的方式。对于 MinGW 平台,可以在 CMakeLists.txt 中添加如下配置:

if(MINGW)# 完全静态链接set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -static")# 对标准库及其他可选组件进行静态化add_link_options(-static-libgcc-static-libstdc++-Wl,-Bstatic -lstdc++ -lpthread)
endif()

这样可以有效避免目标机器因缺少动态链接库而运行失败。

自动化收集 MinGW 运行时库

如果你选择动态链接或项目中含有依赖 MinGW 提供的动态库(如 Qt 部分插件),可以在 CMake 中自动收集并拷贝所需 DLL 文件。示例如下:

if(MINGW AND NOT BUILD_STATIC)# 获取编译器所在目录,并定位到 bin 目录get_filename_component(MINGW_BIN_PATH ${CMAKE_CXX_COMPILER} DIRECTORY)set(MINGW_BIN_PATH "${MINGW_BIN_PATH}/../bin")# 定义必须拷贝的运行时 DLL 文件set(ESSENTIAL_DLLSlibgcc_s_seh-1.dlllibstdc++-6.dlllibwinpthread-1.dlllibssp-0.dll)# 构建拷贝命令,将 DLL 拷贝至目标可执行文件所在目录foreach(dll ${ESSENTIAL_DLLS})add_custom_command(TARGET ${PROJECT_NAME} POST_BUILDCOMMAND ${CMAKE_COMMAND} -E copy_if_different"${MINGW_BIN_PATH}/${dll}"$<TARGET_FILE_DIR:${PROJECT_NAME}>COMMENT "Copying ${dll}")endforeach()
endif()

通过这种方式,构建完成后,必要的 DLL 文件将自动被拷贝到可执行文件目录中,简化发布步骤。

Qt 应用程序的自动化部署

Qt 模块化配置

首先需要设置 Qt 的安装路径,推荐使用参数传递或环境变量方式来指定。示例代码如下:

# 设置 Qt 安装路径(优先级:参数 > 环境变量 > 默认路径)
if(NOT DEFINED QT_PATH)if(DEFINED ENV{QT_DIR})set(QT_PATH $ENV{QT_DIR})else()set(QT_PATH "C:/Qt/6.8.2/mingw_64")endif()
endif()list(APPEND CMAKE_PREFIX_PATH ${QT_PATH})# 查找必需的 Qt 模块
find_package(Qt6 REQUIRED COMPONENTSCoreGuiWidgetsOpenGLMultimediaNetworkConcurrent
)

集成 windeployqt 部署工具

Qt 提供的 windeployqt 工具可以自动收集 Qt 应用所需的所有运行时依赖。将其集成到 CMake 中,可以参考下面的配置:

find_program(WINDEPLOYQT windeployqt HINTS "${QT_PATH}/bin")if(WINDEPLOYQT)# 如有需要,可配置 QML 资源路径set(QML_ROOT "${CMAKE_CURRENT_SOURCE_DIR}/qml")add_custom_command(TARGET ${PROJECT_NAME} POST_BUILDCOMMAND ${WINDEPLOYQT} --verbose 1--no-compiler-runtime--no-system-d3d-compiler--no-angle--no-opengl-sw--qmldir "${QML_ROOT}""$<TARGET_FILE_DIR:${PROJECT_NAME}>"COMMENT "Deploying Qt runtime dependencies...")
else()message(WARNING "windeployqt not found! Qt dependencies will be missing.")
endif()

这样在构建完成后,windeployqt 将自动分析并部署 Qt 所需的依赖,简化了打包工作。

资源文件处理

如果你的项目中包含资源文件(例如图像、配置文件等),也可以使用 CMake 自动将这些文件拷贝到输出目录:

# 自动查找资源目录下所有文件
file(GLOB_RECURSE RESOURCE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/resources/*"
)foreach(res_file ${RESOURCE_FILES})file(RELATIVE_PATH rel_path ${CMAKE_CURRENT_SOURCE_DIR}/resources ${res_file})add_custom_command(TARGET ${PROJECT_NAME} POST_BUILDCOMMAND ${CMAKE_COMMAND} -E copy${res_file}"$<TARGET_FILE_DIR:${PROJECT_NAME}>/resources/${rel_path}")
endforeach()

完整的 QT 配置示例

下面给出一个综合示例,展示如何将上述各部分内容整合到一个完整的 CMakeLists.txt 中:

# 指定 CMake 的最低版本要求  
cmake_minimum_required(VERSION 3.20)  # 定义项目名称和使用的编程语言  
project(MyQtApp LANGUAGES CXX)  # 全局 C++ 标准设置  
# 设置 C++ 标准为 C++17,并要求必须使用该标准  
set(CMAKE_CXX_STANDARD 17)  
set(CMAKE_CXX_STANDARD_REQUIRED ON)  # 输出目录配置  
# 设置可执行文件、静态库和动态库的输出目录  
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)  # 可执行文件输出到 bin 目录  
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)  # 静态库输出到 lib 目录  
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib)  # 动态库输出到 lib 目录  # Qt 配置  
# 设置 Qt 的安装路径  
set(QT_PATH "C:/Qt/6.8.2/mingw_64")  
# 将 Qt 的路径添加到 CMake 的前缀路径中,以便找到 Qt 库  
list(APPEND CMAKE_PREFIX_PATH ${QT_PATH})  
# 查找所需的 Qt 组件,确保 Core、Gui 和 Widgets 组件可用  
find_package(Qt6 REQUIRED COMPONENTS Core Gui Widgets)  # 添加可执行文件及链接 Qt 库  
# 创建一个可执行文件,源文件为 src/main.cpp  
add_executable(${PROJECT_NAME} src/main.cpp)  
# 将 Qt 的核心库、图形库和小部件库链接到可执行文件  
target_link_libraries(${PROJECT_NAME} Qt6::Core Qt6::Gui Qt6::Widgets)  # Qt 部署:调用 windeployqt 自动打包依赖  
# 查找 windeployqt 工具  
find_program(WINDEPLOYQT windeployqt)  
if(WINDEPLOYQT)  # 在构建后调用 windeployqt 来打包 Qt 依赖文件  add_custom_command(TARGET ${PROJECT_NAME} POST_BUILD  COMMAND ${WINDEPLOYQT}   --qmldir ${CMAKE_CURRENT_SOURCE_DIR}/qml  # 指定 QML 目录  $<TARGET_FILE_DIR:${PROJECT_NAME}>  # 指定可执行文件目录  )  
endif()  

构建与打包脚本

为了进一步简化整个流程,可以编写一个简单的批处理脚本(例如 package.bat),实现一键构建和打包:

@echo off
set BUILD_DIR=build
set OUTPUT_DIR=packagecmake -B %BUILD_DIR% -DCMAKE_BUILD_TYPE=Release
cmake --build %BUILD_DIR% --config Releasexcopy /E /Y %BUILD_DIR%\bin\Release %OUTPUT_DIR%

运行该脚本后,将自动生成 Release 版本,并将生成的 exe 与相关依赖拷贝到 package 目录下,便于分发。

构建即发布的未来

通过本文介绍的技术方案,开发者可以将繁琐的多步发布流程简化为单一构建命令。无论是静态链接生成单一 exe,还是自动收集动态库、部署 Qt 依赖,这套方案都能满足小型项目乃至企业级持续交付的需求。建议开发者根据实际项目需求灵活调整配置,平衡文件体积、依赖管理与构建效率,迈向自动化构建与发布的未来。

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

简易的微信聊天网页版【项目测试报告】

文章目录 一、项目背景二、项目简介登录功能好友列表页面好友会话页面 三、测试工具和环境四、测试计划测试用例部分人工手动测试截图web自动化测试测试用例代码框架配置内容代码文件&#xff08;Utils.py&#xff09;登录页面代码文件&#xff08;WeChatLogin.py&#xff09;好…

QT播放视频保持视频宽高比消除黑边

QT播放视频保持视频宽高比消除黑边 1、问题 在播放视频的时候&#xff0c;由于框架的大小发生变化&#xff0c;导致视频出现黑边很不好看。 因此需要像一种方法消除黑边 2、处理 1、读取视频的宽高比 2、设置视频的Widget的大小固定&#xff0c;Widget的宽高比和视频宽高比…

Apache nifi demo 实验

Apache nifi 是个数据流系统&#xff0c;可以通过配置 自定义的流程来实现数据的转换。 比如可以配置一个流程&#xff0c;读取数据库里的数据&#xff0c;再转换&#xff0c;最后保存到本地文件。 这样可以来实现一些数据转换的操作&#xff0c;而不用特地编写程序来导入导出。…

蓝桥杯 - 每日打卡(类斐波那契循环数)

题目: 解题思路&#xff1a; 假设输入数值为number 分析题目&#xff0c;如果想要解决这个问题&#xff0c;我们需要实现两个方法&#xff0c;第一个检查number是否是类斐波那契&#xff0c;第二个是模拟1e7 - 0的过程&#xff0c;因为是求最大的&#xff0c;那么我们从1e7开始…

DeepSeek集成到VScode工具,让编程更高效

DeepSeek与VScode的强强联合&#xff0c;为编程效率树立了新标杆。 DeepSeek&#xff0c;一款卓越的代码搜索引擎&#xff0c;以其精准的索引和高速的检索能力&#xff0c;助力开发者在浩瀚的代码海洋中迅速定位关键信息。 集成至VScode后&#xff0c;开发者无需离开熟悉的编辑…

RAG组件:向量数据库(Milvus)

在当前大模型盛行的时代&#xff0c;大模型的垂类微调、优化成为产业落地、行业应用的关键&#xff1b;RAG技术应运而生&#xff0c;主要解决大模型对专业知识、实效性知识欠缺的问题&#xff1b; RAG的核心工作逻辑是将专业知识、实效知识等大模型欠缺的知识进行收集、打包、保…

2022java面试总结,1000道(集合+JVM+并发编程+Spring+Mybatis)的Java高频面试题

1、面试题模块汇总 面试题包括以下十九个模块&#xff1a; Java 基础、容器、多线程、反射、对象拷贝、Java Web 模块、异常、网络、设计模式、Spring/Spring MVC、Spring Boot/Spring Cloud、Hibernate、Mybatis、RabbitMQ、Kafka、Zookeeper、MySql、Redis、JVM 。如下图所示…

英码科技携昇腾DeepSeek大模型一体机亮相第三届北京人工智能产业创新发展大会

2025年2月28日&#xff0c;第三届北京人工智能产业创新发展大会在国家会议中心隆重开幕。本届大会以"好用、易用、愿用——以突破性创新加速AI赋能千行百业”为主题&#xff0c;重点展示人工智能技术创新成果与产业化应用实践。作为昇腾生态的APN伙伴&#xff0c;英码科技…

(链表 删除链表的倒数第N个结点)leetcode 19

设空结点指向head便于插入和删除结点 考虑特殊情况 head结点被删除 a结点仅用来测试长度&#xff0c;找到目标结点的位置 b结点为空结点指向head返回值 cur用来删除目标值&#xff08;特殊情况 目标值为head 这时curb) 则开始就将cur初始化为b开始遍历 /*** Definition fo…

Android Studio 新版本Gradle发布本地Maven仓库示例

发布代码到JitPack示例&#xff1a;https://blog.csdn.net/loutengyuan/article/details/145938967 以下是基于 Android Studio 24.2.2&#xff08;Gradle 8.10.2 AGP 8.8.0 JDK17&#xff09; 的本地 Maven 仓库发布示例&#xff0c;包含aar和jar的不同配置&#xff1a; 1.…

[今年毕业设计]最新最全最有创意的基于云计算的计算机专业毕设选题精选推荐汇总建议收藏!!

文章目录 前言基于云计算的毕业设计选题毕设作品展示 前言 2025全新毕业设计项目 &#x1f497;博主介绍&#xff1a;✌全网粉丝10W,CSDN全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云等平台优质作者。 &#x1f447;&#x1f3fb; 精彩专栏 推荐订阅&#x1f4…

coze生成的工作流,发布后,利用cmd命令行执行。可以定时发日报,周报等。让他总结你飞书里面的表格。都可以

coze生成的工作流&#xff0c;发布后&#xff0c;利用cmd命令行执行。可以定时发日报&#xff0c;周报等。让他总结你飞书里面的表格。都可以。 很简单。 准备工作&#xff0c;先发布你的工作流&#xff0c;和发布应用。 然后&#xff0c;点击扣子API 。 申请一个&#xff0…

安防监控/视频集中存储EasyCVR视频汇聚平台如何配置AI智能分析平台的接入?

EasyCVR安防视频监控平台不仅支持AI边缘计算智能硬件设备的接入&#xff0c;还能快速集成AI智能分析平台&#xff0c;接收来自智能分析平台或设备的AI告警信息&#xff0c;如烟火检测、周界入侵检测、危险区域闯入检测、安全帽/反光衣佩戴检测等。 本文将详细介绍如何在EasyCVR…

以1.7K深圳小区房价为例,浙大GIS实验室使用注意力机制挖掘地理情景特征,提升空间非平稳回归精度

地理加权回归 (Geographically Weighted Regression, GWR) 是一种广泛应用于地理空间分析的统计方法&#xff0c;用于捕捉地理现象的空间非平稳性&#xff08;即空间异质性&#xff09;。传统 GWR 通过为每个观测点分配权重来反映其对回归参数的影响&#xff0c;这些权重通常基…

【JavaEE】线程安全

【JavaEE】线程安全 一、引出线程安全二、引发线程安全的原因三、解决线程安全问题3.1 synchronized关键字&#xff08;解决修改操作不是原子的&#xff09;3.1.1 synchronized的特性3.1.1 synchronized的使用事例 3.2 volatile 关键字&#xff08;解决内存可见性&#xff09; …

智慧农业中光谱相机对土壤成分的无损检测应用‌

可浏览之前发布的一篇文章&#xff1a;光谱相机在农业中的具体应用案例 一、土壤成分定量分析 ‌养分检测‌ 光谱相机通过捕捉土壤反射的特定波长光线&#xff0c;可精准检测氮、磷、钾等主要养分含量&#xff0c;以及有机质和水分比例。例如&#xff0c;不同养分对近红外波段…

实现浏览器交互Ai Web Ui-本地化部署的deepseek + Ollama + Page Assist

一、deepseek本地化部署 上篇写了deepseek本地化部署的小白教程。 deepseek 本地化部署&#xff08;小白也可部署&#xff09; 但有个问题&#xff0c;Ollama只能在命令行进行交互&#xff0c;体验相当差。 二、Page Assist安装 本篇给大家介绍个好用的chrome浏览器AI Web …

使用Maven搭建Spring Boot框架

文章目录 前言1.环境准备2.创建SpringBoot项目3.配置Maven3.1 pom.xml文件3.2 添加其他依赖 4. 编写代码4.1 启动类4.2 控制器4.3 配置文件 5.运行项目6.打包与部署6.1 打包6.2 运行JAR文件 7.总结 前言 Spring Boot 是一个用于快速构建 Spring 应用程序的框架&#xff0c;它简…

易语言模拟真人鼠标轨迹算法 - 防止游戏检测

一.简介 鼠标轨迹算法是一种模拟人类鼠标操作的程序&#xff0c;它能够模拟出自然而真实的鼠标移动路径。 鼠标轨迹算法的底层实现采用C/C语言&#xff0c;原因在于C/C提供了高性能的执行能力和直接访问操作系统底层资源的能力。 鼠标轨迹算法具有以下优势&#xff1a; 模拟…

10.【线性代数】—— 四个基本子空间

十、 四个基本子空间 1. 列空间 C ( A ) C(A) C(A) in R m R^m Rm2. 零空间 N ( A ) N(A) N(A) in R n R^n Rn3. 行空间 C ( A T ) C(A^T) C(AT) in R n R^n Rn4. 左零空间 N ( A T ) N(A^T) N(AT) in R m R^m Rm综述5. 新的向量空间 讨论矩阵 A m ∗ n A_{m*n} Am∗n​…