ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

从源码编译Qt 5.15.16与VS2019 MSVC集成实战指南

从源码编译Qt 5.15.16与VS2019 MSVC集成实战指南 简介这是Qt 5.15.16在Windows平台下针对Visual Studio 2019环境编译的完整开发包面向需要快速搭建Qt开发环境或构建跨平台应用的C开发者。与手动编译源码相比直接使用预编译库可显著减少环境配置成本适用于桌面、移动及嵌入式项目开发。压缩包为zip格式共包含2000个文件其中以.h头文件为主1548个覆盖Qt Core、Gui、Widgets、OpenGL、Test等模块的接口声明另有少量json、pri等工程配置文件。包体约753.36MB目录结构包含include、lib、plugins、bin四大类分别存放头文件、链接库、扩展插件和运行工具结构清晰、便于按需引用。已有863人学习下载。利用此编译包开发者可直接链接编译好的库文件进行开发省去从源码编译的漫长时间同时可通过原生插件机制扩展功能并借助bin目录下的部署与调试工具完成应用打包和测试。无论从事Windows桌面客户端还是跨平台界面开发这套编译包都能提供扎实的基础支持。 就在上个月我需要给一个工业现场的工控机重新交付一套Qt程序机器是Win10系统对方要求必须用VS2019的MSVC编译器跑。打开官方安装包一看Qt 5.15.2是开源二进制包的最后一个版本但项目依赖里需要修复几个5.15.2之后才合入的Bug这就意味着我只有一条路可走自己动手编译Qt 5.15.16。整个过程耗时大概三个晚上每一步基本都是在验证“官网文档没写清楚但实际又必须注意”的细节。这篇文章就把我完整走过的编译流程、踩过的坑和最终验证方式全部写出来适合正打算从源码编译Qt 5.15系列、尤其是要配合VS2019开发环境的朋友参考。1. 为什么这个版本值得从源码编译而不是等安装包1.1 5.15.2之后的开源包断档先把这个背景说透。Qt 5.15系列是Qt 5的最后一个长期支持版本官方在2020年发布了5.15.2之后就改变了开源分发策略之后的5.15.x补丁版本不再提供离线二进制安装包只给商业授权用户提供预编译产物。开源社区用户能拿到的只有源代码包。所以5.15.2到5.15.16这几个小版本里修复的Bug——包括某些平台下QPainter的渲染问题、QNetworkAccessManager的TLS握手异常等——你想用就只能自己编译。这个问题在5.15.16发布后也算有了一个明确的终局Qt公司把5.15.16定义为社区补丁版本的收尾版后续不再有新的5.15.x补丁。所以选5.15.16作为编版本是最稳妥的它集中了该系列全部已知修复编译之后能长期沿用不用担心“编完了结果还有个已知Bug没修”。我自己评估过5.15.14、5.15.15和5.15.16的差异最终选择16也是不想折腾两次。1.2 什么场景下必须走编译路线不算那些有洁癖喜欢自己定制编译参数的极客正常情况下你走源码编译无非就三种情况官方二进制包缺少你需要的内容比如某些模块WebEngine、Multimedia、SerialPort在官方包里不带debug库或者没带opengl desktop支持。项目对Qt的编译器版本有硬性匹配要求比如工控领域常用的VS2019 MFC混编必须用MSVC编译的Qt库不能拿MinGW版本的来充数。你需要在嵌入式、国产化系统或者无联网的离线环境中部署installer安装器根本用不了源码包是唯一可行分发形式。顺便说一句如果你只是想在Windows上快速开发个界面不需要改Qt源码、不需要自定义编译参数那直接用5.15.2安装包就好别浪费时间走编译流程。编译Qt不是个休闲项目时间成本和磁盘占用都摆在那里我在第二节会给你算一下这笔账。2. 环境准备VS2019、Perl、Python、CMake一套配齐2.1 VS2019需要勾选的组件编译Qt 5.15.16时Visual Studio 2019的安装选项直接决定configure阶段是否报错。很多第一次编译的人只装了“C桌面开发”工作负载结果到配置时报找不到编译器的错误——那是缺少了MSVC工具集和Windows SDK。我在VS Installer里勾选的组件如下工作负载使用C的桌面开发右侧组件MSVC v142 - VS 2019 C x64/x86生成工具右侧组件Windows 10 SDK建议选10.0.18362.0或更新的版本右侧组件C CMake tools for Windows这个不是编译Qt必需的但后续工程管理会用注意不要手欠去勾选C Clang工具也不要把Windows SDK版本选成预览版。Qt 5.15.16的构建脚本对Clang和过新的SDK适配都不好用官方稳定的MSVC v142组合最稳。安装完VS2019后务必先启动一次“开发者命令提示符”或者“x64 Native Tools Command Prompt for VS 2019”确认能正常执行cl命令并显示版本号。这个验证步骤虽然简单但能避免后面花半小时排查环境变量问题。2.2 Perl、Python、CMake版本对照Qt的configure脚本在Windows环境依赖三个外部工具Perl、Python、CMake。缺一个都会在配置阶段直接中断而且报错信息有时候并不直观。Perl推荐Strawberry Perl 5.32或5.36官网下载后勾选添加到PATH。ActivePerl也能用但社区版在某些Qt模块的脚本兼容性上不如Strawberry。实测Strawberry Perl 5.32.1.1配合Qt 5.15.16全流程无压力。Python官方建议Python 3.7到3.9之间我实际用的是3.8.10因为Qt构建脚本对3.9以上版本有所警告虽然多数能编过去但没必要冒险。安装时记得勾选“Add Python to PATH”不然后面脚本找不到解释器。CMakeQt 5.15.16的configure脚本要求CMake 3.16以上我用的是3.21.3。如果你同时使用VS2019做别的CMake项目版本就维持VS自带的那个也行但保险起见建议装独立版并把路径放到PATH前面避免版本混乱。版本对照如表所示工具推荐版本作用PerlStrawberry Perl 5.32.1.1处理构建脚本与源码生成Python3.8.10用于QML类型生成等辅助工具CMake3.21.3部分模块构建依赖QT编译主流程仍用qmakeVS201916.11.xMSVC v142工具链与Windows SDK2.3 目录与磁盘规划编译Qt 5.15.16需要的磁盘空间比你想象中大得多。我编译的是msvc2019_64版本选择的是debug_and_release双构建模式源码目录、构建目录、安装目录三份文件加起来最终占用了接近30GB。这对C盘空间紧张的人是一个巨大的坑。我的规划方案是这样源码目录D:\Qt\src\qt-everywhere-src-5.15.16解压后约8GB。构建目录D:\Qt\build\msvc2019_64单独创建绝对路径不要带空格和中文。这个目录编译时会产生大量中间文件最终体积可能超过10GB。安装目录D:\Qt\5.15.16\msvc2019_64configure时通过-prefix指定最终编译完的产物放这里建议直接规划成以后qmake指向的目录。另外强烈建议在编译前开启Windows的“长路径支持”。Win10较新版本可以在组策略里开启“启用Win32长路径”或者直接修改注册表项HKLM\SYSTEM\CurrentControlSet\Control\FileSystem\LongPathsEnabled为1。不开启的话Qt源码里某些路径很深的文件会在编译后期报“找不到文件”或“路径太长”错误那是最折磨人的问题之一。3. configure配置阶段参数写对了编译省一半时间3.1 获取源码与创建构建目录源码从官方下载即可地址是Qt官网的archive区找5.15.16下的qt-everywhere-opensource-src-5.15.16.zip大约800MB。如果你在下载时遇到网速问题可以使用国内镜像站点镜像的压缩包内容和官方仓库是一致的。解压时注意一个细节不要用Windows资源管理器直接右键解压到含空格或中文的路径。我在第一次编译时把源码放在D:\Qt Source\结果configure阶段频繁出现无法定位路径的错误后来统一改成D:\Qt\src\qt-everywhere-src-5.15.16路径干干净净问题清零。创建好独立的构建目录D:\Qt\build\msvc2019_64所有编译都在这里进行保持源码目录的纯净方便以后排查问题或重复构建。这里要说明一下很多人以为Qt和大多数CMake项目一样支持“在建目录里直接configure”其实Qt 5.15系列在Windows上也是支持shadow build的即源码目录和构建目录分开这也正是我们要这么做的原因。3.2 关键配置参数逐项说明在“x64 Native Tools Command Prompt for VS 2019”中先切换到构建目录然后执行configure。第一次编译Qt的人看到一长串参数往往直接懵其实核心参数就那么几个。我用的完整命令如下cd /d D:\Qt\build\msvc2019_64 D:\Qt\src\qt-everywhere-src-5.15.16\configure.bat -prefix D:\Qt\5.15.16\msvc2019_64 -opensource -confirm-license -debug-and-release -mp -nomake examples -nomake tests -skip qtwebengine -skip qt3d -shared -platform win32-msvc逐个参数说明-prefix指定最终安装目录也就是编译后Qt库、头文件、工具的存放位置。后续qmake会以这个目录为参考定位整个工具链。-opensource -confirm-license确认以开源协议使用直接回答许可证询问避免交互卡住。-debug-and-release同时生成debug版和release版库。只做release可以省不少时间但做项目调试时没有debug版库会非常痛苦建议保留。-mp多进程编译开关启用后构建阶段可以用多核并行。如果不开它即使后面用jom指定多线程某些步骤仍然会串行执行这个参数一定要加。-nomake examples -nomake tests不编译示例和测试代码能节省大量时间。这些东西对应用开发的你来说没有任何用处。-skip qtwebengine跳过WebEngine模块。这个模块在Windows上编译时长极其恐怖且依赖一堆额外组件除非你确实需要内嵌浏览器否则建议跳过。我这次项目用不到直接跳掉整个编译时间缩短了三分之一以上。-skip qt3d跳过Qt 3D模块同理不需要就不编。-shared生成动态链接库这是默认行为写上是为了明确意图。-platform win32-msvc明确构建平台在VS环境下就是win32-msvc不需要额外指定x64后缀编译器会自动检测架构。3.3 二次裁剪通过-skip和-nomake精简如果你对Qt的模块结构比较熟还可以进一步用-skip参数跳过不需要的模块。我这里当前的项目只用到了Core、Gui、Widgets、Network、SerialPort、Xml、Sql这几个模块理论上甚至可以跳过更多但保守起见我只跳了WebEngine和3D。有一个经验是跳过Qt WebEngine带来的时间收益最大那个模块光依赖的Python脚本和Chromium源码处理就要额外加一两个小时编译时间而且稍有不慎就会因为网络或内存问题编译失败。-nomake的另一个用途是控制是否生成工具和插件。比如-nomake tools会跳过Qt Creator自带的工具链但也会影响后续部分插件的生成。我的建议是只用-nomake examples和-nomake tests这两个其他的不要轻易动避免破坏模块之间的依赖关系。configure执行完会显示一个汇总列表列出哪些模块会编译、哪些被跳过、目标平台和编译器版本等信息仔细看一下有没有意外跳过你需要的模块。确认无误后再进入下一步。如果configure中途报错优先检查Perl/Python路径和编译器环境这是最常见的两个坑。4. 漫长的编译过程从nmake到nmake install4.1 开始编译与错误即时处理configure通过后就可以开始编译了。我用的命令是nmake如果configure命令里加了-mpnmake会自动利用多核并行编译实测并非如此。-mp参数是对jom生效的nmake自己并不会并行。所以我实际使用的是Qt自带的多线程构建工具jom而不是nmakejom -j 8jom.exe在之前安装的Qt二进制包里可以找到比如C:\Qt\Tools\QtCreator\bin\jom.exe也可以单独下载对应版本放到系统PATH里。jom是Qt官方专为并行编译开发的make工具和nmake兼容是加快Windows上Qt编译速度的关键工具。第一次编译时我用nmake跑全量构建总共耗时约3小时40分钟。第二次用jom -j 8CPU为i7-107008核16线程总耗时约1小时50分钟效率差距非常明显。如果你没有jom直接用nmake也能完成只是要有等待更长时间的心理准备。还有一点如果你的内存不足16GB建议把并行数降到4或6不然编译期间内存占用过高会卡死系统。编译期间常用的几个处理方式遇到个别文件编译失败错误提示是C2065等语法级问题一般是因为Perl版本或Python版本不配造成的回退版本重试比硬修源码靠谱。遇到“fatal error LNK1104: cannot open file xxx.lib”这类链接错误多半是依赖顺序问题先检查是否跳过了某个模块导致的。编译中途如果因为断电或人为中断停止再次执行jom或nmake会从上次断点继续不需要重新configure。4.2 安装阶段与目录结构编译结束后执行安装命令jom install这一步会把所有头文件、库文件、插件、工具程序、qmake配置等统一复制到-prefix指定的目录D:\Qt\5.15.16\msvc2019_64。安装过程的耗时通常在10到20分钟之间取决于模块数量。安装完成后检查目录结构。正常情况下应看到以下关键子目录bin\存放qmake.exe、moc.exe、uic.exe等工具以及Qt的DLL文件。lib\存放导入库.lib和静态库同时包含cmake子目录用于CMake项目集成。include\Qt头文件按模块分子目录。plugins\平台插件、图像格式插件、SQL驱动等。qml\QML模块文件如果你编译了QtQml相关模块。mkspecs\qmake的配置规范决定后续项目使用何种编译选项。看到bin\qmake.exe出现并双击能正常弹出帮助信息就说明安装基本成功了。这也可以作为编译是否成功的最直观验证。4.3 编译完成后如何验证是否可用我习惯用一个小demo工程验证编译产物可不可用比任何文档都有说服力。在临时目录建一个main.cpp#include QApplication #include QLabel int main(int argc, char *argv[]) { QApplication app(argc, argv); QLabel label(Qt 5.15.16 build test); label.show(); return app.exec(); }再写一个简单的.pro文件QT core gui widgets SOURCES main.cpp TARGET buildtest然后分别执行D:\Qt\5.15.16\msvc2019_64\bin\qmake.exe buildtest.pro jom如果编译出的buildtest.exe能正常启动并显示窗口说明整套Qt库、编译器、链接器之间的配合没有问题。这里要注意运行exe前可能需要把D:\Qt\5.15.16\msvc2019_64\bin加到系统PATH环境变量否则程序启动时提示找不到Qt5Core.dll等动态库是正常的——并不是编译坏了。5. 编译中真实遇到的坑与排查链路5.1 路径过长导致文件无法创建这是我踩的第一个大坑。使用普通命令提示符执行构建到某个比较深的模块时突然报出类似“The system cannot find the path specified”的错误关键是指向的文件路径明明存在。排查后发现是Windows系统默认259字符路径上限导致Qt源码里开源的第三方库路径层层叠加一旦拼接起来超过长度限制cl.exe就无法创建输出文件。我的处理方式是通过注册表开启长路径支持WinR输入gpedit.msc打开组策略进入“计算机配置-管理模板-系统-文件系统”找到“启用Win32长路径”设置为“已启用”。如果是家庭版系统没有组策略就改注册表HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem\LongPathsEnabled把值从0改成1然后重启。改完再编译路径问题彻底消失。5.2 jom编译中断与依赖处理编译过程中段性报错“jom: Error”是家常便饭。刚开始我以为是源码问题后来排查发现大部分jom中断源于内存不足少数源于局部文件损坏。一个识别技巧是jom报错后的输出会保留最后几十行看是哪个目标文件编译失败。如果失败的是qjsonarray.cpp这类基础源文件且旁边没有明显语法错误信息那基本可以判断是内存不够导致的“假错误”。这时不要傻傻去改源码清理一下系统占用把jom -j 8降成jom -j 4重新执行一般就过去了。还有一次遇到“fatal error C1083: Cannot open include file: openssl/ssl.h”之类的报错那是因为Qt某些网络模块在Linux上默认链接OpenSSLWindows上如果没装OpenSSL就会拦路。如果你不需要SSL功能在configure阶段可以加上-no-openssl跳过如果你的网络模块必须要用HTTPS那就得提前在系统里装好OpenSSL并设置OPENSSL_HOME环境变量。我的项目用到和设备的TCP通信不走HTTPS所以果断加了-no-openssl省去一堆麻烦。5.3 configure阶段Python版本检测失败的排查链路另一位同事在按照我的配置走的时候configure阶段卡了一个奇怪的错误“python3 is required but not found”。他明明装了Python 3.8PATH里也能执行python。排查了十分钟发现是Python安装时没有勾选“Add Python to PATH”但Windows商店版的Python别名劫持了python命令。打开“设置-应用-高级应用设置-应用执行别名”把“python.exe”和“python3.exe”两个别名关掉然后再安装一遍正式版Python并且勾选加到PATHconfigure顺利通过。这个经历告诉我们Qt的configure脚本在找Python时是很死板的它认的是PATH里的正规可执行文件。任何通过别名或虚拟环境包装的python都会让它困惑。5.4 编译到最后阶段磁盘空间不足磁盘空间不足这个问题发生在编译WebEngine的时候概率最高。我虽然没有编WebEngine但同事机器上編了结果在最后的链接阶段报“no space left on device”。当时他以为编译重新跑一次就行结果三次都在同一个位置失败。后来我让他检查了C盘剩余空间——发现只剩2GB了。Qt编译会在C:\Users\用户名\AppData\Local\Temp下释放大量临时文件同时Windows页面文件也会动态膨胀。最终清理了C盘旧安装包、把构建目录换到空间更大的D盘才顺利编译完。所以强烈建议在开始之前把系统盘至少留出15GB用户临时目录所在盘符也一并检查一下。这是一个看起来不起眼但能在最后一刻毁掉所有成果的问题。6. 编译产物接入VS2019开发项目并发布6.1 在VS2019里配置Qt版本与使用qmake编译完成后把自编译的Qt接入VS2019有两种常见方式一是用Visual Studio的Qt工具扩展Qt VS Tools配合qmake生成的VS工程二是干脆不用VS的Qt插件直接用命令行qmake jom完成项目构建。前者适合在VS里看界面、调试后者适合自动化构建和脚本集成。如果你安装了Qt VS Tools打开“扩展-Qt VS Tools-Qt Versions”点击“Add new Qt version”路径选择D:\Qt\5.15.16\msvc2019_64版本名会自动识别为5.15.16编译器会自动关联到当前VS的MSVC。完成之后新建项目时就能在“Qt Widgets Application”模板里直接选择这个版本。如果不喜欢插件则依然可以通过qmake生成的Makefile来构建。命令流程是mkdir build cd build D:\Qt\5.15.16\msvc2019_64\bin\qmake.exe ..\myproject.pro jom -j 8这样生成的exe由MSVC编译能和MFC或其他VS项目无缝混编这也是我们选择VS2019MSVC编译Qt而非MinGW的核心原因。6.2 使用windeployqt打包发布编译好Qt程序后面对一堆DLL新手最容易直接在目标机器上拷贝结果运行时弹窗“缺少Qt5Core.dll”。正确的发布方式是用Qt自带的部署工具。在VS的开发命令行下进入编译输出目录执行set PATHD:\Qt\5.15.16\msvc2019_64\bin;%PATH% D:\Qt\5.15.16\msvc2019_64\bin\windeployqt.exe buildtest.exewindeployqt会自动将exe依赖的Qt核心模块、平台插件、图像格式插件复制到当前目录还会生成必要的json配置文件。对于带网络功能的程序它会自动带上Qt5Network.dll对于带界面程序会带上platforms目录下的qwindows.dll。这是Qt官方最推荐的标准发布方式。有一点需要特别留意windeployqt复制DLL时依据的是当前PATH里的Qt版本。如果我们PATH里的Qt版本和编译时用的版本不一致可能出现部署的库把程序带崩的情况。所以部署前一定把PATH设置成编译时的Qt目录我这里是D:\Qt\5.15.16\msvc2019_64\bin。部署完成后再用tree命令看看输出目录结构确认一切文件就位整个编译加部署的闭环就算完整走通了。最后再分享一个我自己在实际部署过程中的小习惯编译完的Qt目录最好单独备份一份压缩成一个压缩包存放在离线环境里。因为这版本一旦配置好后续项目构建基本是基于它做增量如果哪一天构建目录出了问题重新解压一份就能恢复免去再走一遍几小时编译流程的麻烦。在工控领域开发机可能随时被重装系统这种备份的习惯能省掉一次真正让人崩溃的重复劳动。本文还有配套的精品资源点击获取
返回列表