Qt可执行文件打包全流程
1. 简介
Qt生成可执行文件后,为了在一些没有安装Qt环境的电脑运行,通常需要将Qt运行时所需要的文件和生成目录下的可执行文件一起打包在一起。在Windows上Qt提供了一个很快捷使用的工具windeployqt.exe
2. 打包流程
- 编译可执行文件,在Qt的开发IDE中选择
release
模式编译运行,确保没问题后打开生成的目录,其中包含可执行文件.exe
和一些自行添加的运行所需文件.dll
,
注意如果使用了一些安装在自己电脑环境变量中的
.dll
文件,例如使用了OpenCV或者其他开发包,也需要将其对应的.dll
文件复制到这个目录
-
在文件管理器中新建一个文件夹,将整个目录中的文件复制到其中(将所有内容复制才能保证打包时Qt能够完整扫描到所需资源,不用担心文件过大,后续有瘦身方法)
-
在
powershell
中打开这个文件目录,运行指令windeployqt.exe .\xxxx.exe
,打包时会出现一些提示信息 -
打包完成后,理论上可以直接将这个文件夹直接压缩在其他电脑上打开运行,如果要在自己电脑测试,可以先编辑系统环境变量Path,将Qt相关的路径先删除,后运行看是否有问题。但是此时内部文件有冗余,例如我打包后为
146M
。 -
剔除不需要的文件,剔除方法很简单,在这个文件目录下点击可执行文件运行,然后全选文件夹,删除所有内容,此时会出现
File In Use
的提示,这些文件才是必须的,全部选择跳过
。删除后文件夹大小来到71.6M
,此时再将其打包为压缩包只有32M
,这个压缩包就是所谓的绿色软件,解压缩就可以运行
3. 将绿色软件
打包为安装包
为了得到一个类似于安装包的可执行文件,可以使用工具将这个文件夹打包压缩,推荐使用工具Inno Setup Downloads,软件网上有很多教程,不在此详细重复。
-
首先新建一个Inno的文件,推荐使用他的引导流程新建
-
其中一个关键步骤是添加可执行文件和执行文件所需的目录文件夹
-
其余均可默认,最后选择输出文件夹和文件图标
-
最后生成一个.iss文件,可以保存下来,打开后点击顶部编译图标就可以生成可以用来安装的文件了
-
最后生成一个安装包,其文件体积只有
20M
-
双击安装包运行,打开一个安装界面,一路Next安装到默认目录。好处是后续文件更新后可以直接安装,其会自动替换原有的文件,达到类似软件升级的效果
4. 其他与注意事项
-
如果Qml采用了外部Qml,也就是不打包在可执行文件中的方式,可使用以下方式,
property var test_qml: ThemeManager.is_pack ? "file:./Test.qml" : "Test.qml"
file
开头的是采用相对路径的方式,此时的在CMakeLists使用qt_add_qml_module
生成的目录很重要,使用上述剔除冗余文件的方法可能会全部删除掉,主要是索引目录,可以把生成的文件和文件目录删掉,保留以下内容。 -
打包之前可以在CMakeLists中
qt_add_executable
配置WIN32
选项,去除输出信息终端。
qt_add_executable(${program_name} WIN32 main.cpp ${SOURCES} Asset/logo.rc
)
但是此时所有的输出将均不可见,就算打包后出现的bug也无法查看,文件中使用以下方法,将qDebug重定向到Windows中
void CustomMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg) { QByteArray localMsg = msg.toLocal8Bit(); QString formattedMsg = QString("[%1]:%2").arg(QDateTime::currentDateTime().toString("hh:mm:ss.zzz")).arg(localMsg.constData());
#ifdef QT_PACK OutputDebugStringW((LPCWSTR)formattedMsg.utf16());
#else fprintf(stderr, "%s\n", formattedMsg.toStdString().c_str());
#endif
}int main() {
...
/* 自定义日志输出 */qInstallMessageHandler(CustomMessageOutput);
...
}
此时,利用微软提供的软件DebugView - Sysinternals | Microsoft Learn,先运行DebugView再运行自己的软件,就可以看到软件的输出了。