Sdílet prostřednictvím


Základní informace o generování manifestu pro programy C/C++

Manifest je dokument XML, který jednoznačně identifikuje sestavení. Obsahuje informace používané pro vazbu a aktivaci, jako jsou třídy modelu COM, rozhraní a knihovny typů. Manifest může být externí soubor XML nebo prostředek vložený do aplikace nebo sestavení. Manifest izolované aplikace slouží ke správě názvů a verzí sdílených souběžných sestavení, se kterými by se aplikace měla za běhu svázat. Manifest souběžného sestavení určuje jeho závislosti na názvech, verzích, prostředcích a dalších sestaveních.

Existují dva způsoby vytvoření manifestu pro izolovanou aplikaci nebo souběžné sestavení. Nejprve může autor sestavení ručně vytvořit soubor manifestu podle pravidel a požadavků na pojmenování. Další informace naleznete v tématu Referenční informace k souborům manifestu. Pokud program závisí jenom na sestaveních MSVC, jako jsou CRT, MFC, ATL nebo jiné, může linker vygenerovat manifest automaticky.

Hlavičky knihoven MSVC obsahují informace o sestavení a při zahrnutí knihoven do kódu aplikace tyto informace o sestavení používá linker k vytvoření manifestu pro konečný binární soubor. Ve výchozím nastavení linker nevkládá soubor manifestu do binárního souboru. Manifest jako externí soubor nemusí fungovat pro všechny scénáře. Například doporučujeme, aby soukromá sestavení měla vložené manifesty. V buildech příkazového řádku, jako jsou sestavení kódu NMAKE, můžete k vložení manifestu /MANIFEST:EMBED použít možnost linkeru. Případně můžete manifest vložit pomocí nástroje manifestu. Další informace naleznete v tématu Generování manifestu na příkazovém řádku. Při sestavování v sadě Visual Studio lze manifest vložit nastavením vlastnosti nástroje manifestu v dialogovém okně Vlastnosti projektu, jak je popsáno v další části.

Generování manifestu v sadě Visual Studio

Visual Studio můžete říct, aby v dialogovém okně Stránky vlastností projektu vygeneroval soubor manifestu pro konkrétní projekt. V části Vlastnosti konfigurace vyberte vygenerovat manifest manifest>linkeru.> Ve výchozím nastavení jsou vlastnosti projektu nových projektů nastaveny tak, aby vygenerovaly soubor manifestu. Generování manifestu pro projekt je však možné zakázat pomocí vlastnosti Generate Manifest projektu. Pokud je tato vlastnost nastavena na Ano, manifest pro projekt se vygeneruje. Jinak linker ignoruje informace o sestavení při řešení závislostí kódu aplikace a negeneruje manifest.

Systém sestavení v sadě Visual Studio umožňuje vložit manifest do konečného souboru binární aplikace nebo vygenerovat jako externí soubor. Toto chování je řízeno možností Vložit manifest v dialogovém okně Vlastnosti projektu. Chcete-li nastavit tuto vlastnost, otevřete uzel Nástroje manifestu a pak vyberte vstup a výstup. Pokud manifest není vložený, vygeneruje se jako externí soubor a uloží se do stejného adresáře jako konečný binární soubor. Pokud je manifest vložený, Visual Studio vloží konečné manifesty pomocí následujícího procesu:

  1. Jakmile je zdrojový kód zkompilován do souborů objektů, linker shromažďuje závislé informace o sestavení. Zatímco propojí konečný binární soubor, linker vygeneruje zprostředkující manifest, který se použije později k vygenerování konečného manifestu.

  2. Po dokončení zprostředkujícího manifestu a propojení nástroj manifestu sloučí konečný manifest a uloží ho jako externí soubor.

  3. Systém sestavení projektu pak zjistí, jestli manifest vygenerovaný nástrojem manifestu obsahuje jiné informace než manifest, který je již vložen v binárním souboru.

  4. Pokud se manifest vložený v binárním souboru liší od manifestu vygenerovaného nástrojem manifestu nebo binární soubor neobsahuje vložený manifest, Visual Studio vyvolá linker ještě jednou a vloží externí soubor manifestu do binárního souboru jako prostředek.

  5. Pokud je manifest vložený v binárním souboru stejný jako manifest vygenerovaný nástrojem manifestu, sestavení pokračuje k dalším krokům sestavení.

Manifest se vloží do konečného binárního souboru jako textový prostředek. Můžete ho zobrazit tak, že otevřete konečný binární soubor jako soubor v sadě Visual Studio. Pokud chcete zajistit, aby manifest odkazoval na správné knihovny, postupujte podle kroků popsaných v tématu Principy závislostí aplikace Visual C++. Nebo postupujte podle návrhů popsaných v článku Řešení potíží .

Generování manifestu na příkazovém řádku

Při sestavování aplikací C/C++ z příkazového řádku pomocí NMAKE nebo podobných nástrojů se manifest vygeneruje poté, co linker zpracuje všechny soubory objektů a sestaví konečný binární soubor. Linker shromažďuje informace o sestavení uložené v souborech objektů a kombinuje tyto informace do konečného souboru manifestu. Ve výchozím nastavení linker vygeneruje soubor pojmenovaný <binary_name>.<extension>.manifest k popisu konečného binárního souboru. Linker může vložit soubor manifestu do binárního souboru zadáním možnosti linkeru /MANIFEST:EMBED .

Existuje několik dalších způsobů vložení manifestu do konečného binárního souboru, například pomocí nástroje Manifest (mt.exe) nebo kompilace manifestu do souboru prostředků. Při vkládání manifestu musíte dodržovat určitá pravidla, která umožňují funkce, jako jsou přírůstkové propojení, podepisování a úpravy a pokračování. Tato pravidla a další možnosti jsou popsány v další části.

Vložení manifestu do aplikace C/C++

Doporučujeme vložit manifest aplikace nebo knihovny do konečného binárního souboru. Tento přístup zaručuje správné chování modulu runtime ve většině scénářů. Visual Studio se ve výchozím nastavení pokusí vložit manifest při sestavení projektu. Pokud ale aplikaci sestavíte pomocí nástroje NMAKE, musíte v souboru pravidel provést nějaké změny. Tato část ukazuje, jak změnit soubory pravidel tak, aby automaticky vložil manifest do konečného binárního souboru.

Dva přístupy

Manifest můžete vložit do aplikace nebo knihovny dvěma způsoby.

  1. Pokud neprovádíte přírůstkové sestavení, můžete manifest vložit přímo pomocí příkazového řádku podobného následujícímu jako krok po sestavení:

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

    nebo

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

    Pro knihovnu DLL použijte 1 pro exe a 2.

  2. Pokud provádíte přírůstkové sestavení, postupujte následovně:

    • Propojte binární soubor a vygenerujte ho MyApp.exe.manifest .

    • Převeďte manifest na soubor prostředků.

    • Znovu propojte (přírůstkově) a vložte prostředek manifestu do binárního souboru.

Následující příklady ukazují, jak změnit soubory pravidel tak, aby zahrnovaly obě techniky.

Makefiles (Before)

Zvažte skript NMAKE pro MyApp.exejednoduchou aplikaci vytvořenou z jednoho souboru:

# 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

Pokud se tento skript spustí beze změny v sadě Visual Studio, úspěšně se vytvoří MyApp.exe. Vytvoří také externí soubor MyApp.exe.manifestmanifestu , pro použití operačním systémem k načtení závislých sestavení za běhu.

Skript NMAKE vypadá MyLibrary.dll podobně:

# 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

Makefiles (After)

Pokud chcete vytvořit s vloženými manifesty, musíte v původních souborech pravidel provést čtyři malé změny. MyApp.exe Pro soubor pravidel:

# 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.target.inc
#^^^^^^^^^^^^^^^^^^^^^^^^^ Change #4. (Add full path if necessary.)

Pro soubor pravidel 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.target.inc
#^^^^^^^^^^^^^^^^^^^^^^^^^ Change #4. (Add full path if necessary.)

Soubory pravidel nyní obsahují dva soubory, které dělají skutečnou práci, makefile.inc a makefile.target.inc.

Vytvořte a zkopírujte makefile.inc do něj následující obsah:

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

Teď do něj vytvořte makefile.target.inc a zkopírujte následující obsah:

# makefile.target.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.target.inc

Viz také

Sestavování izolovaných aplikací C/C++ a souběžných sestavení
Koncepty izolovaných aplikací a souběžných sestavení
Řešení potíží s izolovanými aplikacemi C/C++ a souběžnými sestaveními
/INCREMENTAL (Přírůstkové propojení)
/MANIFEST (Vytvoření manifestu sestavení vedle sebe)
Sestavení silného názvu (podepisování sestavení) (C++/CLI)
Operace Upravit a pokračovat