Compiler Modules

The Visual C++ suite produces an executable from source files in distinct stages, each handled by its own module.

The production is typically set in train by executing the CL.EXE program. It is CL that is told what files to operate on and with what options. The general aim is that each C or C++ source file is compiled to produce a corresponding object file, then these are linked, possibly with more files, to produce the executable. It falls to CL to work out what processing is required and to coordinate the execution of the compiler modules and of the linker (which is in this sense also a compiler module but can be, and typically is, run independently of CL).


The production of an object file from a C or C++ source file is usually thought of as one operation, namely compilation. However, CL provides for this operation to go through as many as three stages. When the operation is arranged so that CL names the various stages while describing its progress (as when given multiple source files to process as a batch, with the /ZM option active), the names given are:

It happens that the Visual C++ suite does not actually supply a module for the Processing stage, which is anyway disabled unless an undocumented option is used (as discussed below). In ordinary experience, compilation therefore seems to be done in two stages and the modules for Compiling and for Generating Code are sometimes referred to as the front-end and back-end compilers, respectively. Indeed, they are given these names formally in the message text for fatal error C1905.

Visual C++ supplies two front-end compilers and one back-end compiler. The two front-end compilers, C1.DLL and C1XX.DLL, handle C and C++ source files respectively. Each takes one source file and produces from it a set of intermediate files. The back-end compiler, C2.DLL, takes the intermediate files and produces from them one object file. The intermediate files are then ordinarily deleted by CL.


The compiler modules are replacable. The /B1, /Bx and /B2 options name modules to use instead of C1, C1XX and C2 respectively. As if there ought to be a C1½ for the Processing stage, the /B1_5 option both activates this stage and names the module that is to do the work.

These compiler modules may each be a DLL or an executable. It seems that earlier versions of Visual C++ used executables. The use of DLLs instead of executables has a special benefit for performance when CL operates on a batch of source files, since the DLLs need not be reloaded when progressing from one source file to the next.


It is usual to leave CL to generate command lines for the various compiler modules based (mostly) on what CL is itself given as a command line. Some CL options pass to the relevant compiler module more or less unchanged. Others stand for some (useful) combination of options to pass to the compiler modules. CL applies rules for whether one option overrides, requires or is incompatible with some other option, and the compiler modules do in some cases just assume that the options passed through to them have no conflicts.

Each compiler module recognises command-line options that are not known to CL (and are not documented by Microsoft, though at least some are surely useful for more than Microsoft’s own purposes of maintaining and testing the compiler modules). The CL options /d1, /d1_5 and /d2 each name an option that CL is to pass to the relevant compiler module (with /d1 applying to both C1 and C1XX).


All compiler modules are initially enabled, except for the in-between compiler (for the Processing stage). Several command-line options have at least as side-effects that they enable or disable one or more compiler modules:

Options Compiling (C or C++) Processing Generating Code Linking
/E, /EP, /P, /Zg and /Zs enable disable disable disable
/BK disable      
/B1_5   enable    
/c and /ZX       disable

Only for /Zs and /c is the effect stated above the whole effect of the option. For /B1_5, the only other effect is to name the module (no name being known to CL by default).