[原創(chuàng)]win10使用Qt6編譯Quazip手記

前言說明

本文是作者在win10下使用Qt6編譯Quazip的過程記錄,旨在闡明過程中出現(xiàn)的問題,已經解決的思路和方法,不是直截了當?shù)慕坛獭?br> 你可以在這里直接下載已經改造完成的工程。

環(huán)境

· 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. 根據(jù)官網的文檔,執(zhí)行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!

錯誤出現(xiàn)在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,重新執(zhí)行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".

之前的報錯沒有了,但是出現(xiàn)了更多的報錯,根據(jù)提示,看看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",出現(xiàn)一堆報錯
    image.png

    報錯的原因是這個項目是在Qt5環(huán)境下編寫的,很多類型在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,重新構建,一般都可以解決。
但是我出現(xiàn)了一個新的錯誤:-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引擎版本

繼續(xù)使用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并雙擊,此時可以看到構建套件已經出現(xiàn)了6.2.4,并觸發(fā)了自動編譯,關于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<QFileDevice::Permission>”

把下圖中的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”: 函數(shù)聲明必須可用,因為所有參數(shù)都不依賴于模板參數(shù)
..\..\quazip-0.7.3\quazip\quazipdir.cpp(44): note: 此診斷出現(xiàn)在編譯器生成的函數(shù)“bool QuaZipDirPrivate::entryInfoList(QStringList,QDir::Filters,QDir::SortFlags,TFileInfoList &) const”中

查看官方文檔qSort這個函數(shù)只是為了兼容以前老的代碼,Qt6現(xiàn)已廢棄,需要換成std::qsort

image.png

修改辦法是包裝一個lambda表達式來使用現(xiàn)有的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”: 函數(shù)聲明必須可用,因為所有參數(shù)都不依賴于模板參數(shù)
..\..\quazip-0.7.3\quazip\quazipdir.cpp(44): note: 此診斷出現(xiàn)在編譯器生成的函數(shù)“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,詳見qrandQRandomGenerator
toTime_t換成toSecsSinceEpoch,詳見QDateTime::toTime_t

編譯成功

以上改完后就可以成功編譯了,可以看到生成了對應的dll和lib文件。


image.png

參考資料

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容