Embed manifest with makefiles in VS2005
It is pointed out to me that MSDN example on how to embed manifest is focused on changes into one makefile. If you have several makefiles, then it is too much work to change all of them. While our doc writing team is triaging bug for an update to MSDN example, let me briefly describe how how to change this sample if you have many makefiles.
But before I would like to mention that direct embedding of manifest into binary using mt.exe, for example, following steps described here breaks incremental linking and edit and continue. If you change final binary generated by the linker with mt.exe, on the next change to source code the linker will do a full link instead of just linking in objects for modified source to the existing binary. So if you do care about incremental linking, you need embed manifest as a resource.
Anyway, so let's say you have a 100 of makefiles and you need to update all of them to embed manifest. Assuming your original makefiles similar to ones described in MSDN example, you need to do the following :
1) Create makefile.inc (see below, also attached to this post).
2) Create makefile.targ.inc (see below, , also attached to this post).
3) Include makefile.inc and makefile.targ.inc into existing makefiles (see below)
4) Add two lines into existing makefiles for link and clean steps (see below)
Now these steps in more details:
1) Create a makefile.inc which will be included in other files later on. Here is the file (copying lines from MSDN sample):
####################################################################################
# makefile.inc Include this file into existing makefile at the very top
####################################################################################
# Step 1. Adding _VC_MANIFEST_INC to specify which build is incremental (1 - incremental)
# Step 2. Adding _VC_MANIFEST_BASENAME used to specify name of a temporary resource file
####################################################################################
!if "$(DEBUG)" == "1"
CPPFLAGS=$(CPPFLAGS) /MDd
LFLAGS=$(LFLAGS) /INCREMENTAL
_VC_MANIFEST_INC=1
_VC_MANIFEST_BASENAME=__VC80.Debug
!else
CPPFLAGS=$(CPPFLAGS) /MD
_VC_MANIFEST_INC=0
_VC_MANIFEST_BASENAME=__VC80
!endif
####################################################################################
# Step 3. Specifying name of temporary resource file used only in incremental builds
####################################################################################
!if "$(_VC_MANIFEST_INC)" == "1"
_VC_MANIFEST_AUTO_RES=$(_VC_MANIFEST_BASENAME).auto.res
!else
_VC_MANIFEST_AUTO_RES=
!endif
####################################################################################
#Step 4. Adding _VC_MANIFEST_EMBED_EXE - command to embedd manifest to EXE
####################################################################################
!if "$(_VC_MANIFEST_INC)" == "1"
#MT_SPECIAL_RETURN=1090650113
#MT_SPECIAL_SWITCH=-notify_resource_update
MT_SPECIAL_RETURN=0
MT_SPECIAL_SWITCH=
_VC_MANIFEST_EMBED_EXE= \
if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
link $** /out:$@ $(LFLAGS)
!else
_VC_MANIFEST_EMBED_EXE= \
if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
!endif
####################################################################################
#Step 5. Adding _VC_MANIFEST_EMBED_DLL - command to embedd manifest into DLL
####################################################################################
!if "$(_VC_MANIFEST_INC)" == "1"
MT_SPECIAL_RETURN=1090650113
MT_SPECIAL_SWITCH=-notify_update
_VC_MANIFEST_EMBED_DLL= \
if exist $@.manifest mt.exe -manifest $@.manifest -out:$(_VC_MANIFEST_BASENAME).auto.manifest $(MT_SPECIAL_SWITCH) & \
if "%ERRORLEVEL%" == "$(MT_SPECIAL_RETURN)" \
rc /r $(_VC_MANIFEST_BASENAME).auto.rc & \
link $** /out:$@ $(LFLAGS)
!else
_VC_MANIFEST_EMBED_DLL= \
if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
!endif
####################################################################################
# Step 6. Adding _VC_MANIFEST_CLEAN - command to clean resources files generated temporarily
####################################################################################
!if "$(_VC_MANIFEST_INC)" == "1"
_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
$(_VC_MANIFEST_BASENAME).auto.rc \
$(_VC_MANIFEST_BASENAME).auto.manifest
!else
_VC_MANIFEST_CLEAN=
!endif
# End of makefile.inc
####################################################################################
2) Create a makefile.targ.inc which will be included in existing makefileslater on. Here is the file (copying lines from MSDN sample):
####################################################################################
# makefile.targ.inc - include this at the very bottom of the existing makefile
####################################################################################
# Step 7. Adding commands to generate initial empty manifest file, RC file
# that references it and for generating the .res file
####################################################################################
$(_VC_MANIFEST_BASENAME).auto.res : $(_VC_MANIFEST_BASENAME).auto.rc
$(_VC_MANIFEST_BASENAME).auto.rc : $(_VC_MANIFEST_BASENAME).auto.manifest
type <<$@
#include <winuser.h>
1RT_MANIFEST"$(_VC_MANIFEST_BASENAME).auto.manifest"
<< KEEP
$(_VC_MANIFEST_BASENAME).auto.manifest :
type <<$@
<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
</assembly>
<< KEEP
# end of makefile.targ.inc
####################################################################################
3) Include makefile.inc and makefile.targ.inc into existing makefiles
####################################################################################
#include makefile.inc. Add full path if necessary
!include makefile.inc
!if "$(DEBUG)" == "1"
CPPFLAGS=$(CPPFLAGS) /MDd
LFLAGS=$(LFLAGS) /INCREMENTAL
!else
CPPFLAGS=$(CPPFLAGS) /MD
!endif
MyApplication.exe : MyApplication.obj
link $** /out:$@ $(LFLAGS)
MyApplication.obj : MyApplication.cpp
clean :
del MyApplication.obj MyApplication.exe
####################################################################################
#include makefile.targ.inc. Add full path if necessary
!include makefile.targ.inc
4) Add two lines (in red) into existing makefiles for link step (for EXEs)
####################################################################################
#include makefile.inc. Add full path if necessary
!include makefile.inc
!if "$(DEBUG)" == "1"
CPPFLAGS=$(CPPFLAGS) /MDd
LFLAGS=$(LFLAGS) /INCREMENTAL
!else
CPPFLAGS=$(CPPFLAGS) /MD
!endif
MyApplication.exe : MyApplication.obj
link $** /out:$@ $(LFLAGS)
$(_VC_MANIFEST_EMBED_EXE)
MyApplication.obj : MyApplication.cpp
clean :
del MyApplication.obj MyApplication.exe
$(_VC_MANIFEST_CLEAN)
####################################################################################
#include makefile.targ.inc. Add full path if necessary
!include makefile.targ.inc
For DLLs, you have to do similar change. Here is a changed makefile for a DLL using makefile from MSDN sample:
####################################################################################
#include makefile.inc. Add full path if necessary
!include makefile.inc
!if "$(DEBUG)" == "1"
CPPFLAGS=$(CPPFLAGS) /MDd
LFLAGS=$(LFLAGS) /DLL /INCREMENTAL
!else
CPPFLAGS=$(CPPFLAGS) /MD
LFLAGS=$(LFLAGS) /DLL
!endif
MyLibrary.dll : MyLibrary.obj
link $** /out:$@ $(LFLAGS)
$(_VC_MANIFEST_EMBED_DLL)
MyLibrary.obj : MyLibrary.cpp
clean :
del MyLibrary.obj MyLibrary.dll
$(_VC_MANIFEST_CLEAN)
####################################################################################
#include makefile.targ.inc. Add full path if necessary
!include makefile.targ.inc
This should do it. Please beware of formatting changes when I convert makefiles from TXT to HTML on this page. This is why I am attaching both makefile.inc and makefile.targ.inc to this post also.
Thanks to Sridhar and Zach for pointing out problem with MSDN sample and providing sample code for the change.
[06/30/2006] Thanks to Bern McCarty for pointing out that MSDN sample has been changed and my reference to it for definition of _VC_MANIFEST_EMBED_DLL is not valid anymore. I have updated the sample and makefiles in the attached zip.
makefile.inc and makefile.targ.inc.zip
Comments
Anonymous
May 21, 2006
With VC 2005 the native libraries such as the CRT, MFC, and ATL can now be installed as Side by Side...Anonymous
January 15, 2007
The comment has been removedAnonymous
January 16, 2007
Hi, I am not surprised that MSDN example has more information. My post is from the time when MSDN example was not even written up. Example described in this post eventually ended up as a starting point for the topic on MSDN, however as you have noticed MSDN has more information about that. NikolaAnonymous
July 10, 2007
hi if anyone can tell me how to create and embed the manifest file for dll where i am using the iexplore for calling the dll thanx in advance.Anonymous
August 02, 2007
I have been trying to work through manifest related issues with VC2005 and Longhorn for hours today. I have to say this is one of the more frustrating experiences I'd had to deal with in years. I'm not sure what's really been solved with this manifest concept -- it just seems like over thinking a very straightforward solution which has worked for me and the vast majority of everyone else in the civilized world. THE FILESYSTEM SEARCH PATH.Anonymous
January 10, 2008
I'm sure there are some very bright people at Microsoft but so far none have found a way to improve on *nix's simple and elegant way of installing programs and shared objects using links. Unbelievable.Anonymous
December 31, 2008
The comment has been removed