Bagikan melalui


Memahami pembuatan manifes untuk program C/C++

Manifes adalah dokumen XML yang secara unik mengidentifikasi rakitan. Ini berisi informasi yang digunakan untuk pengikatan dan aktivasi, seperti kelas COM, antarmuka, dan pustaka jenis. Manifes dapat berupa file XML eksternal atau sumber daya yang disematkan di dalam aplikasi atau rakitan. Manifes aplikasi terisolasi digunakan untuk mengelola nama dan versi rakitan bersama berdampingan yang harus diikat aplikasi pada waktu proses. Manifes rakitan berdampingan menentukan dependensinya pada nama, versi, sumber daya, dan rakitan lainnya.

Ada dua cara untuk membuat manifes untuk aplikasi terisolasi atau rakitan berdampingan. Pertama, penulis assembly dapat membuat file manifes secara manual dengan mengikuti aturan dan persyaratan penamaan. Untuk informasi selengkapnya, lihat Referensi file manifes. Atau, jika program hanya bergantung pada rakitan MSVC seperti CRT, MFC, ATL atau lainnya, maka linker dapat menghasilkan manifes secara otomatis.

Header pustaka MSVC berisi informasi perakitan, dan ketika pustaka disertakan dalam kode aplikasi, informasi perakitan ini digunakan oleh linker untuk membentuk manifes untuk biner akhir. Secara default, linker tidak menyematkan file manifes di dalam biner. Memiliki manifes sebagai file eksternal mungkin tidak berfungsi untuk semua skenario. Misalnya, disarankan agar rakitan privat telah menyematkan manifes. Dalam build baris perintah seperti yang menggunakan NMAKE untuk membuat kode, Anda dapat menggunakan /MANIFEST:EMBED opsi linker untuk menyematkan manifes. Atau, manifes dapat disematkan menggunakan alat manifes. Untuk informasi selengkapnya, lihat Pembuatan manifes di baris perintah. Saat Anda membuat di Visual Studio, manifes dapat disematkan dengan mengatur properti untuk alat manifes dalam dialog Properti Proyek, seperti yang dijelaskan di bagian berikutnya.

Pembuatan manifes dalam Visual Studio

Anda dapat memberi tahu Visual Studio untuk membuat file manifes untuk proyek tertentu dalam dialog Halaman Properti proyek. Di bawah Properti Konfigurasi, pilih File>Manifes Linker>Hasilkan Manifes. Secara default, properti proyek proyek baru diatur untuk menghasilkan file manifes. Namun dimungkinkan untuk menonaktifkan pembuatan manifes untuk proyek dengan menggunakan properti Buat Manifes proyek. Ketika properti ini diatur ke Ya, manifes untuk proyek dihasilkan. Jika tidak, linker mengabaikan informasi perakitan saat menyelesaikan dependensi kode aplikasi, dan tidak menghasilkan manifes.

Sistem build di Visual Studio memungkinkan manifes disematkan dalam file aplikasi biner akhir, atau dihasilkan sebagai file eksternal. Perilaku ini dikontrol oleh opsi Sematkan Manifes dalam dialog Properti Proyek. Untuk mengatur properti ini, buka simpul Alat Manifes, lalu pilih Input dan Output. Jika manifes tidak disematkan, manifes dibuat sebagai file eksternal dan disimpan dalam direktori yang sama dengan biner akhir. Jika manifes disematkan, Visual Studio menyematkan manifes akhir menggunakan proses berikut:

  1. Setelah kode sumber dikompilasi ke file objek, linker mengumpulkan informasi perakitan dependen. Meskipun menautkan biner akhir, linker menghasilkan manifes perantara yang digunakan nanti untuk menghasilkan manifes akhir.

  2. Setelah manifes perantara dan penautan selesai, alat manifes menggabungkan manifes akhir dan menyimpannya sebagai file eksternal.

  3. Sistem build proyek kemudian mendeteksi apakah manifes yang dihasilkan oleh alat manifes berisi informasi yang berbeda dari manifes yang sudah disematkan dalam biner.

  4. Jika manifes yang disematkan dalam biner berbeda dari manifes yang dihasilkan oleh alat manifes, atau biner tidak berisi manifes yang disematkan, Visual Studio memanggil linker sekali lagi untuk menyematkan file manifes eksternal di dalam biner sebagai sumber daya.

  5. Jika manifes yang disematkan dalam biner sama dengan manifes yang dihasilkan oleh alat manifes, build berlanjut ke langkah build berikutnya.

Manifes disematkan di dalam biner akhir sebagai sumber daya teks. Anda dapat melihatnya dengan membuka biner akhir sebagai file di Visual Studio. Untuk memastikan bahwa manifes menunjuk ke pustaka yang benar, ikuti langkah-langkah yang dijelaskan dalam Memahami dependensi aplikasi Visual C++. Atau, ikuti saran yang dijelaskan dalam artikel Pemecahan Masalah.

Pembuatan manifes di baris perintah

Saat Anda membangun aplikasi C/C++ dari baris perintah menggunakan NMAKE atau alat serupa, manifes dihasilkan setelah linker memproses semua file objek dan membangun biner akhir. Linker mengumpulkan informasi rakitan yang disimpan dalam file objek dan menggabungkan informasi ini ke dalam file manifes akhir. Secara default, linker menghasilkan file bernama <binary_name>.<extension>.manifest untuk menjelaskan biner akhir. Linker dapat menyematkan file manifes di dalam biner dengan menentukan /MANIFEST:EMBED opsi linker.

Ada beberapa cara lain untuk menyematkan manifes di dalam biner akhir, seperti menggunakan alat Manifes (mt.exe) atau mengkompilasi manifes ke dalam file sumber daya. Anda harus mengikuti aturan tertentu saat menyematkan manifes untuk mengaktifkan fitur seperti penautan inkremental, penandatanganan, dan Edit dan Lanjutkan. Aturan ini dan opsi lainnya dibahas di bagian berikutnya.

Cara menyematkan manifes di dalam aplikasi C/C++

Kami menyarankan agar Anda menyematkan manifes aplikasi atau pustaka Anda di dalam biner akhir. Pendekatan ini menjamin perilaku runtime yang benar dalam sebagian besar skenario. Secara default, Visual Studio mencoba menyematkan manifes saat membangun proyek. Namun, jika Anda membangun aplikasi dengan menggunakan NMAKE, Anda harus membuat beberapa perubahan pada makefile. Bagian ini menunjukkan cara mengubah makefiles sehingga secara otomatis menyematkan manifes di dalam biner akhir.

Dua pendekatan

Ada dua cara untuk menyematkan manifes di dalam aplikasi atau pustaka.

  1. Jika Anda tidak melakukan build inkremental, Anda dapat langsung menyematkan manifes menggunakan baris perintah yang mirip dengan yang berikut ini sebagai langkah pasca-build:

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

    atau

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

    Gunakan 1 untuk EXE dan 2 untuk DLL.

  2. Jika Anda melakukan build inkremental, gunakan langkah-langkah berikut:

    • Tautkan biner untuk menghasilkan MyApp.exe.manifest file.

    • Mengonversi manifes menjadi file sumber daya.

    • Tautan ulang (secara bertahap) untuk menyematkan sumber daya manifes ke dalam biner.

Contoh berikut menunjukkan cara mengubah makefiles untuk menggabungkan kedua teknik.

Makefiles (Sebelum)

Pertimbangkan skrip NMAKE untuk MyApp.exe, aplikasi sederhana yang dibangun dari satu file:

# 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

Jika skrip ini dijalankan tidak berubah dengan Visual Studio, skrip berhasil membuat MyApp.exe. Ini juga membuat file MyApp.exe.manifestmanifes eksternal , untuk digunakan oleh sistem operasi untuk memuat rakitan dependen saat runtime.

Skrip NMAKE untuk MyLibrary.dll terlihat mirip:

# 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 (Setelah)

Untuk membangun dengan manifes yang disematkan, Anda harus membuat empat perubahan kecil pada makefiles asli. Untuk 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.target.inc
#^^^^^^^^^^^^^^^^^^^^^^^^^ Change #4. (Add full path if necessary.)

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

Makefiles sekarang mencakup dua file yang melakukan pekerjaan nyata, makefile.inc dan makefile.target.inc.

Buat makefile.inc dan salin konten berikut ke dalamnya:

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

Sekarang buat makefile.target.inc dan salin konten berikut ke dalamnya:

# 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

Baca juga

Membangun aplikasi terisolasi C/C++ dan rakitan berdampingan
Konsep aplikasi terisolasi dan rakitan berdampingan
Pemecahan masalah aplikasi terisolasi C/C++ dan rakitan berdampingan
/INCREMENTAL (Tautan bertahap)
/MANIFEST (Buat manifes perakitan berdampingan)
Rakitan Nama Kuat (Penandatanganan rakitan) (C++/CLI)
Edit dan Lanjutkan