The MinGW compiler comprises a comprehensive suite of separate programs, intended for deployment as a native compiler, on the Microsoft Windows platform, or alternatively, as a cross‑compiler for use on some other platform, to create applications for deployment on the native Windows platform. In either case, the compiler suite consists of, at least:–
In addition to the above, a native MinGW compiler deployment is accompanied by several other GNU DLLs, which are required to support the operation of the compiler itself; in the case of a cross‑compiler, the function of these additional DLLs is served by equivalents, which are native to the platform on which the cross‑compiler is run.
Regardless of whether it is deployed as a native compiler,
or as a cross‑compiler suite,
the MinGW compiler, assembler, and linker are normally invoked
by means of a common driver  program;
in the case of a native compiler,
this driver program is normally gcc
,
(or g++
, when compiling C++ code);
in the case of a cross‑compiler,
the corresponding driver programs may be mingw32‑gcc
,
and mingw32‑g++
,
(possibly qualified by an additional prefix,
to identify the target CPU).
In either case,
the driver program determines the sequence of auxiliary programs,
which are to be executed,
and the options and file names which are to be passed to them,
on the basis of:–
In this HOWTO, we explore the capabilities afforded by ‘specs’ string modifications, illustrating these capabilities by examples of:–
By default, the behaviour of GCC is controlled by a collection of ‘specs’ strings, which are defined at the time when GCC itself is built, and are built‑in to the driver program; such built‑in ‘specs’ strings are internally immutable,  but any of them may be redefined in external  ‘specs’ files, thus allowing them to be effectively modified  at GCC run‑time. Thus, it should be evident that customization of GCC behaviour will require the use of external  ‘specs’ files.
Before we embark on the customization process, it may be helpful to clarify some aspects of how GCC interprets, ‘specs’ files ... an area in which the GCC documentation, and its built‑in help are ambiguously vague! In particular, within the built‑in help:
$ gcc --help : -specs=<file> Override built-in specs with the contents of <file>. :
this terse description of the -specs
option,
while technically accurate,
may lead to a misconception that,
when this option is specified,
GCC will ignore its built‑in ‘specs’
in their entirety ;
however, in reality:
-specs=<file>
option,
GCC will,  with just one exception, 
initialize its default ‘specs’  state
to that which is directed by its built‑in ‘specs’.
-specs=specs
option; (indeed,
if it is, it will be read twice, 
the effect of which is unlikely to be desired).
-specs=<file>
option.
Each ‘specs’ file so nominated,
(more than one is permitted, in which case they will be read
in strictly left‑to‑right order, as nominated),
will augment  the prevailing ‘specs’ state,
(as it has been established at the time when each file is read);
augmentation may:
Having established an understanding of
how GCC processes ‘specs’ files,
we may now progress to development of our customization strategy.
First we must decide, in the case of each planned customization,
whether we would like it to affect every  GCC invocation,
or if it should be subject to selection,
by specification of a -specs=<file>
option.
In the former case,
the customization should be applied in a ‘specs’ file
which overrides all of the built‑in ‘specs’,
(i.e. in a file named “specs”);
in the latter, a selective customization
(in a file with any user-chosen name other than “specs”)
may be more appropriate.
Regardless of how any required ‘specs’ files are to be named, they must  be installed at an appropriate location within the GCC installation directory hierarchy; the appropriate directory path name may be identified, (as in this example for a MinGW installation of GCC-3.4.5), by running the command:
$ gcc -print-libgcc-file-name c:/mingw/bin/../lib/gcc/mingw32/3.4.5/libgcc.a
and discarding the final file name component of the path name,
to obtain a directory path name resembling
c:/mingw/bin/../lib/gcc/mingw32/3.4.5
.
Note: if you are running this
in an MSYS (or other POSIX‑compatible) shell,
and assuming that the sed
utility program is installed,
you may wish to use it, in an adaptation of the preceding command,
to obtain the requisite directory path name directly,
expressing it in canonical form):
$ gcc -print-libgcc-file-name | sed 's!/[^/]*$!!;:1;s![^/][^/]*/\.\./!/!;t 1' c:/mingw/lib/gcc/mingw32/3.4.5
Alternatively, in Microsoft’s cmd.exe
shell,
with a suitable POSIX‑compatible sed
utility program available,
you may use the same adaptation of the command,
except  that you must substitute double quotes,
in place of the single quotes:
C:\> gcc -print-libgcc-file-name | sed "s!/[^/]*$!!;:1;s![^/][^/]*/\.\./!/!;t 1" c:/mingw/lib/gcc/mingw32/3.4.5
If you plan to apply any customizations
which you wish to take effect every  time you run GCC,
(i.e. without  requiring
a -specs=<file>
option),
then you must  apply those customizations
within a ‘specs’ file which is
explicitly  named “specs”,
in the directory which you have just identified,
as described above.
If such a ‘specs’ file already exists,
then you are good to go;
back it up,
(in case you need to revert it ... a mistake in customization
could break GCC in some “interesting” way),
then proceed to edit it,
to apply your chosen customizations.
Conversely, if no file named “specs” yet exists,
in the appropriate directory,
you must create it.
Ideally, you should start from a baseline which exactly reproduces
GCC’s built‑in ‘specs’;
you may create, (or subsequently revert to), such a baseline,
by running the command:
$ gcc -dumpspecs > c:/path/to/libgcc/dir/specs
where /path/to/libgcc/dir
represents the path
to the directory in which libgcc.a
is installed,
as you have identified previously, from the output of the
gcc -print-libgcc-file-name
command;
(thus, by extension of the earlier example, you would execute):
$ gcc -dumpspecs > c:/mingw/lib/gcc/mingw32/3.4.5/specs
As noted in the
“Include File Search Path HOWTO”,
if a mingw32
build of GCC had been
configured to run on a typical Unix system,
it might be expected to search for include files
in /usr/local/include
,
some GCC and mingw32
specific directories,
and /usr/include
.
On its native MS‑Windows host,
when installed at its default file system location of C:/MinGW
,
it may seem reasonable to consider that C:/MinGW
could be used
as a representative equivalent of the /usr
directory
of the typical Unix system; thus,
C:/MinGW/local/include
would be equivalent to
the Unix system’s /usr/local/include
directory.
However, in a standard mingw32
build of GCC,
C:/MinGW/local/include
is conspicuously omitted 
from the configured include file search path.
On a Unix system,
the /usr/local/lib
file system hierarchy
would typically be used to segregate third‑party,
locally installed libraries, from the core system libraries,
with the corresponding header files,
associated with such locally installed libraries,
being placed into the file system hierarchy
below /usr/local/include
.
From a system management perspective,
this segregation is very convenient;
the absence of a similar file system infrastructure,
in a standard MinGW installation,
introduces an inconvenience which we would like to mitigate.
Of course,
having created a supporting directory structure,
and installed our third‑party header files within it,
we can always  instruct GCC to search for them by specifying
-I...
, -isystem
 ...
,
or even -iquote
 ...
options to GCC commands,
or by specifying CPATH=...
, C_INCLUDE_PATH=...
,
CPLUS_INCLUDE_PATH=...
, or OBJC_INCLUDE_PATH=...
environment variables,  as appropriate;
of more interest here, however,
is the development of an inconvenience mitigating configuration,
by means of ‘specs’ file customization.
Let us assume that we have created a suitable
file system hierarchy at C:/MinGW/local
,
and we have installed our third‑party header files
into C:/MinGW/local/include
;
(we could just as well have chosen a path outside
the default MinGW installation hierarchy
. . . say C:/Local/MinGW
,
with header files in
C:/Local/MinGW/include
. . .
but the principle remains the same;
we would simply substitute C:/Local/MinGW
for C:/MinGW/local
,
in ‘specs’ file references).
Given this assumption, as stated,
our objective will be to customize the GCC ‘specs’ state,
such that C:/MinGW/local/include
will be searched,
as if specified by -isystem C:/MinGW/local/include
,
every  time GCC is invoked.
Since we would like this customization to apply for every GCC invocation,
the most appropriate place to make the necessary changes is in the external
‘specs’ file which is explicitly named “specs”,
rather than in any which needs to be nominated by specification of
a -specs=<file>
option.
If this file already exists, make a backup copy of it,
(in case you mess it up, and need to revert it);
if it does not yet exist, create it.
(Please refer to the preceding section, within this document,
for advice on how to locate, or how to create, this “specs” file,
if you do not already know).
Next, open this “specs” file in your favourite text‑file editor, and add:
*local_prefix: c:/mingw/local/ *local_includes: -I %(local_prefix)include
at (or near) the top of the file, taking care to ensure that each of these new custom ‘specs’ string definitions, (while also taking care to preserve the same structure for all existing,  adjacent definitions), comprises exactly :
Finally,
to make GCC actually use 
our local_includes
definition,
we must append it to each of GCC's own (existing) ccp
,
and cc1plus
definitions.
While the “specs” file is still open,
in your text‑file editor,
move to the end of the file,
and add:
*cpp: + %(local_includes) *cc1plus: + %(local_includes)
(again, taking care to leave the two empty lines,  as shown), before saving the file, and quitting from the text‑editor, to complete the modification.
Astute readers may have noticed that,
to the extent to which this ‘specs’ file modification uses it,
our definition of local_prefix
is effectively redundant;
we could just as well have specified the value of
local_includes
directly, 
to be -isystem c:/mingw/local/include
,
and the effect would be the same.
We have chosen to define local_prefix
separately,
because, as we will see in the next section,
we will want to define a local_libpath
specification,
relative to the same file system prefix.
Of course, we could also specify local_libpath
entirely  within a single ‘specs’ string,
(including a duplicate of the prefix from local_includes
);
the advantage of defining local_prefix
separately,
and then relating both local_includes
and local_libpath
to it,
is that it offers us an option,
at some unspecified future time,
to relocate the entire  local file system hierarchy,
(from C:/MinGW/local
to C:/Local/MinGW
,
for example), by redefining, or by overriding, 
just the one local_prefix
‘specs’ string.
Further building on the underlying principles of, and complementing the customized include file search path configuration, as described in the preceding section, GCC also needs to be instructed where to search for the associated third‑party library files.
By analogy with the customized local include file search path,
which we have configured as c:/mingw/local/include
,
the logically corresponding local library search path would be
c:/mingw/local/lib
.
While the “Library Search Path HOWTO” indicates how
this search path may be specified,
without recourse to ‘specs’ file customization,
for the additional convenience which it will ultimately afford,
we are more interested, here, in how to specify this custom search path
using  ‘specs’ file customization.
Like the local include file search path configuration,
this ‘specs’ file customization will be most convenient
if its deployment does not  require the use of
a -specs=<file>
command line option.
So, assuming that you have already followed the preceding procedures,
to provision a primary ‘specs’ file,
(explicitly named “specs”),
and to configure the custom include file search path,
open this ‘specs’ file once again,
in your favourite text‑file editor;
locate the definition for local_includes
,
which you added previously, and below it,
add the definition:
*local_libpath: -L %(local_prefix)lib
once again, taking care to maintain correct structure, both within this new definition, and those adjacent to it.
Finally, to complete the configuration, and instruct GCC to use  this new custom search path, go to the end of the file, and add:
*link_libgcc: + %(local_libpath)
before saving the ‘specs’ file, and quitting the editor.
By default, the MinGW compiler/linker combination will link applications,
such that they depend on Microsoft’s MSVCRT.DLL
‘C’ runtime library;
while not strictly “free”,
in the sense defined by the GNU General Public Licence,
this does,  qualify for the GPL linking exemption
for integration with non‑free software components,
on the basis that it is distributed, by Microsoft,
as a standard Windows operating system component.
In addition to MSVCRT.DLL
,
Microsoft also distribute various alternative ‘C’ runtime libraries,
as components of their “Visual Studio”, or “Visual C”
software development suites.
Bearing names such as
MSVCR70.DLL
 ..
 MSVCR120.DLL
,
these are not  distributed as standard components
of the Windows operating system;
thus, they do not  qualify for the GPL linking exemption,
and MinGW.OSDN is not  licensed to distribute them.
Notwithstanding the foregoing licensing restrictions on their use,
the non‑free Microsoft ‘C’ runtime libraries
do  introduce a small number of functions,
which Microsoft have never incorporated into
MSVCRT.DLL
;
consequently, there may be occasions when users will
wish to link their MinGW applications with one of these
non‑free ‘C’ runtime libraries.
While MinGW.OSDN is not licensed to distribute these
‘C’ runtime libraries,
in DLL form,
we can,  and do, 
distribute import libraries  which map their entry points,
(at least for MSVCR70.DLL
 ..
 MSVCR100.DLL
),
so that any users who are prepared to handle the licensing implications,
and the provisioning of the DLLs for themselves,
may link their MinGW applications with these libraries,
if they so wish.
Some users may assume, naïvely,
that linking with, for example MSVCR80.DLL
, would be
as simple as adding the -lmsvcr80
library specification
to the gcc
command line;
unfortunately, it is not  as simple as this!
The problem with this naïve approach is twofold:–
-lmsvcr80
,
it is also necessary  to link with -lmoldname80
;
while it may appear that this would be as simple as
also adding -lmoldname80
,
this is also the wrong way to accomplish the objective!
-lmoldname80 -lmsvcr80
to the gcc
command line
is that the default GCC ‘specs’ strings already add 
-lmoldname -lmsvcrt
to the effective  gcc
command.
Thus, by also  adding
-lmoldname80 -lmsvcr80
,
we are asking the linker to search both 
libmoldname80.a
and  libmoldname.a
,
to resolve OLDNAME
symbols,
and ultimately both  libmsvcr80.a
and  libmsvcrt.a
,
to resolve ‘C’ runtime DLL references.
This introduces potential for the linked application to depend on
both  MSVCR80.DLL
and  MSVCRT.DLL
,
which is definitively unsupported ;
at best, you may  be lucky, and get away with it;
more likely, your application will be unstable,
and may crash and burn at run time,
with unpredictable side effects.
Thus, we should not simply specify -lmsvcr80
,
(either free‑standing, or accompanied by -lmoldname80
),
to the gcc
command line, when our intent is to link with
MSVCR80.DLL
, in preference to MSVCRT.DLL
.
(Nor, following similar reasoning, should we attempt to substitute
any of Microsoft’s other non‑free ‘C’
runtime DLLs, in this manner).
Rather, we must  modify the GCC ‘specs’ strings,
such that all  existing references to -lmsvcrt
,
and to -lmoldname
, are replaced  by
-lmsvcr80
and -lmoldname80
, respectively,
(or whatever alternative references are appropriate,
for the intended substitute ‘C’ runtime DLL).
Below, we will explore some methods for achieving this objective.
As we’ve seen above,
when we wish to link with any of Microsoft’s non‑free
‘C’ runtime libraries,
we really  ought to modify the GCC ‘specs’ strings,
to avoid any conflicting application dependencies on both 
MSVCRT.DLL
,
and the chosen non‑free DLL.
The default libraries specification,
for linking with MSVCRT.DLL
,
is -lmoldname -lmsvcrt
;
for linking with any of the non‑free ‘C’ runtime DLLs,
this couplet must  be replaced,
in any ‘specs’ string which includes it,
by an alternative couplet selected from the following table:–
To Use | Preprocessor Identification | Link With Libraries | Remarks |
---|---|---|---|
MSVCRT.DLL |
-lmoldname -lmsvcrt |
MinGW default; no preprocessor identification or ‘specs’ changes required | |
MSVCR70.DLL |
-D__MSVCRT_VERSION__=0x0700 |
-lmoldname70 -lmsvcr70 |
|
MSVCR71.DLL |
-D__MSVCRT_VERSION__=0x0710 |
-lmoldname71 -lmsvcr71 |
|
MSVCR80.DLL |
-D__MSVCRT_VERSION__=0x0800 |
-lmoldname80 -lmsvcr80 |
|
MSVCR90.DLL |
-D__MSVCRT_VERSION__=0x0900 |
-lmoldname90 -lmsvcr90 |
|
MSVCR100.DLL |
-D__MSVCRT_VERSION__=0x1000 |
-lmoldname100 -lmsvcr100 |
Note that,
in addition to the alternative libraries couplet,
the foregoing table also specifies a “preprocessor
identification ”,
for all but the default MSVCRT.DLL
case.
This should be added to the
cpp
‘specs’ string,
as applicable,
to ensure that definitions associated with the selected non‑free
runtime library are made visible,
when the compiler parses the appropriate ‘C’ header files.
A simple,
although rather naïve,
method of implementing the necessary ‘specs’ string modifications,
might be to create a separate copy of the ‘specs’ file,
specific to each non‑free runtime DLL
which we wish to support.
For example,
to support linking with MSVCR80.DLL
,
we might create a copy of an existing external ‘specs’ file,
(in the appropriate ‘specs’ file directory),
naming the copy as msvcr80
,
(or, if we don’t have an external ‘specs’ file,
use the gcc -dumpspecs
command to create msvcr80
,
as described under the heading “Preparing the GCC
‘specs’ for Customization”, above).
Once we have created a copy of the ‘specs’ file,
(which we’ve called msvcr80
, in our example case),
we may edit it, to implement the required customizations.
First, we should locate the cpp
string definition ...
it should look something like this:
*cpp: %{posix:-D_POSIX_SOURCE} %{mthreads:-D_MT} %{pthread:-D_REENTRANT} %{!no-pthread: }
or, if we’ve already added an additional include file search path:
*cpp: %{posix:-D_POSIX_SOURCE} %{mthreads:-D_MT} %{pthread:-D_REENTRANT} %{!no-pthread: } %(local_includes)
to which we must add
the appropriate preprocessor identification,  string,
selected from the table above,
(which, in the MSVCR80.DLL
case,
is -D__MSVCRT_VERSION__=0x0800
).
Thus, the modified definition becomes:
*cpp: %{posix:-D_POSIX_SOURCE} %{mthreads:-D_MT} %{pthread:-D_REENTRANT} %{!no-pthread: } -D__MSVCRT_VERSION__=0x0800
or:
*cpp: %{posix:-D_POSIX_SOURCE} %{mthreads:-D_MT} %{pthread:-D_REENTRANT} %{!no-pthread: } %(local_includes) -D__MSVCRT_VERSION__=0x0800
Second,
we must locate all occurrences of -lmsvcrt
,
and of -lmoldname
,
and replace each with the corresponding equivalents from the table above,
(i.e. -lmsvcr80
and -lmoldname80
, respectively,
in the case of the MSVCR80.DLL
example).
Typically, each will appear just once,
with both in the libgcc
string definition,
which initially, should look something like:
*libgcc: %{mthreads:-lmingwthrd} -lmingw32 -lmingwex -lmingw32 -lmingwex %{static|static-libgcc:-lgcc -lgcc_eh} %{!static:%{!static-libgcc:%{!shared:%{!shared-libgcc:-lgcc -lgcc_eh} %{shared-libgcc:-lgcc_s -lgcc}} %{shared:-lgcc_s -lgcc}}} -lmoldname -lmsvcrt
and, after modification, should look like this:
*libgcc: %{mthreads:-lmingwthrd} -lmingw32 -lmingwex -lmingw32 -lmingwex %{static|static-libgcc:-lgcc -lgcc_eh} %{!static:%{!static-libgcc:%{!shared:%{!shared-libgcc:-lgcc -lgcc_eh} %{shared-libgcc:-lgcc_s -lgcc}} %{shared:-lgcc_s -lgcc}}} -lmoldname80 -lmsvcr80
Finally,
while these two modifications are sufficient for gcc
,
they will not  pass the correct __MSVCRT_VERSION__
definition for compilation with g++
;
to correct this deficiency,
we must also modify the cc1plus
‘specs’ string,
(which, unless we've already added anything to it,
appears to be initially empty, by default), so we define it as:
*cc1plus: -D__MSVCRT_VERSION__=0x0800
or, if we had already added, e.g. an additional include files search path:
*cc1plus: %(local_includes) -D__MSVCRT_VERSION__=0x0800
With all three of the above modifications in place,
in the msvcr80
‘specs’ file,
we may invoke gcc
, (or g++
), like this:
$ gcc -specs=msvcr80 foo.c -o foo.exe
to compile, and link foo.exe
with MSVCR80.DLL
,
without  incurring any dependency on MSVCRT.DLL
.
However, the naïve simplicity of this ‘specs’ strings
modification technique does  make it sub‑optimal,
and may create potential problems;
in the following section,
we will discuss possible improvements to this simple modification technique.
The simplistic ‘specs’ strings modification technique, as described in the preceding section, for supporting the use of Microsoft’s non‑free ‘C’ runtime DLLs, exhibits the following potential disadvantages:–
specs
file copy thereof),
but modifies only two  of them.
An implication of this is that every one  of those
unmodified  ‘specs’ strings must 
be parsed twice ;
this is grossly inefficient.
specs
file,
but also  in every 
non‑free runtime specific auxiliary ‘specs’ file;
not only is this an undesirable maintenance burden ...
it is potentially error‑prone!
To some extent,
these disadvantages may be mitigated by elimination of
all  unmodified ‘specs’ strings from
each of the auxiliary ‘specs’ files,
leaving the entire  content of,
for example, the msvcr80
‘specs’ file,
(incorporating the additional include file search path modification),
as exactly :
*cpp: %{posix:-D_POSIX_SOURCE} %{mthreads:-D_MT} %{pthread:-D_REENTRANT} %{!no-pthread: } %(local_includes) -D__MSVCRT_VERSION__=0x0800 *cc1plus: %(local_includes) -D__MSVCRT_VERSION__=0x0800 *libgcc: %{mthreads:-lmingwthrd} -lmingw32 -lmingwex -lmingw32 -lmingwex %{static|static-libgcc:-lgcc -lgcc_eh} %{!static:%{!static-libgcc:%{!shared:%{!shared-libgcc:-lgcc -lgcc_eh} %{shared-libgcc:-lgcc_s -lgcc}} %{shared:-lgcc_s -lgcc}}} -lmoldname80 -lmsvcr80
(and similarly, for other auxiliary ‘specs’ files relating to other non‑free ‘C’ runtime DLLs).
This is better,
but it still leaves a significant degree of redundancy,
in the three definitions which do  need to be modified.
A simple way to remove some of this redundancy,
without  requiring any pyhsical change to
the originating definition,
as it appears in the built‑in ‘specs‘,
is by reformulating the amended cpp
and cc1plus
definitions as:
*cpp: + -D__MSVCRT_VERSION__=0x0800 *cc1plus: + -D__MSVCRT_VERSION__=0x0800
but, unfortunately,
we cannot adopt a similar adjustment to remove the redundancy
in the modified libgcc
definition.
If we do wish to eliminate the redundancies entirely, 
then we must  modify the libgcc
‘specs’
string at its point of origin;
this implies that we must  use an external 
specs
file,
in which we can make the necessary modification.
Thus, if we don't already have an external ‘specs’ file,
we should follow the procedure described above,
under the heading “Preparing the GCC
‘specs’ for Customization”,
to create one now.
Once we have set up an external ‘specs’ file,
such that gcc
, and g++
, will read it
instead of using their built‑in ‘specs’,
we may edit it,
splitting the original libgcc
definition
into a modified libgcc
,
and a supplementary libmsvcrt
definition, thus:
*libgcc: %{mthreads:-lmingwthrd} -lmingw32 -lmingwex -lmingw32 -lmingwex %{static|static-libgcc:-lgcc -lgcc_eh} %{!static:%{!static-libgcc:%{!shared:%{!shared-libgcc:-lgcc -lgcc_eh} %{shared-libgcc:-lgcc_s -lgcc}} %{shared:-lgcc_s -lgcc}}} %(libmsvcrt) *libmsvcrt: -lmoldname -lmsvcrt
(noting the use of parentheses  in the
%(libmsvcrt)
substitution field,
whereas braces are used elsewhere,
throughout the libgcc
definition).
Now,
with that single modification in place,
within the external specs
file,
the supplementary msvcr80
‘specs’ file
may be condensed, to nothing more than:
*cpp: + -D__MSVCRT_VERSION__=0x0800 *cc1plus: + -D__MSVCRT_VERSION__=0x0800 *libmsvcrt: -lmoldname80 -lmsvcr80
and Microsoft’s other non‑free ‘C’ runtime DLLs
may be similarly supported,
with suitably named copies of this supplementary ‘specs’ file,
each with appropriate changes to the __MSVCRT_VERSION__
assignment,
and the import libraries named in the libmsvcrt
definition.