This blog is about developing Windows applications using Visual Studio. All postings on this weblog are provided "AS IS" with no warranties, and confer no rights. Use of any samples are subject to the terms specified at http://www.microsoft.com/info/cpyright.htm
Your host Nikola Dudar is a Program Manager in Windows division of Microsoft Corporation. He has been working on Windows Web Services API during Windows 7 and various additions to Visual C++ during VS2005 and VS2008. More details are in LinkedIn profile under Nikola's formal name Mykola Dudar.
If you are interested in program management and project management, check out my other blog at http://www.pmsnack.com/ where I collect best practices and other topics interesting to program and project managers.
To send feedback, comments or requests for new posts, please use the contact form.
Here is an unofficial preview of sample that is going to be available soon on MSDN. As always, standard disclosure that this post is provided "AS IS" with no warranties, and confer no rights and use of this sample is subject to the terms specified at http://www.microsoft.com/info/cpyright.htm
It is recommended for C/C++ applications to have manifest embedded inside the final binary because this ensures proper runtime behavior in most of scenarios. Visual Studio by default tries to embed manifest when building project from source files, see my post on how manifest is generated in visual studio for more details. However if an application is built using nmake build utility, some changes to existing makefile are necessary. In this section it is demonstrated how to change existing makefiles to automatically embed manifest inside final binary.
First let’s take a look on MyApplication.exe, which is a simple application built from one file using a nmake script as the following:
!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
If this script is run unchanged with Visual C++ 2005, it successfully creates MyApplication.exe and external manifest MyApplication.exe.manifest that is used by operation system to load dependent assemblies at runtime.
However it may be required to embed manifest inside MyApplication.exe for some reasons. There are several ways to achieve this. A simple change to make is to embed external manifest generated by linker as a resources inside the final binary. This can be achieved by making changes to nmake script file. First
# 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
_VC_MANIFEST_INC=1
_VC_MANIFEST_BASENAME=__VC80.Debug
_VC_MANIFEST_INC=0
_VC_MANIFEST_BASENAME=__VC80
#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
_VC_MANIFEST_AUTO_RES=
#Step 4. Adding _VC_MANIFEST_EMBED_EXE - command to embedd manifest to EXE
#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 & \
if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;1
# Step 5. Changing command used to build EXE
MyApplication.exe : MyApplication.obj $(_VC_MANIFEST_AUTO_RES)
$(_VC_MANIFEST_EMBED_EXE)
# Step 6. 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>
1 RT_MANIFEST "$(_VC_MANIFEST_BASENAME).auto.manifest"
<< KEEP
$(_VC_MANIFEST_BASENAME).auto.manifest :
<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
<assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'>
</assembly>
# Step 7. Adding _VC_MANIFEST_CLEAN - command to clean generate files
# for temporary resources
_VC_MANIFEST_CLEAN=-del $(_VC_MANIFEST_BASENAME).auto.res \
$(_VC_MANIFEST_BASENAME).auto.rc \
$(_VC_MANIFEST_BASENAME).auto.manifest
_VC_MANIFEST_CLEAN=
del MyApplication.obj MyApplication.exe MyApplication.exe.manifest
$(_VC_MANIFEST_CLEAN)
Similarly changes to nmake scripts required in case of an library MyLibrary.dll. If it was built using the following script:
LFLAGS=$(LFLAGS) /DLL /INCREMENTAL
LFLAGS=$(LFLAGS) /DLL
MyLibrary.dll : MyLibrary.obj
MyLibrary.obj : MyLibrary.cpp
del MyLibrary.obj MyLibrary.dll
In this case, build script has to change in a similar way to EXE with only one exception. Manifest has to embedded as resource with ID equal to 2, instead of 1 as for EXE.
#Step 4. Adding _VC_MANIFEST_EMBED_DLL - command to embedd manifest into DLL
MT_SPECIAL_RETURN=1090650113
MT_SPECIAL_SWITCH=-notify_update
_VC_MANIFEST_EMBED_DLL= \
if exist $@.manifest mt.exe -manifest $@.manifest -outputresource:$@;2
# Step 5. Changing command used to build DLL
MyLibrary.dll : MyLibrary.obj $(_VC_MANIFEST_AUTO_RES)
$(_VC_MANIFEST_EMBED_DLL)
# Step 6. Adding commands to generate initial empty manifest file, RC file that references it
# and for generating the .res file
# Note: RT_MANIFEST has ID 2, because this is DLL.
2 RT_MANIFEST "$(_VC_MANIFEST_BASENAME).auto.manifest"
#Step 7. Adding _VC_MANIFEST_CLEAN - command to clean generate files for temporary resources
del MyLibrary.obj MyLibrary.dll MyLibrary.dll.manifest
Try your new makefile. This should work for you. If it does not, please let me know ASAP. I will try fixing it for you.
Have fun,Nikola