qmake does not generate /SUBSYSTEM:WINDOWS,5.01 in my .vcxproj file



  • I am trying to cross-compile a Qt program for Windows XP on a Windows 7 machine using Visual Studio 2012, following the guidelines at http://blogs.msdn.com/b/vcblog/archive/2012/10/08/10357555.aspx. One of the things that needs to be done, is to use the linker flag /SUBSYSTEM:CONSOLE,5.01 (notice the version number!).

    I have compiled Qt myself (we are still using 4.8.6 and I currently cannot upgrade) and I also have adapted some variables in mkspecs/win32-msvc2012/qmake.conf as follows

    DEFINES                 += UNICODE WIN32 _USING_V110_SDK71_
    QMAKE_CFLAGS            = -nologo -Zm200 -Zc:wchar_t- -arch:IA32
    QMAKE_LFLAGS_CONSOLE    = /SUBSYSTEM:CONSOLE,5.01
    QMAKE_LFLAGS_WINDOWS    = /SUBSYSTEM:WINDOWS,5.01
    

    To illustrate my problem, I have created the following hello world program:

    #include <iostream>
    
    int main()
    {
        std::cout << "Hello World!" << std::endl;
    }
    

    My .pro file simply consists of

    TEMPLATE = app
    SOURCES += subsystem.cpp
    

    I generate a .vcxproj file using the command

    qmake -tp vc -d subsystem.pro
    

    In the qmake debug output, I clearly see the /SUBSYSTEM:WINDOWS,5.01 (including the version number!) in the QMAKE_LFLAGS* variables:

    DEBUG 1: QMAKE_LFLAGS === /NOLOGO :: /DYNAMICBASE :: /NXCOMPAT :: /DEBUG :: /SUBSYSTEM:WINDOWS,5.01 :: "/MANIFESTDEPENDENCY:type='win32' :: name='Microsoft.Windows.Common-Controls' :: version='6.0.0.0' :: publicKeyToken='6595b64144ccf1df' :: language='*' :: processorArchitecture='*'"
    DEBUG 1: QMAKE_LFLAGS_CONSOLE === /SUBSYSTEM:CONSOLE,5.01
    DEBUG 1: QMAKE_LFLAGS_WINDOWS === /SUBSYSTEM:WINDOWS,5.01
    

    so it appears that qmake correctly parsed the .pro file and assigned subsystem version 5.01. However, the 5.01 version number is nowhere in the generated .vcxproj file. All I see
    is

    <Link>
        ...
        <SubSystem>Windows</SubSystem>
        ...
    </Link>
    

    Where I would expect

    <Link>
       ...
       <SubSystem>Windows</SubSystem>
       ...
       <MinimumRequiredVersion>5.01</MinimumRequiredVersion>
       ...
    </Link>
    

    Therefore, when building with msbuild, I get /SUBSYSTEM:WINDOWS as linker option instead of /SUBSYSTEM:WINDOWS,5.01:

    Link:
      C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\bin\link.exe /ERRORREPORT:QUEUE /OUT:"debug\\subsystem.exe" /NOLOGO /LIBPATH:"d:\qt-everywhere-opensource-src-4.8.6-xp\lib" /LIBPATH:"D:\OpenSSL\win32-xp-build" "d:\qt-everywhere-opensource-src-4.8.6-xp\lib\qtmaind.lib" "d:\qt-everywhere-opensource-src-4.8.6-xp\lib\QtGuid4.lib" "d:\qt-everywhere-opensource-src-4.8.6-xp\lib\QtCored4.lib" kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /MANIFEST /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /manifest:embed /DEBUG /PDB:"debug\subsystem.pdb" /SUBSYSTEM:WINDOWS /TLBID:1 /DYNAMICBASE /NXCOMPAT /MACHINE:X86 /SAFESEH "/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" debug\subsystem.obj
      subsystem.vcxproj -> D:\GIT\Qt\tests\subsystem\debug\subsystem.exe
    

    When I let qmake generate Makefiles and compile with nmake instead of generating a .vcxproj file and building with msbuild, I do get the correct linker flag (/SUBSYSTEM:WINDOWS,5.01).

    What can I do to have this 5.01 version also in my .vcxproj and be able to build with msbuild? Upgrading to a higher version of Qt is currently not an option (I know later versions have the -target xp configure option, but i cannot upgrade for now).



  • Hi, if you have problems with getting /SUBSYSTEM:WINDOWS,5.01 stuffed into your .exe file during the build proces, you can also binary edit the .exe file to make it run nicely on XP, check out my blog post



  • Going through the source code of Qt 4.8.6, I find the following snipped of code:

    case 0x78dc00d: // /SUBSYSTEM:{CONSOLE|EFI_APPLICATION|EFI_BOOT_SERVICE_DRIVER|EFI_ROM|EFI_RUNTIME_DRIVER|NATIVE|POSIX|WINDOWS|WINDOWSCE}[,major[.minor]]
        {
            // Split up in subsystem, and version number
            QStringList both = QString(option+11).split(",");
            switch (elfHash(both[0].toLatin1())) {
            case 0x8438445: // CONSOLE
                SubSystem = subSystemConsole;
                break;
            case 0xbe29493: // WINDOWS
                SubSystem = subSystemWindows;
                break;
            // The following are undocumented, so add them to AdditionalOptions
            case 0x240949e: // EFI_APPLICATION
            case 0xe617652: // EFI_BOOT_SERVICE_DRIVER
            case 0x9af477d: // EFI_ROM
            case 0xd34df42: // EFI_RUNTIME_DRIVER
            case 0x5268ea5: // NATIVE
            case 0x05547e8: // POSIX
            case 0x2949c95: // WINDOWSCE
            case 0x4B69795: // windowsce
                AdditionalOptions += option;
                break;
            default:
                found = false;
            }
        }
        break;
    

    Notice that although the major.minor version number is available in both[1] after the string split, it is not being used. I assume that is the reason why I am not seing it in the .vcxproj output, so I guess it's simply not possible with 4.8.6. I have therefore decided to manually add the <MinimumRequiredVersion> element in the generated XML from the .vcxproj once qmake has finished. I'm still open for other elegant solutions however.



  • For what it's worth, qmake in Qt 5.5.1 doesn't seem any better. I would like to set /SUBSYSTEM:WINDOWS,6.1 to specify that only Windows 7 and later are allowed, but qmake is still ignoring the version part when generating the vcxproj.