Tuesday, August 16, 2011

Empty SxS <assembly> tag from VS2008

Symptoms
VS2008 sometimes manages to embed empty manifest into the binaries it builds. Normally this will give you some (at first) strange SxS error when you attempt to run your newly built binary.

Investigation
Using mt.exe we can check out the embedded manifest in the binary
mt.exe -inputresource:myapp.exe -out:foo


Output
In the failing case resulting in this short blurp in foo:

<!--?xml version="1.0" encoding="UTF-8" standalone="yes"?-->
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestversion="1.0"></assembly>

Expected output
You would, however, expect the embedded manifest to look something like the following

<!--?xml version="1.0" encoding="UTF-8" standalone="yes"?-->
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestversion="1.0">
<trustinfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedprivileges>
<requestedexecutionlevel level="asInvoker" uiaccess="false"></requestedexecutionlevel>
</requestedprivileges>
</security>
</trustinfo>
<dependency>
<dependentassembly>
<assemblyidentity type="win32" name="Microsoft.VC90.CRT" version="9.0.nnnnn.mmmmm" processorarchitecture="x86" publickeytoken="1fc8b3b9a1e18e3b"></assemblyidentity>
</dependentassembly>
</dependency>
</assembly>

Examination
This seems to happen only when building files on a networked drive (long story short - I need to). Typically this means your build folders will be on the same networked drive too. As a result, so will the myapp.embed.manifest file that we try to embed.

There's various reasons if you read around on the net, but it all relates to
  1. Incremental linking
  2. and a FAT32 optimization in VS2008 gone haywire
  3. with BIND_TO_CURRENT_CRT
  4. when project files are on a networked drive
I haven't investigated if not using BIND_TO_CURRENT_CRT makes a difference or not, but it might.

Options
There's a few options to avoid this, not all of which may be applicable nor desirable

1. Don't do incremental linking
Will only work for smaller projects.

2. Place cmake files on local disk
Might not be desirable, for various reasons. Dependencies to other projects would be one.

3. Manually embed the correct manifest
Having cmake do a POST_BUILD step, where it runs the cmake equivalent of
mt.exe -verbose  -manifest myapp.embed.manifest  -outputresource:myapp.exe


is really the only safe option IMHO.

So help VS2008 along the way and manually embed your manifest, and you hopefully won't be bothered by that SxS error again...