I had a MFC ActiveX project created in Visual Studio 2010. Freshly out of the wizard, it built fine.
I then added to the project one pair of .h and .cpp files from another source, and I got the pre-compilation error, because the .cpp file does not have #include “stdafx.h”. I did not want to modify the source code, so I just turned off pre-compilation for the .cpp file from project settings (C/C++ | Precompiled Headers | Precompiled Header – Not Using).
Now when I built the project, I got this error at linking (Debug):
mfcs100d.lib(dllmodul.obj) : error LNK2005: _DllMain@12 already defined in MSVCRTD.lib(dllmain.obj)
or this one (Release)
mfcs100.lib(dllmodul.obj) : error LNK2005: _DllMain@12 already defined in MSVCRT.lib(dllmain.obj)
First of all, both the MFC library and CRT library are default libraries (former post) that I did not bother to explicit set.
Normally the error should appear as duplicated definitions for DllMain, but because the function has weak external linkage in CRT, it allows overtaking, with a condition that the other version must appear first than CRT.
In the error message above, an MFC DLL project (ActiveX is a DLL) is supposed to use DllMain from the MFC DLL (import library mfcs100d.lib or mfcs100.lib), but somehow the CRT version of DllMain (import library MSVCRTD.lib or MSVCRT.lib) gets into the scene. That is, the MFC library appears later than CRT in the default library list.
This is because the .cpp file was compiled without including afx.h (which adds MFC/CRT/Win32 default libraries in correct order), and therefore it only receives the default library records for MSVCRT.LIB and OLDNAMES.LIB added by Visual C++ compiler. At the link time, the linker can see MSVCRT.LIB earlier than MFC libraries, and hence the error.
There are a few approaches to solve the problem.
- Simply include “stdafx.h” as the first line of the .cpp file. This not only solves the linking problem, but also avoids modifying the pre-compilation option. It brings the unnecessary dependency on stdafx.h and its own dependencies such as MFC.
- Suppress default library for the offending .obj file. Use /Zl for the .cpp file: C/C++ Advanced | Omit Default Library Name – Yes (/Zl). The results in the .obj file without any default library records. Therefore, linker would follow default libraries and their order from other .obj files, and hopefully they are correct in the sense of an MFC application. If the offending .cpp file relies on other default libraries for its own right, if /Zl is used on it, we have to add back explicitly those libraries to linker options.
- Set the correct link order manually. Use /NODEFAULTLIB (Linker | Input | Ignore Specific Default Libraries : mfcs100d.lib;MSVCRTD.lib) to ignore the two fighting libraries. This removes the two libraries from the list even if they appear in any .obj file. Then add them explicitly in the correct order (Linker | Input | Additional Dependencies : mfcs100d.lib;MSVCRTD.lib). See Microsoft Support Article 148652. This method requires us to find the exact fighting libraries of MFC and CRT. They may change under different project settings, Debug/Release, Unicode/Not, … and it can be quite difficult to maintain.
- Seeing all the cons above, I decide to make all the stuff in the .cpp file inline and put it in a header file. Let the user of the header file worry and solve the library order problem, because it should not be this module’s problem anyway. Also, pre-compilation is not relevant either. In the MFC application above, the user just needs to #include the header file and it’s good to go. In fact, this is my preferred approach to write modules; a header file library is often much easier to maintain and share. The only question is whether everything can be put in the header file. For example, if it has global data, a translation unit is normally required, and this does not work (but I sometimes use a singleton to wrap the global data and it can still fit merely in a header file).