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