In my previous post what .prf files are automatically loaded by qmake, you have known that qmake will read a spec file qmake.conf before reading your .pro file. This spec configure file contains many important qmake variables such as MAKEFILE_GENERATOR. The directory C:\Qt\Qt5.12.1\5.12.1\Src\qtbase\mkspecs\ has many sub-directories, each of which corresponds to one spec. The name of the sub-directory is the spec name. Every sub-directory has a qmake.conf in it. The question is: how does qmake know which spec file to load?
When you configure your qt build, you can provide an xplatform option such as:
cd c:\qtbuild c:\Qt\Qt5.12.1\5.12.1\Src\configure.bat -xplatform win32-g++
The xplatform is target platform. In qtConfOutput_prepareSpec in Src/qtbase/configure.pri, the XSPEC variable is set to win32-g++. In qtConfOutput_preparePaths, the content of XSPEC will be written to qt.conf(in the same directory of qmake.exe) as TargetSpec with the replace function printHostPaths:
[Paths] .... TargetSpec=win32-g++ ....
When qmaking your .pro file, the TargetSpec will be read as QMAKE_XSPEC property and set to the m_qmakespec variable in QMakeEvaluator::loadSpec():
qmakespec = propertyValue(ProKey(m_hostBuild ? "QMAKE_SPEC" : "QMAKE_XSPEC")).toQString();
The m_qmakespec will be used in QMakeEvaluator::loadSpecInternal() to find the qmake.conf file of the spec:
QString spec = m_qmakespec + QLatin1String("/qmake.conf");
If you did not provide a xplatform configure option but a device configure option when configuring qt like:
cd c:\qtbuild c:\Qt\Qt5.12.1\5.12.1\Src\configure.bat -device win32-g++
the device name is used as the spec name, i.e., the sub-directory name under C:\Qt\Qt5.12.1\5.12.1\Src\qtbase\mkspecs\. But if you neither provided a xplatform option nor a device option when configuring qt, how does qmake know the correct spec to load? Well, the bat script c:\Qt\Qt5.12.1\5.12.1\Src\configure.bat creates a default version of the qt.conf(alongside qmake.exe) with the following content:
[Paths] ... TargetSpec=dummy HostSpec=win32-g++ ...
The TargetSpec is temporarily set to dummy because configure.bat does not know what target you’ll build. But configure.bat knows the host spec. You can know how configure.bat infers the HostSpec in my post qt configure script. Here, you should understand the difference between host and target. Host is the machine you run the building commands such as mingw32-make or qmake.exe. Target is the outcome of the building. When control is passed from configure.bat to qmake, qmake will edit the qt.conf again to set the correct TargetSpec in qtConfOutput_preparePaths. But since you did not specify device(target device) and xplatform(target platform), qmake will set XSPEC as $$[QMAKE_SPEC], i.e., the HostSpec. This means qmake assumes you will build a target for your host.