Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create manifest file for Qt standalone application

I am building a Qt standalone application with static linking following this guide. I followed each step except the last one, which consists of embedding a manifest to the executable, and the application runs fine on a number of machines; I found one, however, where the executable cannot be launched because MSVCP140.dll is missing from the computer. This is error is most probably caused by the fact that I did not include the manifest. Indeed, in the guide above it is clearly written:

[...] you should execute mt.exe to embed a manifest inside the application to avoid error such as missing MSVCP90.dll when the application is started on other computers

My two questions are:

  1. What is the function of the manifest file in this case? Why is it that on some machines the application runs without it while for others it is necessary? From what I know, Visual Studio is installed on none of the computers that were used for the test.
  2. How do I generate such file for my Qt application? I followed the steps of the guide and no .manifest file is automatically generated. Hence, I am assuming that either I missed something when I built the static version of Qt or that I should use some external tool for doing it. For example, I saw that Mage.exe can be used to generate manifests, but I do not know if it's the right way to go in my case.
like image 667
lupod Avatar asked Oct 18 '22 07:10

lupod


1 Answers

If you don't want to redistribute the DLLs, then you need to statically link the CRT into the application. If you had done that, you wouldn't be getting errors about DLLs missing. Your app wouldn't be using the DLLs because it is statically linked.

Note that this is separate from linking to the Qt libraries. You are probably linking those statically, but have forgotten to link the CRT statically.

If you're using Visual Studio, you'll find the appropriate knob here:
     Project → Properties → Configuration → C/C++ → Code Generation → Runtime Library.
For release builds, which you will be distributing, make sure it is set to /MT. Multithreaded is the only available option nowadays. You don't want a "debug" version for release builds, and you don't want the DLL version if you are statically linking. Make sure that all of your projects are set to the same option here, as well as any other static libraries that you link in. Everything needs to use the same version of the CRT in order to avoid compatibility problems.

If you're using a different IDE/compiler toolset, you'll need to consult its documentation to learn how to configure these settings. You don't mention a specific one in the question.

As for the manifest, yes, all Windows applications should include a manifest. Exactly what belongs in your manifest depends on what your application is doing and what Windows features you support. But there is a 99% chance that you want to indicate support for version 6 of the common controls. You will also want to mark yourself as UAC aware. 85% likelihood that you are writing a standard app that does not need administrative privileges, so your manifest will specify asInvoker. Other things can go in the manifest, too, like DPI awareness, Windows version support, etc. The MSDN documentation contains more details, specifically the section on Application Manifests.

A sample manifest for a standard application might look like this:

<?xml version="1.0" encoding="UTF-8"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" manifestVersion="1.0">

  <!-- Enable use of version 6 of the common controls (Win XP and later) -->
  <dependency>
    <dependentAssembly>
      <assemblyIdentity type="win32"
                        name="Microsoft.Windows.Common-Controls"
                        version="6.0.0.0"
                        processorArchitecture="*"
                        publicKeyToken="6595b64144ccf1df"
                        language="*" />
    </dependentAssembly>
  </dependency>

  <!-- Indicate UAC compliance, with no need for elevated privileges (Win Vista and later) -->
  <!-- (if you need enhanced privileges, set the level to "highestAvailable" or "requireAdministrator") -->
  <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
    <security>
      <requestedPrivileges>
        <requestedExecutionLevel level="asInvoker" uiAccess="false" />
      </requestedPrivileges>
    </security>
  </trustInfo>

  <!-- Indicate high API awareness (Win Vista and later) -->
  <!-- (if you support per-monitor high DPI, set this to "True/PM") -->
  <application xmlns="urn:schemas-microsoft-com:asm.v3">
    <windowsSettings>
      <dpiAware xmlns="http://schemas.microsoft.com/SMI/2005/WindowsSettings">true</dpiAware>
    </windowsSettings>
  </application>

  <!-- Declare support for various versions of Windows -->
  <ms_compatibility:compatibility xmlns:ms_compatibility="urn:schemas-microsoft-com:compatibility.v1" xmlns="urn:schemas-microsoft-com:compatibility.v1">
    <ms_compatibility:application>
      <!-- Windows Vista/Server 2008 -->
      <ms_compatibility:supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}" />
      <!-- Windows 7/Server 2008 R2 -->
      <ms_compatibility:supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}" />
      <!-- Windows 8/Server 2012 -->
      <ms_compatibility:supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}" />
      <!-- Windows 8.1/Server 2012 R2 -->
      <ms_compatibility:supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}" />
      <!-- Windows 10 -->
      <ms_compatibility:supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}" />
    </ms_compatibility:application>
  </ms_compatibility:compatibility>

</assembly>

A manifest is a simple text file, following a Microsoft-defined XML schema, that you link into your application's binary using the SDK tools. Specifically, mt.exe does this for you, merging the manifest into the binary. Often this is done at link time. Microsoft's linker will do it for you automatically. I'm not sure about linkers from other vendors. You can certainly call mt.exe to do it for you as a post-build step. It will be on your computer as long as you've installed the Windows SDK. Sample command:

mt.exe -manifest MyApp.exe.manifest -outputresource:MyApp.exe;#1

If you are signing your binary, make sure that you sign after embedding the manifest, as this step (obviously) changes the binary, thus invalidating the signature.

like image 190
Cody Gray Avatar answered Nov 01 '22 09:11

Cody Gray