Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Compile MFC Sources with Visual Studio 2019

0.00/5 (No votes)
18 Dec 2020 2  
How to compile MFC sources with VS 2019 (for ARM64 too)
In previous versions of Visual Studio, the bundled MFC source files could be compiled into a static library or a DLL. But since Visual Studio 2008, the necessary files to build MFC are not supplied anymore. In this article, I show you how you can compile the MFC sources with Visual Studio 2019. The new version supports ARM64.

Introduction

With the latest Visual C++ versions (since 2008), it is not possible anymore to compile the bundled MFC sources. The necessary files, i.e., makefiles like atlmfc.mak and a DEF file are not provided anymore.

In a LOB software project, I needed a x86 MFC DLL without the DAO database classes. With statically linked MFC, I provided my own versions of the DAO classes (which internally use MySQL) by overriding the *dao*.obj files, but MFC object files cannot be overridden when using the DLL form of MFC.

So I took the road to build my own MFC vcxproj files.

The github project https://github.com/fobrs/MFC has all the necessary files to build the MFC sources as a DLL.

The latest version supports ARM64 too. See below.

Background, DEF file and LTCG

The first hurdle was the missing DEF file. The MFC DLL exports its symbols via a provided Module Definition File or DEF file. The linker uses this DEF file to create the LIB file for the DLL. I couldn't use the old VC++ 2005 DEF file because the MFC feature pack added a lot of new functions.

After some internet search, I discovered the tool: dumpexts.exe. I found the source code of it and modified it a little so it could create a DEF file for all the objs created by the compiler.

The tool is run as a pre-link Build Event for the MFCDLL project. Because Visual Studio has no macro with a list of all obj files, a DOS command enumerates all obj files in the Intermediate directory before calling dumpexts.exe. Be sure to first clean the MFCDLL project so that no old obj files are hiding in it.

When building the DLL the first time, also be sure Link Time Code Generation (LTCG) is not used. The object files the compiler generates when using LTCG cannot be read by dumpexts.exe. Luckily, once when we have generated a DEF file, it can be used in a future LTCG build.

Using the Code

When you clone the Github project, and run the Solution with Visual Studio 2019, a default wizard created MFC application is compiled and run but it uses the private MFC DLL!

To overcome copyright issues, the MFC source files are not included but read during compilation from the $(VCToolsInstallDir) folder. So no original MFC source files are included in the Solution except for one file: ctlpset.cpp. The original file gave a compiler error, so a fixed version is included.

1>------ Build started: Project: MFCDLL, Configuration: Release Win32 ------
1>ctlpset.cpp
1>C:\Program Files (x86)\Windows Kits\10\Include\10.0.18362.0\ucrt\corecrt_memcpy_s.h(50): 
error C4789: buffer 'var' of size 24 bytes will be overrun; 
24 bytes will be written starting at offset 8
1>Done building project "MFCDLL.vcxproj" -- FAILED.

Apparently, there are still bugs present in MFC after all those 28 years!

The current Character Set in the project configuration is set to UNICODE. If you use Multi Byte Character Set, then the file afxtaskdialog.cpp is excluded from the build (unload and edit the project file to see this).

In the original mfcdll.mak file, the source file dllmodul.cpp is compiled twice with different flags. Therefore, this file is copied to dllmodulX.cpp in the MFCstatic project. This project compiles a LIB file which needs to be linked to the EXE which is using the MFC DLL.

The MFCres project is a resource DLL which is a localization for German. However, its use is not very well tested in this project.

Points of Interest

One last point, which I don't understand. I needed to supply the /ENTRY point to all builds except the Release|Win32 build of the main application linker settings. It is set to wWinMainCRTStartup for UNICODE builds.

ARM64

For a successful compilation for ARM64, the file dispimpl_supporting.h was reconstructed. armasm.exe is used on objcall_.s to create objcall_.obj. This resolves the unknown symbols:

UNSUPPORTEDPLAT_PARAMS (_ARM64_PARAMS)
UnsupportedplatParamsReset
UnsupportedplatParamsAddFloat
UnsupportedplatParamsAddDouble

To test these functions, an Active X Control is added (Circ) to test passing floats and doubles on ARM64. Open the Aboutbox and click 'Circle Active X control', then click outside the circle. A MessageBox is shown if the float and double tests passes. Reg free COM is used to load the active X control when running the app. The x86 version of circ.dll file has to be registered in an admin console with regsvr32 circ.dll before Visual Studio shows the control.

Before building for ARM64, please build first for x64 (Debug and Release). The x64 dumpexts.exe is used in the ARM64 build.

History

  • 30th March, 2020: Initial version
  • 18th December, 2020: Added ARM64 support

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here