VS 2008: MFC selbst kompilieren
Gestern hatte ich darüber berichtet, wie man der WinSxS-Hölle entkommt und eine eigene Version der C/C++-Laufzeit kompiliert. Nun kompilieren wir uns noch eine MFC ohne Manifest und können in Zukunft die C/C++-Laufzeit sowie die MFC unseren Anwendungen beilegen, ohne uns mit Manifestproblemen herumquälen zu müssen.
1. Anpassen der Dateien
Die nötigen Änderungen an den MFC-Dateien halten sich in Grenzen. Zuerst schnappen wir uns die Datei atlmfc\include\MFCassem.h und kommentieren das Manifest ab Zeile 25 bis zum Ende aus. In atlmfc\include\afx.h ersetzen wir die Zeilen 81 bis 97 durch folgende:
#ifndef _UNICODE #ifdef _DEBUG #pragma comment(lib, "MyMfc90d.lib") #pragma comment(lib, "MyMfc90sd.lib") #else #pragma comment(lib, "MyMfc90.lib") #pragma comment(lib, "MyMfc90s.lib") #endif #else #ifdef _DEBUG #pragma comment(lib, "MyMfc90ud.lib") #pragma comment(lib, "MyMfc90sud.lib") #else #pragma comment(lib, "MyMfc90u.lib") #pragma comment(lib, "MyMfc90su.lib") #endif #endif
Damit legen wir fest, dass unsere Anwendungen dynamisch gegen die MyMfc90(u).dll gelinkt werden.
2. Vorbereitung der .DEF-Dateien
In atlmfc\src\mfc\intel und atlmfc\src\mfc\intel befinden sich jeweils vier .DEF-Dateien, deren Modulnamen ebenfalls angepasst werden müssen:
mfc90.def -> MyMfc90 mfc90d.def -> MyMfc90d mfc90u.def -> MyMfc90u mfc90ud.def -> MyMfc90ud
Im Gegensatz zur C/C++-Laufzeit werden aber nur die Modulnamen in den .def-Dateien angepasst, die Dateinamen selbst dürfen nicht geändert werden.
3. Anpassung des Makefiles
Die Änderung in der Datei atlmfc\src\atlmfc.mak beschränkt sich darauf, die Erstellung der statischen MFC sowie der WinForms-Komponenten auszuklammern. Dazu löschen wir in Zeile 123 die Einträge MFC_STATIC und MFCM_DLL.
4. Kompilieren
Nun kopieren wir unsere bereits erstellten Batchdateien mit den Umgebungsvariablen aus dem Ordner crt in den Ordner atlmfc\src. Zusätzlich erstellen wir in diesem Verzeichnis eine Datei makemfc_x86.bat mit dem Inhalt
nmake -f atlmfc.mak MFC LIBNAME=MyMfc90 PLATFORM=INTEL MP_BUILD=1
sowie makemfc_amd64.bat mit
nmake -f atlmfc.mak MFC LIBNAME=MyMfc90 PLATFORM=AMD64 MP_BUILD=1
Anschließend öffnen wir eine Eingabeaufforderung und starten
vcvars_x86.bat makemfc_x86.bat
sowie anschließend
vcvars_amd64.bat makemfc_amd64.bat
Nach ein paar Minuten sollte der Compiler seine Arbeit erledigt haben und wieder das Befehlsprompt erscheinen.
5. Kopieren der Lib-Dateien
Der letzte Schritt ist das Kopieren der lib-Dateien nach atlmfc\lib, damit der Linker diese später auch findet. Die Lib-Dateien für die 32-bit Version werden bei der MFC-Erstellung in atlmfc\lib\Intel abgelegt und müssen deshalb manuell nach atlmfc\lib kopiert werden. Die Lib-Dateien für die x64-Version landen dagegen direkt im richtigen Verzeichnis (atlmfc\lib\amd64).
Die MFC-Dlls finden wir in atlmfc\src\mfc\intel bzw. atlmfc\src\mfc\amd64. Zusammen mit den Dlls der C/C++-Laufzeit sowie den jeweiligen PDB-Dateien kopieren wir sie in einen Ordner, der in die PATH-Umgebungsvariable eingetragen wird. Somit ist sichergestellt, dass Visual Studio 2008 beim Debuggen auch alle nötigen Dateien findet.
6. Kontrolle
Zur Kontrolle erstellen wir uns ein Testprojekt und prüfen, ob gegen die richtigen Dateien gelinkt wird. Dazu lassen wir uns vom AppWizard eine einfache MFC-Anwendung erstellen und kompilieren diese. Mit Hilfe der Schnellansicht von SpeedCommander lässt sich leicht ermitteln, ob die Programmdatei an die richtigen Module gebunden wurden. Wenn es so ausschaut, dann ist alles in bester Ordnung:
Die gleiche Aktion führen wir noch einmal für die MyMfc90(ud).dll durch, diese sollten ebenfalls gegen die MyVcr90(d).dll gelinkt sein.
7. Letzte Worte
Zum Abschluss sei nochmals erwähnt, dass sich diese beiden Artikel wirklich nur an den nativen Entwickler richten, der vollständigen Einfluss auf die von ihm verwendeten Komponenten hat. Dazu gehört, dass alle Fremdkomponenten im Quellcode vorliegen und somit gegen die angepasste C/C++-Laufzeit bzw. die MFC kompiliert werden können. Verwendet man dagegen zusätzliche Managed Code-Erweiterungen oder fertige Libs/Dlls, die bereits gegen die originale MsVcr90.dll gelinkt sind, dann sollte man um die manifestlose Lösung einen großen Bogen machen.
Super Idee. Das Bauen der Runtime library hat auch einwandfrei funktioniert. Beim Bauen der MFC ging
Schritt 4 leider schief. Erst dachte ich man muesste nur in den DEF Dateien die LIBRARY von mfc90(u,d).dll auf MyMfc90(u,d).dll anpassen. Aber das resultat war identisch. Hat irgendwer eine Idee ?
Anbei mein Log:
——————————————————————————————
C:\Program Files\Microsoft Visual Studio 9.0\VC\atlmfc\src>“C:\Program Files\Mic
rosoft Visual Studio 9.0\VC\atlmfc\src\makemfc_x86.bat“
C:\Program Files\Microsoft Visual Studio 9.0\VC\atlmfc\src>nmake -f atlmfc.mak M
FC LIBNAME=MyMfc90 PLATFORM=INTEL MP_BUILD=1
Microsoft (R) Program Maintenance Utility Version 9.00.21022.08
Copyright (C) Microsoft Corporation. All rights reserved.
if not exist ..\lib\INTEL md ..\lib\INTEL
cd MFC
„C:\Program Files\Microsoft Visual Studio 9.0\VC\BIN\nmake.exe“ /
/f mfcdll.mak LIBNAME=MyMfc90 debug=0 _OD_EXT= PLATFORM=INTEL
Microsoft (R) Program Maintenance Utility Version 9.00.21022.08
Copyright (C) Microsoft Corporation. All rights reserved.
NMAKE : fatal error U1073: don’t know how to make ‚INTEL\MFC90.DEF‘
Stop.
NMAKE : fatal error U1077: ‚“C:\Program Files\Microsoft Visual Studio 9.0\VC\BIN
\nmake.exe“‚ : return code ‚0x2‘
Stop.
C:\Program Files\Microsoft Visual Studio 9.0\VC\atlmfc\src>“C:\Program Files\Mic
rosoft Visual Studio 9.0\VC\atlmfc\src\vcvars_x86.bat“
Setting environment for using Microsoft Visual Studio 2008 x86 tools.
C:\Program Files\Microsoft Visual Studio 9.0\VC\atlmfc\src>“C:\Program Files\Mic
rosoft Visual Studio 9.0\VC\atlmfc\src\makemfc_x86.bat“
C:\Program Files\Microsoft Visual Studio 9.0\VC\atlmfc\src>nmake -f atlmfc.mak M
FC LIBNAME=MyMfc90 PLATFORM=INTEL MP_BUILD=1
Microsoft (R) Program Maintenance Utility Version 9.00.21022.08
Copyright (C) Microsoft Corporation. All rights reserved.
if not exist ..\lib\INTEL md ..\lib\INTEL
cd MFC
„C:\Program Files\Microsoft Visual Studio 9.0\VC\BIN\nmake.exe“ /
/f mfcdll.mak LIBNAME=MyMfc90 debug=0 _OD_EXT= PLATFORM=INTEL
Microsoft (R) Program Maintenance Utility Version 9.00.21022.08
Copyright (C) Microsoft Corporation. All rights reserved.
cl @C:\DOCUME~1\Wagemann\LOCALS~1\Temp\nm4D6.tmp
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 15.00.21022.08 for 80×86
Copyright (C) Microsoft Corporation. All rights reserved.
cl /Ycstdafx.h /FpINTEL\$DLL.W\stdafx.pch /D_X86_ /FoINTEL\$DLL.W\ /W4 /WX /Zl
/EHsc /GR /GS /Gm- /O1 /GyF /MD /D_DLL /GF /D_MT /Wp64 /Zc:wchar_t /GL /D_A
FX_CORE_IMPL /D_AFX_OLE_IMPL /D_AFX_DB_IMPL /D_AFX_NET_IMPL /D_AFX_MONOLITHIC /D
_MFC_DLL_BLD /D_WINDLL /D_AFXDLL /D_MBCS /D_AFX_DISABLE_DEPRECATED /D_AFX_NOFORC
E_MANIFEST /D_ATL_NOFORCE_MANIFEST /D_CRT_NOFORCE_MANIFEST /D_ATL_ENABLE_PTM_WAR
NING /c objcore.cpp
cl : Command line warning D9035 : option ‚Wp64‘ has been deprecated and will be
removed in a future release
objcore.cpp
NMAKE : fatal error U1073: don’t know how to make ‚INTEL\MFC90.DEF‘
Stop.
NMAKE : fatal error U1077: ‚“C:\Program Files\Microsoft Visual Studio 9.0\VC\BIN
\nmake.exe“‚ : return code ‚0x2‘
Stop.
—————————————————————
Ich habe mich wohl etwas ungenau ausgedrückt. Es müssen nur die Namen IN den .def-Dateien angepasst werden, die Dateinamen selbst dürfen NICHT geändert werden.
Danke, manchmal habe ich einfach ein Brett vorm Kopf.
Äh ich glaub das muss ich mir nochmal genauer durchlesen das klingt ein bischen nach der lösung meines problems :o)