Here are a few small modifications I needed to make to get Qt 5.15.17 to build with MSVC when configured to use C++23 (i.e., configure.bat -c++std c++2b/cl.exe /std:c++latest).
Qt 5 refers to C++20 as c++2a and C++23 as c++2b (holdovers from before they were published).
If you don't care about the details, you can just apply the attached patches. Note that there may be other issues I haven't encountered, since I try to disable all Qt functionality I'm not actively using.
I am using Visual Studio 2022, but I assume this mostly applies to Visual Studio 2019 (and probably also future versions). Specifically, I have Visual Studio Professional 2022 version 17.14.11 with cl.exe version 19.44.35214 (x64).
While I have only personally encountered these issues building Qt 5.15.15 and later, some have reports dating back to Qt 5.9.
These instructions reflect my experience building a minimal set of Qt modules with many features disabled. If you enable additional components (like Bluetooth or WebEngine), you may encounter related or entirely new issues. Also, mixing C++ standard versions across modules might lead to subtle binary incompatibilities; use a consistent standard when possible. Follow this guide at your own risk.
There are issues building QtScript/QtScriptTools with C++20 and newer.
The 3rd party JavaScriptCore code uses std::auto_ptr, which was removed in C++17. The Qt build system already accounts for C++17—but not C++20 or C++23.
To fix this, edit qtscript\src\script\script.pro, replacing the line
CONFIG -= c++1z(which disables C++17) with
CONFIG -= c++1z c++2a c++2b(which additionally disables C++20 and C++23).
I can't say for sure that this doesn't result in other, much subtler issues (e.g., ABI incompatibility), but given that C++17 was already being disabled in the same way, I think it's fine.
I am currently not encountering errors here because I have Qt Location disabled (-skip qtlocation). However, my notes indicate that the 3rd party mapbox-gl-native code suffers from the same issue as QtScript: it includes Boost 1.65.1, which uses std::auto_ptr.
The fix is also the same: add c++2a and c++2b to the CONFIG -= line in the .pro file.
The relevant line is mapbox-gl-native.pro:6.
Note that Qt itself never seems to use auto_ptr; rather, it's always in third-party code.
This problem occurs when the /permissive- compiler option is set—and it's implicitly set by /std:c++latest (and /std:c++20).
Some code in qfunctions_winrt.h is broken with /permissive- because it tries to use IAsyncInfo and AsyncStatus when they haven't been declared.
This is not usually a problem because the code in question is hidden behind the Q_OS_WINRT macro, which is not set for desktop Windows. However, certain files—in particular, qwasapiutils.cpp—explicitly define Q_OS_WINRT.
It's also defined in qlowenergycontroller_winrt_new.cpp, which is built when qtConfig(winrt_bt) is true. Since I disabled Bluetooth support, I don't know if the problem would have appeared there. Regardless, the change provided below should fix it everywhere.
The problem can be resolved by including an additional header that defines the missing types.
Simply open qtbase\src\corelib\kernel\qfunctions_winrt.h (not qtbase\include\QtCore\qfunctions_winrt.h, which just includes the former) and add the following line after #ifdef Q_OS_WINRT (line 78 in Qt 5.15.17):
#include <asyncinfo.h>As this 2018 Microsoft Developer Community post shows, the same problem arises when /permissive- is used. And while I don't set that flag, it's implied by newer C++ /std options. From the /permissive- documentation:
The
/permissive-option is implicitly set by the/std:c++latestoption starting in Visual Studio 2019 version 16.8, and in version 16.11 by the/std:c++20option.
The documentation states that it can be overridden with an explicit /permissive after the last relevant /std, but I didn't think that was a desirable/sustainable solution. (You might have to apply the fix to consumers of the Qt library.)
My solution is basically the same as the one given by Microsoft employee Leo Zhang in the Developer Community thread: including asyncinfo.h, which provides AsyncStatus and IAsyncInfo. While Zhang includes it just after the block of Qt includes, I chose to put it inside the Q_OS_WINRT section. (I seem to be the only one doing that, so it's probably wrong somehow... but it also probably doesn't matter.)
Note that asyncinfo.h can include windows.h, but since we are including it after QtCore/qt_windows.h, it has already been included (with NOMINMAX defined).
A patch was proposed in 2017 that doesn't seem to have gone anywhere. It adds asyncinfo.h just after the block of Qt headers (inside Q_OS_WIN but outside Q_OS_WINRT). Possibly unrelatedly, it adds wrl.h while removing the forward declaration of Microsoft::WRL::ComPtr<T>. A comment indicates there may be prerequisites for asyncinfo.h but gives no further information.
(The patch also adds QtCore/QCoreApplication, but that seems to have been done separately at some point before 5.15.15.)
Commit 45b0f1b (Remove winrt) renames the header to qfunctions_winrt_p.h (making it private) and removes the Q_OS_WINRT check entirely. It adds includes for wrl.h and windows.foundation.h and refers to IAsyncInfo via ABI::Windows::Foundation::IAsyncInfo. It still uses the unqualified AsyncStatus, though.
The author of the Developer Community post also filed QTBUG-61119. The response was essentially "don't use /permissive-." Related attempts to fix the issue were abandoned: 228932 and 228919 (an attempt to get -permissive- working).
qfunctions_winrt.h error text, in case anyone is searching for it
qt-everywhere-src-5.15.17\qtbase\include\QtCore\../../src/corelib/kernel/qfunctions_winrt.h(176): error C2065: 'IAsyncInfo': undeclared identifier (compiling source file qt-everywhere-src-5.15.17\qtmultimedia\src\plugins\wasapi\qwasapiutils.cpp) qt-everywhere-src-5.15.17\qtbase\include\QtCore\../../src/corelib/kernel/qfunctions_winrt.h(181): error C2065: 'AsyncStatus': undeclared identifier (compiling source file qt-everywhere-src-5.15.17\qtmultimedia\src\plugins\wasapi\qwasapiutils.cpp) qt-everywhere-src-5.15.17\qtbase\include\QtCore\../../src/corelib/kernel/qfunctions_winrt.h(181): error C3878: syntax error: unexpected token 'status' following 'expression' (compiling source file qt-everywhere-src-5.15.17\qtmultimedia\src\plugins\wasapi\qwasapiutils.cpp) qt-everywhere-src-5.15.17\qtbase\include\QtCore\../../src/corelib/kernel/qfunctions_winrt.h(187): error C2065: 'status': undeclared identifier (compiling source file qt-everywhere-src-5.15.17\qtmultimedia\src\plugins\wasapi\qwasapiutils.cpp) qt-everywhere-src-5.15.17\qtbase\include\QtCore\../../src/corelib/kernel/qfunctions_winrt.h(187): error C2065: 'status': undeclared identifier (compiling source file qt-everywhere-src-5.15.17\qtmultimedia\src\plugins\wasapi\qwasapiutils.cpp) qt-everywhere-src-5.15.17\qtbase\include\QtCore\../../src/corelib/kernel/qfunctions_winrt.h(187): error C2065: 'AsyncStatus': undeclared identifier (compiling source file qt-everywhere-src-5.15.17\qtmultimedia\src\plugins\wasapi\qwasapiutils.cpp) qt-everywhere-src-5.15.17\qtbase\include\QtCore\../../src/corelib/kernel/qfunctions_winrt.h(197): error C2065: 'status': undeclared identifier (compiling source file qt-everywhere-src-5.15.17\qtmultimedia\src\plugins\wasapi\qwasapiutils.cpp) qt-everywhere-src-5.15.17\qtbase\include\QtCore\../../src/corelib/kernel/qfunctions_winrt.h(197): error C2065: 'status': undeclared identifier (compiling source file qt-everywhere-src-5.15.17\qtmultimedia\src\plugins\wasapi\qwasapiutils.cpp) qt-everywhere-src-5.15.17\qtbase\include\QtCore\../../src/corelib/kernel/qfunctions_winrt.h(197): error C2065: 'AsyncStatus': undeclared identifier (compiling source file qt-everywhere-src-5.15.17\qtmultimedia\src\plugins\wasapi\qwasapiutils.cpp) qt-everywhere-src-5.15.17\qtbase\include\QtCore\../../src/corelib/kernel/qfunctions_winrt.h(209): error C2065: 'status': undeclared identifier (compiling source file qt-everywhere-src-5.15.17\qtmultimedia\src\plugins\wasapi\qwasapiutils.cpp) qt-everywhere-src-5.15.17\qtbase\include\QtCore\../../src/corelib/kernel/qfunctions_winrt.h(209): error C2065: 'status': undeclared identifier (compiling source file qt-everywhere-src-5.15.17\qtmultimedia\src\plugins\wasapi\qwasapiutils.cpp) qt-everywhere-src-5.15.17\qtbase\include\QtCore\../../src/corelib/kernel/qfunctions_winrt.h(209): error C2065: 'AsyncStatus': undeclared identifier (compiling source file qt-everywhere-src-5.15.17\qtmultimedia\src\plugins\wasapi\qwasapiutils.cpp) qt-everywhere-src-5.15.17\qtbase\include\QtCore\../../src/corelib/kernel/qfunctions_winrt.h(217): error C2065: 'status': undeclared identifier (compiling source file qt-everywhere-src-5.15.17\qtmultimedia\src\plugins\wasapi\qwasapiutils.cpp) qt-everywhere-src-5.15.17\qtbase\include\QtCore\../../src/corelib/kernel/qfunctions_winrt.h(217): error C2065: 'AsyncStatus': undeclared identifier (compiling source file qt-everywhere-src-5.15.17\qtmultimedia\src\plugins\wasapi\qwasapiutils.cpp)
You can significantly speed up the build by using jom instead of NMAKE. It can be found at qt.io. Put the executable (jom.exe) somewhere in your PATH. Use the jom command exactly as you would nmake—with the exception that you can specify how many parallel processes to use with /J.
While you can pass -make-tool jom to configure.bat, that only controls how qmake is built. You still have to run jom yourself to build everything else.
Note that I think I ran into problems trying to build docs (jom docs) in parallel, so I use NMAKE for that. Makefiles not designed with parallel processing in mind sometimes contain race conditions or other bugs. But building and installing Qt (jom, jom install) seems to work fine.
If you want your Qt installation to be detected by various tools, create a file named qt.conf in the bin directory containing:
[Paths]
Prefix=..