[原创]win10使用Qt6编译Quazip手记

前言说明

本文是作者在win10下使用Qt6编译Quazip的过程记录,旨在阐明过程中出现的问题,已经解决的思路和方法,不是直截了当的教程。
你可以在这里直接下载已经改造完成的工程。

环境

· Win10
· CMake 3.23.0-rc2
· Qt Creator 6.0.2 Based on Qt 6.2.2 (MSVC 2019, 64 bit)

一次失败的尝试经历步骤

  1. 从Github下载最新的quazip-master 09ec1d1on 25 Jan
  2. 解压到某个目录,比如F:\tgit\lib\quazip-master\quazip-1.2.0
  3. 根据官网的文档,执行CMake,结果失败,如下所示
(c) 2020 Microsoft Corporation. 保留所有权利。

C:\Users\fygame>F:

F:\>cd F:\tgit\lib\quazip-master\quazip-1.2.0

F:\tgit\lib\quazip-master\quazip-1.2.0>cmake -S . -B F:\tgit\qtprojects\quazip -D QUAZIP_QT_MAJOR_VERSION=6
-- Building for: Visual Studio 16 2019
CMake Warning at CMakeLists.txt:1 (project):
  VERSION keyword not followed by a value or was followed by a value that
  expanded to nothing.


CMake Error at CMakeLists.txt:1 (project):
  VERSION not allowed unless CMP0048 is set to NEW


CMake Warning (dev) in CMakeLists.txt:
  No cmake_minimum_required command is present.  A line of code such as

    cmake_minimum_required(VERSION 3.23)

  should be added at the top of the file.  The version specified may be lower
  if you wish to support older CMake versions for this project.  For more
  information run "cmake --help-policy CMP0000".
This warning is for project developers.  Use -Wno-dev to suppress it.

-- Configuring incomplete, errors occurred!

错误出现在F:\tgit\lib\quazip-master\quazip-1.2.0\CMakeLists.txt的第一行,如下所示

project(QuaZip_Library VERSION ${QUAZIP_LIB_VERSION})

include(GNUInstallDirs) # configurable CMAKE_INSTALL_*DIR

提示如果要使用VERSION,必须把CMP0048设置为NEW,按照提示修改如下:

cmake_policy(SET CMP0048 NEW)
project(QuaZip_Library VERSION ${QUAZIP_LIB_VERSION})

include(GNUInstallDirs) # configurable CMAKE_INSTALL_*DIR

删除缓存F:\tgit\qtprojects\quazip,重新执行CMake命令:

F:\tgit\lib\quazip-master\quazip-1.2.0>cmake -S . -B F:\tgit\qtprojects\quazip -D QUAZIP_QT_MAJOR_VERSION=6
CMake Warning at CMakeLists.txt:2 (project):
  VERSION keyword not followed by a value or was followed by a value that
  expanded to nothing.


-- Selecting Windows SDK version 10.0.17763.0 to target Windows 10.0.19041.
-- The C compiler identification is MSVC 19.29.30140.0
-- The CXX compiler identification is MSVC 19.29.30140.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: D:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.29.30133/bin/Hostx64/x64/cl.exe - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: D:/Program Files (x86)/Microsoft Visual Studio/2019/Community/VC/Tools/MSVC/14.29.30133/bin/Hostx64/x64/cl.exe - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
CMake Error at CMakeLists.txt:49 (add_library):
  add_library ALIAS requires exactly one target argument.


CMake Error at CMakeLists.txt:51 (set_target_properties):
  set_target_properties called with incorrect number of arguments.


CMake Error at CMakeLists.txt:57 (target_include_directories):
  Cannot specify include directories for target "PUBLIC" which is not built
  by this project.


CMake Error at CMakeLists.txt:63 (target_link_libraries):
  target_link_libraries called with incorrect number of arguments


CMake Error at CMakeLists.txt:67 (target_compile_definitions):
  Cannot specify compile definitions for target "PUBLIC" which is not built
  by this project.


CMake Warning (dev) in CMakeLists.txt:
  No cmake_minimum_required command is present.  A line of code such as

    cmake_minimum_required(VERSION 3.23)

  should be added at the top of the file.  The version specified may be lower
  if you wish to support older CMake versions for this project.  For more
  information run "cmake --help-policy CMP0000".
This warning is for project developers.  Use -Wno-dev to suppress it.

-- Configuring incomplete, errors occurred!
See also "F:/tgit/qtprojects/quazip/CMakeFiles/CMakeOutput.log".

之前的报错没有了,但是出现了更多的报错,根据提示,看看CMakeLists.txt的第49行:

add_library(QuaZip::QuaZip ALIAS ${QUAZIP_LIB_TARGET_NAME})

set_target_properties(${QUAZIP_LIB_TARGET_NAME} PROPERTIES
    VERSION ${QUAZIP_LIB_VERSION}
    SOVERSION ${QUAZIP_LIB_SOVERSION}
    OUTPUT_NAME ${QUAZIP_LIB_FILE_NAME}
    PUBLIC_HEADER "${QUAZIP_HEADERS}"
)

${QUAZIP_LIB_TARGET_NAME}这个变量并没有赋值的地方,而且此类报错解决了一个应该还会冒出来新的,感觉按照官方流程是走不通的,可能不兼容Qt6,或者不兼容CMake 3.23.0-rc2。换了个官方声称CMake minimum version 3.15 is required to build QuaZip 1.0.的CMake 1.0,也是一堆问题,算了,不试了,决定另辟蹊径。

第二次尝试

上面编译quazip-1.2.0失败,于是按照这篇教程https://www.cnblogs.com/qiyawei/p/10695192.html,尝试编译quazip-0.7.3

  1. 从https://sourceforge.net/projects/quazip/下载quazip-0.7.3,解压到F:\tgit\qtprojects\quazip-0.7.3
  2. 在Qt Creator打开项目文件F:\tgit\qtprojects\quazip-0.7.3\quazip.pro
  3. 在子项目quazip/quazip.priqztest/qztest.pro文件中添加Qt安装目录下的QtZlib,如下图所示:
    image.png

这里和上述那篇教程不同,此处使用$$[QT_INSTALL_PREFIX]来获得Qt安装目录,避免写死本机绝对路径,保证可移植性。经过测试,在WIN10下qmake对INCLUDEPATH的斜杠方向敏感,需要使用system_path将其转换为windows路径的反斜杠,否则编译时找不到对应的头文件。

  1. 右键点击子项目quazip,选择构建"quazip",或者点击菜单构建>Build Subproject "quazip",出现一堆报错
    image.png

    报错的原因是这个项目是在Qt5环境下编写的,很多类型在Qt6已经无法直接使用。

关于QTextCodec的报错

F:\tgit\qtprojects\quazip-0.7.3\quazip\quazip.h:30: error: C1083: 无法打开包括文件: “QTextCodec”: No such file or directory

查看Qt官网这个类的介绍:

image.png

我用的是qmake,因此在F:\tgit\qtprojects\quazip-0.7.3\quazip\quazip.pro中添加一行QT += core5compat,如下图所示
image.png

重新构建,提示

:-1: error: Unknown module(s) in QT: core5compat

这是因为我没有安装组件,打开Qt安装目录下的MaintenanceTool.exe

image.png

· 使用账号密码登录
· 选择“添加或移除组件”
· 勾选Qt 5 Compatibility Module
image.png

安装后重启Qt,重新构建,一般都可以解决。
但是我出现了一个新的错误:-1: error: Unknown module(s) in QT: core5compat
image.png

这猜测这是因为我之前使用的是Qt6.2.3,而它已被6.2.4所取代,我在添加组件时找不到6.2.3对应的组件,所以我安装了6.2.4的组件,看来这样Qt识别不出来。看来我只能把版本升级到6.2.4了。

修改Qt引擎版本

继续使用MaintenanceTool.exe安装6.2.4的相关组件,安装好之后,重启Qt,打开菜单工具>选项>Kits>Qt Versions

image.png

可以看到Qt已经自动检测到6.2.4
image.png

再选中左侧的项目,右键Desktop Qt 6.2.4 MSVC2019 64bit,将其enable并双击,此时可以看到构建套件已经出现了6.2.4,并触发了自动编译,关于QT: core5compat的报错也消失了。
由此说明,因Qt存在多个版本,选择哪个版本应当小心,来看看我当初安装的6.2.3的说明:
image.png

6.2.3并不是终版,终将被6.2.4所代替。因此,6.2.4出来后,你就没办法再安装6.2.3的组件了。

关于tfUtf8的报错

F:\tgit\qtprojects\quazip-0.7.3\quazip\quagzipfile.cpp:60: error: C2039: "trUtf8": 不是 "QuaGzipFile" 的成员
F:\tgit\qtprojects\quazip-0.7.3\quazip\quagzipfile.h(39): note: 参见“QuaGzipFile”的声明

改成QObject::tr对应的QuaGzipFile::tr即可

关于Permissions的报错

F:\tgit\qtprojects\quazip-0.7.3\quazip\quazipfileinfo.cpp:29: error: C2440: “初始化”: 无法从“int”转换为“QFlags

把下图中的QFile::Permissions perm = 0;


改成QFile::Permissions perm = QFile::Permissions();
image.png

关于created的报错

F:\tgit\qtprojects\quazip-0.7.3\quazip\quazipnewinfo.cpp:137: error: C2039: "created": 不是 "QFileInfo" 的成员
D:\Qt\6.2.3\msvc2019_64\include\QtCore\qfileinfo.h(56): note: 参见“QFileInfo”的声明

把下图中的setFileNTFScTime(fi.created());

image.png

改成setFileNTFScTime(fi.birthTime());
image.png

关于qSort的报错

F:\tgit\qtprojects\quazip-0.7.3\quazip\quazipdir.cpp:393: error: C3861: “qSort”: 找不到标识符
..\..\quazip-0.7.3\quazip\quazipdir.cpp(393): note: “qSort”: 函数声明必须可用,因为所有参数都不依赖于模板参数
..\..\quazip-0.7.3\quazip\quazipdir.cpp(44): note: 此诊断出现在编译器生成的函数“bool QuaZipDirPrivate::entryInfoList(QStringList,QDir::Filters,QDir::SortFlags,TFileInfoList &) const”中

查看官方文档,qSort这个函数只是为了兼容以前老的代码,Qt6现已废弃,需要换成std::qsort

image.png

修改办法是包装一个lambda表达式来使用现有的QuaZipDirComparator,如下图所示:

image.png

然而,这样修改改动有点大,有没有办法简单地修改一下呢?既然std::qsort是为了兼容老的代码,那就直接把它换成std::sort吧,直接把qSort(list.begin(), list.end(), lessThan);这句代码改成std::sort(list.begin(), list.end(), lessThan);即可。如下图所示:
image.png

同样的道理,在子项目qztest中,把qSort(xxx);之类的语句,改成std::sort(xxx.begin(), xxx.end())

其他报错

F:\tgit\qtprojects\quazip-0.7.3\quazip\quazipdir.cpp:393: error: C3861: “qSort”: 找不到标识符
..\..\quazip-0.7.3\quazip\quazipdir.cpp(393): note: “qSort”: 函数声明必须可用,因为所有参数都不依赖于模板参数
..\..\quazip-0.7.3\quazip\quazipdir.cpp(44): note: 此诊断出现在编译器生成的函数“bool QuaZipDirPrivate::entryInfoList(QStringList,QDir::Filters,QDir::SortFlags,TFileInfoList &) const”中

return compressDir(fileCompressed, dir, recursive, 0);改为return compressDir(fileCompressed, dir, recursive, QDir::Filters());
QString::SkipEmptyParts改为Qt::SkipEmptyParts
qrand换成QRandomGenerator,详见qrand、QRandomGenerator
toTime_t换成toSecsSinceEpoch,详见QDateTime::toTime_t

编译成功

以上改完后就可以成功编译了,可以看到生成了对应的dll和lib文件。


image.png

参考资料

  • qmake环境变量手册:https://doc.qt.io/qt-6/qmake-environment-reference.html
  • qmake函数手册:https://doc.qt.io/qt-6/qmake-function-reference.html

你可能感兴趣的:([原创]win10使用Qt6编译Quazip手记)