_VC80_UPGRADE and Warning RC4005 (IDR_MANIFEST Redefinition)

The _VC80_UPGRADE macro seems to cause some confusion around, as does the warning

'warning RC4005: 'IDR_MANIFEST' : redefinition.'

While it was tempting to try and smear these issues on two posts, fact is they are one. A disk search finds a single reference to both, at afxres.h:

#if defined(_VC80_UPGRADE) && (_VC80_UPGRADE >= 0x0700) && (_VC80_UPGRADE < 0x0800) && defined(IDR_MANIFEST)
  // Handle project upgrade from VC7/VC7.1 for projects with manifest
  #define IDR_MANIFEST    1024

Which still doesn’t remotely pass as documentation. The closest I could find is this Connect reply:

We left this warning deliberately. Our upgrade support manages to make sure that your old project’s manifest doesn’t clash with the manifest that our tools now insert automatically. Our upgrade conversion warns you of this in its conversion log. However, this compile-time warning serves as a reminder that you should remove the manifest entry from your .rc file. When that’s done, you can undefine the _VC80_UPGRADE symbol.

The relevant conversion log snippet, quoted in the connect entry, is somewhere between obscure and misleading:

Due to the requirement that Visual C++ projects produce an embedded (by default) Windows SxS manifest, manifest files in the project are automatically excluded from building with the Manifest Tool. It is recommended that the dependency information contained in any manifest files be converted to “#pragma comment(linker,”<insert dependency here>”)” in a header file that is included from your source code. If your project already embeds a manifest in the RT_MANIFEST resource section through a resource (.rc) file, the line will need to be commented out before the project will build correctly.

Here’s what I make of it all – and this isn’t anywhere near official, so tread with caution.

Conjecture 1: In VC versions from 0x700 (inclusive) to 0x800 (non inclusive), embedding external manifests via resource scripts was either automatic or encouraged (certainly supported) as a way to declare dependencies upon specific assembly versions. From VS2005 (VC 0x800) onwards, the manifest tool automatically generates and embeds such manifests into the built binaries.

Conjecture 2: Judging by the conversion log (‘If your project already embeds a manifest in the … rc file, the line will need to be commented out before the project will build correctly’) , the project upgrade wizard didn’t handle well the conversion of the RT_MANIFEST resource section. Judging by the Connect response (‘Our upgrade …manages to make sure that your old project’s manifest doesn’t clash…’) the upgrade wizard probably did a good job, but for whatever reasons preferred not to delete the RT_MANIFEST section itself.

If you put your heart into it you might reconcile these two phrasings (maybe by ‘build correctly’ they mean with no warnings? Maybe they just made sure the manifests ‘didn’t clash’, but couldn’t decide which was correct?). Doesn’t matter – one way or another MSFT didn’t feel comfortable with auto-upgrading the RC-manifest and sought ways to encourage you to look into it in person.

Conjecture 3: Setting _VC80_UPGRADE to 0x700 and duplicating the definition of IDR_MANIFEST is just MSFT nudging you to peek into your old .RC script, confirm the choices the auto-update made and delete the entire RT_MANIFEST section when you’re done.

If any of this is true (which I can’t verify), it is a weird, weird hack by the VC team. At the very least I would expect some guidance near the (deliberate) warning origin. Even an informative comment – anything more than ‘Handle VC7.0 upgrade’ would be nice – but why not customize the warning?

#if defined(_VC80_UPGRADE) && (_VC80_UPGRADE >= 0x0700) && (_VC80_UPGRADE < 0x0800)
#pragma message("We have reason to believe you are using a custom manifest as an embedded resource. Are you? Please don't. Really. The build process now generates and embeds a manifest automatically and there are better ways to guide it if you must. (Although try not too. It tickles.)")
  #define IDR_MANIFEST    1024

Some Concrete Suggestions

If you did see ‘warning RC4005: ‘IDR_MANIFEST’ redefinition’, don’t ignore it. Inspect your project’s RC file – and specifically the RT_MANIFEST section. If it doesn’t contain any meaningful dependencies – erase it and be done with it. If it does hold some assembly references that you decide you want to keep – migrate them to some modern means: either #pragma comment(linker) as the conversion log suggests (I can’t think of a scenario where that’s the better way, but who knows), or use the /MANIFESTDEPENDENCY liker switch – either at the command line or via project properties, at Linker\Manifest File \Additional Manifest Dependencies.

Whether you saw the warning or not, whether you did migrate manifest settings or not, the _VC80_UPGRADE macro is now just clutter. It arrived at your projects via an added property sheet reference, and the civilized way of clearing it is via View\Property Manager:

The screenshot is from VS2010, and of clearing some embarrassing upgrade clutter from VC6.0 (!). Oh well, better late.

This entry was posted in VC++, Visual Studio. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s