准备工作:
1. 在Qt官网下载Qt库的源码。
qt-opensource-windows-x86-msvc2015_64-5.6.0.exe
安装过程中选择需要源代码。
2.下载并安装Python。
3. 下载并安装Perl。
4. 下载并安装Ruby。版本对应如下:
命令行下进入QT源码:
configure -prefix "D:\Qt5.6.0\5.6\msvc2022_64_static" -static -static-runtime -release -nomake examples -nomake tests -skip qtwebengine -opensource -confirm-license -qt-pcre -qt-pcre -qt-freetype –opengl desktop -opengl es2
其中由于QT5.6与VS2022有些地方不匹配,nmake会报下列错误。
D:\Qt5.6.0\5.6\Src\qtbase\src\tools\qlalr
compress.cpp
.\compress.cpp(45): error C2039: "binary_function": 不是 "std" 的成员
e:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\iostream(18): note: 参见“std ”的声明
.\compress.cpp(45): error C2504: “binary_function”: 未定义基类
.\compress.cpp(45): error C2143: 语法错误: 缺少“,”(在“<”的前面)
.\compress.cpp(53): error C2039: "binary_function": 不是 "std" 的成员
e:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\iostream(18): note: 参见“std ”的声明
.\compress.cpp(53): error C2504: “binary_function”: 未定义基类
.\compress.cpp(53): error C2143: 语法错误: 缺少“,”(在“<”的前面)
.\compress.cpp(143): error C2039: "binary_function": 不是 "std" 的成员
e:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\include\iostream(18): note: 参见“std ”的声明
.\compress.cpp(143): error C2504: “binary_function”: 未定义基类
.\compress.cpp(143): error C2143: 语法错误: 缺少“,”(在“<”的前面)
解决方法:
只需要在源码compress.cpp中添加:
#include<functional>
D:\Qt5.6.0\5.6\Src\qtbase\src\testlib\ testlib.pro
qtesttable.cpp
.\qtesttable.cpp(135): error C2039: "unary_function": 不是 "std" 的成员
只需要在源码中添加:
#include<functional>
D:\Qt5.6.0\5.6\Src\qtdeclarative\src\src.pro
..\3rdparty\masm\wtf/MathExtras.h(157): error C2169: “log2”: 内部函数,不能定义
..\3rdparty\masm\wtf/MathExtras.h(163): error C2169: “log2f”: 内部函数,不能定义
..\3rdparty\masm\wtf/MathExtras.h(215): error C2169: “lrint”: 内部函数,不能定义
将这三个函数注释掉。
D:\Qt5.6.0\5.6\Src\qt3d\src\core\core.projobs\dependencyhandler.cpp(63): error C2039: "unary_function": 不是 "std" 的成员
D:\Qt5.6.0\5.6\Src\qtbase\include\QtCore\../../src/corelib/tools/qarraydatapointer.h(208): note: 参见“std”的声明
jobs\dependencyhandler.cpp(63): error C2504: “unary_function”: 未定义基类
jobs\dependencyhandler.cpp(63): error C2143: 语法错误: 缺少“,”(在“<”的前面)
jobs\dependencyhandler.cpp(80): error C2039: "unary_function": 不是 "std" 的成员
D:\Qt5.6.0\5.6\Src\qtbase\include\QtCore\../../src/corelib/tools/qarraydatapointer.h(208): note: 参见“std”的声明
jobs\dependencyhandler.cpp(80): error C2504: “unary_function”: 未定义基类
jobs\dependencyhandler.cpp(80): error C2143: 语法错误: 缺少“,”(在“<”的前面)
jobs\dependencyhandler.cpp(91): error C2039: "binary_function": 不是 "std" 的成员
D:\Qt5.6.0\5.6\Src\qtbase\include\QtCore\../../src/corelib/tools/qarraydatapointer.h(208): note: 参见“std”的声明
jobs\dependencyhandler.cpp(91): error C2504: “binary_function”: 未定义基类
jobs\dependencyhandler.cpp(91): error C2143: 语法错误: 缺少“,”(在“<”的前面)
解决方法:
只需要在源码中添加:
#include<functional>
完成上述修改后,
nmake
nmake install
得到QT5.6的静态库。
然后在VS2022中利用QT_VS_TOOLS设置。
这里有个大坑,我之前由于Qt在编译的时候将生成的库修改了文件夹名称发现在VS2015中QT VS TOOLS ADD VERSIONS完成后关闭后总是没有了,开始以为是QT_VS_TOOLS出问题了,卸载后下载低版本仍然是这个问题,VS2022中提示信息中绝对路径明显是我修改之前的路径,我才意识到问题所在,打开IDA发现果然将绝对路径写在qmake.exe中。
当使用qmake xxxx.pro生成的Makefile会使用库文件中写死的SDK安装路径(configure的-prefix参数指定的),这导致必须将SDK安装到特定的路径下不然找不到编译好的Qt库(可以利用qt.conf 文件进行修改,详见:https://blog.csdn.net/BGK112358/article/details/103321938)。
这也就是QT VS TOOLS ADD VERSIONS失败的原因。
VS2022中直接链接VS2015编译的QT静态库,同样首先需要在VS2022下重新编译libffi库,编译VMP成功。
严重性 | 代码 | 说明 | 项目 | 文件 | 行 | 禁止显示状态 | 详细信息 |
错误 | LNK1181 | 无法打开输入文件“dxguid.lib” | VMProtect | E:\vmp_vs2022\vmp\vcproj\LINK | 1 |
但是VS2022中链接VS2022编译的QT静态库,编译VMP会出现很多BUG:
BUG1:
1>LINK : fatal error LNK1181: 无法打开输入文件“dxguid.lib”
原因是VS2022我没有安装SDK,简单省事的办法,安装directx SDK,然后将其路径添加到LIB库路径。下。
BUG2:
严重性 | 代码 | 说明 | 项目 | 文件 | 行 | 禁止显示状态 | 详细信息 |
错误 | LNK2001 | 无法解析的外部符号 __std_find_trivial_8 | VMProtect | E:\vmp_vs2022\vmp\vcproj\Qt5Gui.lib(qopenglshaderprogram.obj) | 1 | ||
严重性 | 代码 | 说明 | 项目 | 文件 | 行 | 禁止显示状态 | 详细信息 |
错误 | LNK2001 | 无法解析的外部符号 __CxxFrameHandler4 | VMProtect | E:\vmp_vs2022\vmp\vcproj\Qt5Core.lib(qmimemagicrule.obj) | 1 |
该问题产生的原因是:微软为了用于减小 x64 上 C++ 异常处理(try/catch 和自动析构函数)的二进制大小。我为用于C++异常处理的数据开发了新的格式和处理,称为 FH4(__CxxFrameHandler4见下文),它比现有实现小 ~60%,从而为大量使用C++异常处理的程序总体二进制文件减少了 20%。在较新的 VS 版本中手动指定旧版本的VS(平台工具集),使用较新版本的 Visual Studio(默认使用)构建的链接(静态)库,可能会导致链接错误“未解析的外部符号FH3FH3FH4__CxxFrameHandler4"
解决方法是:
VS2019->Properties->C/C++->Command Line add ‘-d2FH4-‘
VS2019->Properties->Linker->Command Line add ‘-d2:-FH4-‘
我按照这个办法试验发现仍然不解决问题。
禁止在 VS 16.3+ 上使用 __CxxFrameHandler4(仅限 x64)https://developercommunity.visualstudio.com/content/problem/746534/visual-c-163-runtime-uses-an-unsupported-api-for-u.html
add_compile_flags(“/Zc:threadSafeInit-”)
if(ARCH STREQUAL “amd64” 和 MSVC_VERSION GREATER 1922)
add_compile_flags(“/d2FH4-”)
add_link_options(“/d2:-FH4-”)
#生成警告级别 3
add_compile_flags(“/W3”)
原因应该是VS2022下编译QT静态库时使用了__CxxFrameHandler4,或者VS2022有新的特性,为此,我更改工程平台工具集VS2022(V143),重新编译。
报错BUG3:
watermarks_window.obj : error LNK2001: 无法解析的外部符号 "class std::vector<struct PROCESS_ITEM,class std::allocator<struct PROCESS_ITEM> > __cdecl os::K32EnumProcesses(void)" (?K32EnumProcesses@os@@YA?AV?$vector@UPROCESS_ITEM@@V?$allocator@UPROCESS_ITEM@@@std@@@std@@XZ)
void WatermarksWindow::processEditDropDown()
std::vector<PROCESS_ITEM> processes = os::EnumProcesses();
错误原因在于Windows psapi.h中默认将EnumProcesses定义为宏K32EnumProcesses函数,解决方法:
将EnumProcesses重新命名为其它名称,解决该问题。
BUG4:
3>libGLESv2.lib(libGLESv2.obj) : error LNK2005: glBindTexture 已经在 Opengl32.lib(OPENGL32.dll) 中定义
3>libGLESv2.lib(libGLESv2.obj) : error LNK2005: glBlendFunc 已经在 Opengl32.lib(OPENGL32.dll) 中定义
3>libGLESv2.lib(libGLESv2.obj) : error LNK2005: glClear 已经在 Opengl32.lib(OPENGL32.dll) 中定义
3>libGLESv2.lib(libGLESv2.obj) : error LNK2005: glClearColor 已经在 Opengl32.lib(OPENGL32.dll) 中定义
3>libGLESv2.lib(libGLESv2.obj) : error LNK2005: glClearStencil 已经在 Opengl32.lib(OPENGL32.dll) 中定义
3>libGLESv2.lib(libGLESv2.obj) : error LNK2005: glColorMask 已经在 Opengl32.lib(OPENGL32.dll) 中定义
3>libGLESv2.lib(libGLESv2.obj) : error LNK2005: glCopyTexImage2D 已经在 Opengl32.lib(OPENGL32.dll) 中定义
解决该问题时,也走了很多弯路,最开始想的是工程只链接libGLESv2.lib或者Opengl32.lib,后来发现会导致其它错误,回忆了一下VS2015下没有这个问题,区别就是产生libGLESv2.lib的方法是-share参数,而且没有支持opengl,直接将VS2015编译生成的libEGL.lib和libGLESv2.lib拷贝过来,发现果然不报错误了。为了验证,在VS2022下configure -prefix "D:\Qt5.6.0\5.6\msvc2022_64_static2" -shared -release -nomake examples -nomake tests -skip qtwebengine -opensource -confirm-license
重新生成SDK静态库,但是发现必须需要libEGL.dll和libGLESv2.dll文件才能运行EXE(利用VS2015的libEGL.lib和libGLESv2.lib文件同样有这个问题),看来这个问题与VS2015和VS2022这个两个开发环境下支持OpenGL有关系了,收工了。