How to make small statically linked MFC EXEs in Visual C++ 2010
May 27, 2010 42 Comments
As a followup to my previous blog entry, I’ve decided to make a simple workaround for those users that want to create a statically linked MFC EXE in 2010 with a size comparable to what was possible in 2008 SP1, that is, a size around 600K instead of the 1800K that you’d get by creating a simple MFC SDI app with classic menus, native/default look and feel, and classic docking toolbars.
It turns out that there are only three source files from the “classic” MFC source code with dependencies on the feature pack source code, that is causing it all to be pulled in when linking. If we can modify this source code by including these three files in our projects, by removing references to the feature pack source code, then the generated EXE size drops dramatically to 600K.
And of course, we must make sure that we do not use any of the feature pack classes, because as soon as you pull one in, you get most of it linked in. I’m specifcally alluding to CDialogEx. CDialogEx is the “new” base class for dialog boxes generated by the MFC appwizard, including the default generated About box. CDialogEx is relatively useless, unless you want to change the background color and/or image of your dialog box, which is something I wouldn’t recommend doing anyway. So the first thing you want to do is change any instances in your project from CDialogEx to CDialog (base classes, base method calls, etc). (a simple Find in Files will suffice)
Then, follow the directions below to get your app back to a reasonable size.
1) Create a default MFC SDI app with no special features (MFC standard, windows native/default style, classic menu, classic docking toolbar, no restart manager support) (this step is not necessary if you already have a project to play with)
2) Change to MFC static linking using project properties
3) add the following MFC source files to your project (copy them from the MFC source file folder located in the place you installed Visual Studio 2010, usually your program files\microsoft visual studio 10.0\vc\atlmfc\src\mfc into your project folder and then “add existing item” for all three files)
4) comment out (or #if 0/#endif) the following code in the MFC source files added:
all the includes after afxctrlcontainer.h
some lines in CMFCControlContainer::CreateDlgControl
some lines in PreUnsubclassControl
the call to tagManager in ReadBoolProp
all the includes after comdef.h except afxglobals.h
the loop that starts with “Notify toolbars about font changing:”
the cleanup for various items ( these will be obvious based on the errors you get compiling after removing the includes above)
the references to CPaneFrameWnd
the references to feature pack classes in AfxIsExtendedFrameClass
the reference to CMFCToolbar in AfxIsMFCToolbar
the two includes after sfdafx.h
the block of code in UpdateClientEdge that starts with CMDIChildWndEx
5) In your project’s stdafx.h add the following lines (these are internal MFC code that some of the source files require, you can add them to the individual source files instead of you prefer):
6) Remove the
from the stdafx.h if applicable. And remove any references to CShellManager in your generated project.
After doing the above, recompile your release build, and notice that your generated EXE should be quite a bit smaller (around 600K instead of 1800K for the above example).