[cmake-developers] [PATCH] [CMake 0015674]: Windows: Correctly determine Windows version

James Johnston JamesJ at motionview3d.com
Fri Sep 18 14:58:37 EDT 2015


> -----Original Message-----
> From: cmake-developers [mailto:cmake-developers-bounces at cmake.org]
> On Behalf Of Brad King
> Sent: Friday, September 18, 2015 18:24
> To: Gilles Khouzam
> Cc: cmake-developers at cmake.org
> Subject: Re: [cmake-developers] [PATCH] [CMake 0015674]: Windows:
> Correctly determine Windows version
> 
> On 09/10/2015 07:24 PM, Gilles Khouzam wrote:
> > This patch adds a simple version manifest
> > Source\cmake.version.manifest to the CMake executables.
> 
> After working out the support for manifests across all generators as
> discussed elsewhere in this thread, I've added your manifest file to
CMake's
> own build:
> 
>  Windows: Fix CMAKE_HOST_SYSTEM_VERSION on Windows >= 8 (#15674)
>  http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=cdd15551

While on the subject, there are some other additions to the manifest you
might want to consider.

    <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
        <security>
            <requestedPrivileges>
                <requestedExecutionLevel level="asInvoker"
uiAccess="false"/>
            </requestedPrivileges>
        </security>
    </trustInfo>

The above block will disable UAC heuristics on Windows Vista and above, such
that elevation won't ever be requested.  It will also disable the Program
Compatibility Assistant for Vista IIRC.  (as I understand it, supportedOS
wasn't added until Windows 7.  Why there is a GUID in there for Vista, I'm
not sure.  App manifests are not the best documented thing on MSDN IMHO.)
It would probably be appropriate to use this for all CMake executables.

    <dependency>
        <dependentAssembly>
            <assemblyIdentity
                type="win32"
                name="Microsoft.Windows.Common-Controls"
                version="6.0.0.0"
                processorArchitecture="*"
                publicKeyToken="6595b64144ccf1df"
                language="*"
            />
        </dependentAssembly>
    </dependency>

The above block will declare a preference to use the newer common controls
library introduced with Windows XP.  Without this, Windows will fall back on
the old Windows 2000 era of common controls (i.e. Windows 95 style buttons).
This would be appropriate for cmake-gui.  Since it uses Qt though, the
effect is probably minimal, but if some API were called such that native
Win32 controls were used somewhere, this would improve the appearance.

<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0"
xmlns:asmv3="urn:schemas-microsoft-com:asm.v3">
    <asmv3:application>
        <asmv3:windowsSettings
xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">
            <dpiAware>True/PM</dpiAware>
        </asmv3:windowsSettings>
    </asmv3:application>
</assembly>

The above block will make the cmake-gui DPI aware, such that DPI
virtualization is disabled on Windows Vista and above.  In laymen's terms,
it fixes "blurry text".  It looks like Qt already does this (I just tested
CMake 3.3 on a high DPI profile.)  See http://doc.qt.io/qt-5/highdpi.html.
Probably they do it by calling the SetProcessDpiAwareness function.
However, this API has some caveats; from MSDN:

" The SetProcessDPIAware function in Windows Vista and later versions sets
the current process as DPI-aware. However, the use of the SetProcessDPIAware
function is discouraged. For example, if a DLL caches DPI settings during
initialization, invoking SetProcessDPIAware in your application might
generate a possible race condition. For this reason, we recommend that an
application enable DPI awareness by using the application's assembly
manifest rather than by calling SetProcessDPIAware." ---
https://msdn.microsoft.com/en-us/library/windows/desktop/dn469266(v=vs.85).a
spx

And also:

" If you use the SetProcessDpiAwareness method to set the DPI awareness
level, you must call SetProcessDpiAwareness prior to any Win32API call that
forces the system to begin virtualization."

The safer path seems to me to be put it in the manifest, as recommended by
MSFT.  Note there are two possible values:  "True" and "True/PM".  "PM"
stands for per-monitor DPI aware (introduced with Windows 8.1).  Looks like
Qt supports PM now, but since it was introduced in Windows 8.1, probably
only very recent versions of Qt.  You'd have to be careful what is in the
manifest agrees with the version of Qt being used. (e.g. you don't want to
declare "True/PM" on a non-PM older version of Qt, else no per-monitor
scaling would happen at all - virtualized or otherwise).

Since Qt does call SetProcessDPIAware and cmake-gui does seem to scale OK
right now, including this block may end up being a little "pointless" in
practice, despite the caveats from MSDN above.

    <assemblyIdentity
        name="HelloWorld"
        version="0.0.0.0"
        type="win32"/>

Finally there is this block; I'm not exactly sure which versions of Windows
might actually require this or what.  I'm a little fuzzy on why I included
it.  Most of the built-in Windows accessories seem to have this in their
manifests though.  IIRC it's especially needed with the common controls
manifest block.

Best regards,

James Johnston



More information about the cmake-developers mailing list