Udostępnij za pośrednictwem


Porady: osadzanie manifestu w aplikacji C/C++

Zalecane jest, że C/C++ aplikacji (lub biblioteki) mają manifeście osadzić wewnątrz końcowego pliku binarnego, ponieważ gwarantuje to zachowanie poprawne runtime w większości scenariuszy.Domyślnie Visual Studio próbuje osadzić manifest podczas tworzenia projektu z plików źródłowych. zobacz Generowanie manifestu w Visual Studio uzyskać więcej informacji.Jednak jeśli aplikacja jest zbudowana przy użyciu nUpewnij, niezbędne są pewne zmiany do istniejącego pliku makefile.W tej sekcji przedstawiono sposób zmienić istniejące makefile manifest wewnątrz pliku binarnego końcowego jest osadzana automatycznie.

Dwa podejścia

Istnieją dwa sposoby, aby osadzić w manifeście wewnątrz aplikacji lub biblioteki.

  • Jeśli nie robi przyrostowe kompilacji można osadzać bezpośrednio manifest krokiem po konstrukcji za pomocą wiersza polecenia podobny do następującego:

    mt.exe –manifest MyApp.exe.manifest -outputresource:MyApp.exe;1

    lub

    mt.exe –manifest MyLibrary.dll.manifest -outputresource:MyLibrary.dll;2

    (1 EXE, 2 dla biblioteki DLL).

  • Jeśli robisz przyrostowe kompilacji bezpośrednio edytuje zasobu, jak pokazano poniżej będzie wyłączyć przyrostowe budynku i powodować pełnej przebudowy; Dlatego też należy podjąć inne podejście:

    • Łącze pliku binarnego do generowania pliku MyApp.exe.manifest.

    • Manifest należy przekonwertować plik zasobów.

    • Ponowne łączenie (przyrostowo), aby osadzić zasób manifestu w pliku binarnego.

Następujące przykłady pokazują jak zmienić makefile do włączenia obu technik.

Makefile (przed)

Należy wziąć pod uwagę skrypt nUpewnij MyApp.exe, prosta aplikacja zbudowany z jednego pliku:

# build MyApp.exe
!if "$(DEBUG)" == "1"
CPPFLAGS=$(CPPFLAGS) /MDd
LFLAGS=$(LFLAGS) /INCREMENTAL
!else
CPPFLAGS=$(CPPFLAGS) /MD
!endif

MyApp.exe : MyApp.obj
    link $** /out:$@ $(LFLAGS)

MyApp.obj : MyApp.cpp

clean : 
    del MyApp.obj MyApp.exe

Jeżeli ten skrypt jest uruchamiany bez zmian w programie Visual C++, pomyślnie tworzy MyApp.exe.Tworzy również zewnętrznego pliku manifestu MyApp.exe.manifest, do użycia przez system operacyjny, aby załadować zestawy zależne w czasie wykonywania.

Bardzo podobny skrypcie nUpewnij dla MyLibrary.dll:

# build MyLibrary.dll
!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)

MyLibrary.obj : MyLibrary.cpp

clean : 
    del MyLibrary.obj MyLibrary.dll

Makefile (po)

Zbudowanie z osadzonych manifestów trzeba wprowadzać cztery małe zmiany oryginalnego makefile.Dla pliku makefile MyApp.exe:

# build MyApp.exe
!include makefile.inc
#^^^^^^^^^^^^^^^^^^^^ Change #1. (Add full path if necessary.)

!if "$(DEBUG)" == "1"
CPPFLAGS=$(CPPFLAGS) /MDd
LFLAGS=$(LFLAGS) /INCREMENTAL
!else
CPPFLAGS=$(CPPFLAGS) /MD
!endif

MyApp.exe : MyApp.obj
    link $** /out:$@ $(LFLAGS)
    $(_VC_MANIFEST_EMBED_EXE)
#^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Change #2

MyApp.obj : MyApp.cpp

clean : 
    del MyApp.obj MyApp.exe
    $(_VC_MANIFEST_CLEAN)
#^^^^^^^^^^^^^^^^^^^^^^^^ Change #3

!include makefile.targ.inc
#^^^^^^^^^^^^^^^^^^^^^^^^^ Change #4. (Add full path if necessary.)

Dla pliku makefile MyLibrary.dll:

# build MyLibrary.dll
!include makefile.inc
#^^^^^^^^^^^^^^^^^^^^ Change #1. (Add full path if necessary.)

!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)
#^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Change #2.

MyLibrary.obj : MyLibrary.cpp

clean : 
    del MyLibrary.obj MyLibrary.dll
    $(_VC_MANIFEST_CLEAN)
#^^^^^^^^^^^^^^^^^^^^^^^^ Change #3.

!include makefile.targ.inc
#^^^^^^^^^^^^^^^^^^^^^^^^^ Change #4. (Add full path if necessary.)

Makefile teraz zawierać dwa pliki, które nie rzeczywistej pracy, makefile.inc i makefile.targ.inc.

Utwórz makefile.inc i skopiuj do niego następujące:

# makefile.inc -- Include this file into existing makefile at the very top.

# _VC_MANIFEST_INC specifies whether build is incremental (1 - incremental).
# _VC_MANIFEST_BASENAME specifies name of a temporary resource file.

!if "$(DEBUG)" == "1"
CPPFLAGS=$(CPPFLAGS) /MDd
LFLAGS=$(LFLAGS) /INCREMENTAL
_VC_MANIFEST_INC=1
_VC_MANIFEST_BASENAME=__VC90.Debug

!else
CPPFLAGS=$(CPPFLAGS) /MD
_VC_MANIFEST_INC=0
_VC_MANIFEST_BASENAME=__VC90

!endif

####################################################
# 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

####################################################
# _VC_MANIFEST_EMBED_EXE - command to embed manifest in 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

####################################################
# _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 
####################################################

Teraz utworzyć makefile.targ.inc i skopiuj do niego następujące:

# makefile.targ.inc - include this at the very bottom of the existing makefile

####################################################
# Commands to generate initial empty manifest file and the 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

Zobacz też

Koncepcje

Ogólne informacje o tworzeniu manifestu dla programów C/C++