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

Manifest to dokument XML, który jednoznacznie identyfikuje zestaw. Zawiera informacje używane do tworzenia powiązań i aktywacji, takich jak klasy COM, interfejsy i biblioteki typów. Manifest może być zewnętrznym plikiem XML lub zasobem osadzonym wewnątrz aplikacji lub zestawu. Manifest izolowanej aplikacji służy do zarządzania nazwami i wersjami udostępnionych zestawów side-by-side, z którymi aplikacja powinna być powiązana w czasie wykonywania. Manifest zestawu równoległego określa jego zależności od nazw, wersji, zasobów i innych zestawów.

Istnieją dwa sposoby tworzenia manifestu dla izolowanej aplikacji lub zestawu równoległego. Najpierw autor zestawu może ręcznie utworzyć plik manifestu, postępując zgodnie z regułami i wymaganiami dotyczącymi nazewnictwa. Aby uzyskać więcej informacji, zobacz Dokumentacja plików manifestu. Alternatywnie, jeśli program zależy tylko od zestawów MSVC, takich jak CRT, MFC, ATL lub inne, konsolidator może wygenerować manifest automatycznie.

Nagłówki bibliotek MSVC zawierają informacje o zestawie, a gdy biblioteki są zawarte w kodzie aplikacji, te informacje o zestawie są używane przez konsolidator do utworzenia manifestu końcowego pliku binarnego. Domyślnie konsolidator nie osadza pliku manifestu wewnątrz pliku binarnego. Posiadanie manifestu jako pliku zewnętrznego może nie działać we wszystkich scenariuszach. Na przykład zaleca się, aby zestawy prywatne miały osadzone manifesty. W kompilacjach wiersza polecenia, takich jak te, które używają narzędzia NMAKE do kompilowania kodu, można użyć /MANIFEST:EMBED opcji konsolidatora, aby osadzić manifest. Alternatywnie manifest można osadzać przy użyciu narzędzia manifestu. Aby uzyskać więcej informacji, zobacz Generowanie manifestu w wierszu polecenia. Podczas kompilowania w programie Visual Studio manifest można osadzać, ustawiając właściwość narzędzia manifestu w oknie dialogowym Właściwości projektu, zgodnie z opisem w następnej sekcji.

Generowanie manifestu w programie Visual Studio

Program Visual Studio może generować plik manifestu dla określonego projektu w oknie dialogowym Strony właściwości projektu. W obszarze Właściwości konfiguracji wybierz pozycję Plik>manifestu konsolidatora>Generuj manifest. Domyślnie właściwości projektu nowych projektów są ustawiane na generowanie pliku manifestu. Można jednak wyłączyć generowanie manifestu dla projektu przy użyciu właściwości Generate Manifest projektu. Gdy ta właściwość ma wartość Tak, manifest projektu zostanie wygenerowany. W przeciwnym razie konsolidator ignoruje informacje o zestawie podczas rozpoznawania zależności kodu aplikacji i nie generuje manifestu.

System kompilacji w programie Visual Studio umożliwia osadzanie manifestu w końcowym pliku aplikacji binarnej lub generowane jako plik zewnętrzny. To zachowanie jest kontrolowane przez opcję Osadź manifest w oknie dialogowym Właściwości projektu. Aby ustawić tę właściwość, otwórz węzeł Narzędzie manifestu, a następnie wybierz pozycję Dane wejściowe i wyjściowe. Jeśli manifest nie jest osadzony, jest generowany jako plik zewnętrzny i zapisywany w tym samym katalogu co końcowy plik binarny. Jeśli manifest jest osadzony, program Visual Studio osadza końcowe manifesty przy użyciu następującego procesu:

  1. Po skompilowaniu kodu źródłowego do plików obiektów konsolidator zbiera informacje o zestawie zależnym. Chociaż łączy końcowy plik binarny, konsolidator generuje manifest pośredni, który jest używany później do generowania końcowego manifestu.

  2. Po zakończeniu pośredniego manifestu i łączeniu narzędzie manifestu scala końcowy manifest i zapisuje go jako plik zewnętrzny.

  3. Następnie system kompilacji projektu wykrywa, czy manifest wygenerowany przez narzędzie manifestu zawiera inne informacje niż manifest już osadzony w pliku binarnym.

  4. Jeśli manifest osadzony w pliku binarnym różni się od manifestu wygenerowanego przez narzędzie manifestu lub plik binarny nie zawiera osadzonego manifestu, program Visual Studio wywołuje konsolidator jeszcze raz, aby osadzić zewnętrzny plik manifestu wewnątrz pliku binarnego jako zasób.

  5. Jeśli manifest osadzony w pliku binarnym jest taki sam jak manifest wygenerowany przez narzędzie manifestu, kompilacja kontynuuje kolejne kroki kompilacji.

Manifest jest osadzony wewnątrz końcowego pliku binarnego jako zasobu tekstowego. Możesz go wyświetlić, otwierając końcowy plik binarny jako plik w programie Visual Studio. Aby upewnić się, że manifest wskazuje prawidłowe biblioteki, wykonaj kroki opisane w temacie Understanding the dependencies of a Visual C++ application (Opis zależności aplikacji Visual C++). Możesz też postępować zgodnie z sugestiami opisanymi w artykule Dotyczącym rozwiązywania problemów.

Generowanie manifestu w wierszu polecenia

Podczas kompilowania aplikacji C/C++ z wiersza polecenia przy użyciu narzędzia NMAKE lub podobnych narzędzi manifest jest generowany po przetworzeniu wszystkich plików obiektów przez konsolidator i skompilowaniu końcowego pliku binarnego. Konsolidator zbiera informacje o zestawie przechowywane w plikach obiektów i łączy te informacje w ostatnim pliku manifestu. Domyślnie konsolidator generuje plik o nazwie <binary_name>.<extension>.manifest w celu opisania końcowego pliku binarnego. Konsolidator może osadzić plik manifestu wewnątrz pliku binarnego, określając opcję konsolidatora /MANIFEST:EMBED .

Istnieje kilka innych sposobów osadzania manifestu wewnątrz końcowego pliku binarnego, na przykład przy użyciu narzędzia manifestu (mt.exe) lub kompilowania manifestu w pliku zasobów. Należy postępować zgodnie z określonymi regułami podczas osadzania manifestu, aby włączyć funkcje, takie jak łączenie przyrostowe, podpisywanie i edytowanie i kontynuuj. Te reguły i inne opcje zostały omówione w następnej sekcji.

Jak osadzić manifest w aplikacji C/C++

Zalecamy osadzanie manifestu aplikacji lub biblioteki wewnątrz końcowego pliku binarnego. Takie podejście gwarantuje prawidłowe zachowanie środowiska uruchomieniowego w większości scenariuszy. Domyślnie program Visual Studio próbuje osadzić manifest podczas kompilowania projektu. Jeśli jednak utworzysz aplikację przy użyciu narzędzia NMAKE, musisz wprowadzić pewne zmiany w pliku make. W tej sekcji pokazano, jak zmienić pliki makefile, aby automatycznie osadzać manifest wewnątrz końcowego pliku binarnego.

Dwa podejścia

Istnieją dwa sposoby osadzania manifestu wewnątrz aplikacji lub biblioteki.

  1. Jeśli nie wykonujesz kompilacji przyrostowej, możesz bezpośrednio osadzić manifest przy użyciu wiersza polecenia podobnego do poniższego jako krok po kompilacji:

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

    lub

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

    Użyj 1 dla pliku EXE i 2 dla biblioteki DLL.

  2. Jeśli wykonujesz kompilację przyrostową, wykonaj następujące kroki:

    • Połącz plik binarny, MyApp.exe.manifest aby wygenerować plik.

    • Przekonwertuj manifest na plik zasobu.

    • Połącz ponownie (przyrostowo), aby osadzić zasób manifestu w pliku binarnym.

W poniższych przykładach pokazano, jak zmienić pliki makefile w celu uwzględnienia obu technik.

Pliki programu Make (przed)

Rozważ użycie skryptu NMAKE dla MyApp.exeprogramu , prostej aplikacji utworzonej na podstawie 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śli ten skrypt zostanie uruchomiony bez zmian w programie Visual Studio, pomyślnie utworzy element MyApp.exe. Tworzy również plik MyApp.exe.manifestmanifestu zewnętrznego do użycia przez system operacyjny do ładowania zestawów zależnych w czasie wykonywania.

Skrypt NMAKE dla polecenia MyLibrary.dll wygląda podobnie:

# 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

Pliki programu Make (po)

Aby skompilować za pomocą osadzonych manifestów, musisz wprowadzić cztery małe zmiany w oryginalnych plikach make. Dla pliku MyApp.exe make:

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

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

Pliki makefile zawierają teraz dwa pliki, które wykonują rzeczywistą pracę, makefile.inc i makefile.target.inc.

Utwórz makefile.inc i skopiuj do niej następującą zawartość:

# 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 utwórz makefile.target.inc i skopiuj do niego następującą zawartość:

# 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

Zobacz też

Kompilowanie aplikacji izolowanych w języku C/C++ i zestawów równoległych
Pojęcia dotyczące izolowanych aplikacji i zestawów równoległych
Rozwiązywanie problemów z aplikacjami izolowanymi w języku C/C++ i zestawami równoległym
/INCREMENTAL (Połącz przyrostowo)
/MANIFEST (Tworzenie manifestu zestawu równoległego)
Zestawy silnej nazwy (podpisywanie zestawów) (C++/CLI)
Edytuj i kontynuuj