This Mini‑HOWTO offers advice on installation, and explains the conventions which have been adopted by MinGW, (and also by Cygwin), to identify disparate versions of similarly named shared libraries, (DLLs), and so mitigate the “DLL Hell” which may arise, as a result of software dependencies on potentially incompatible versions of such DLLs.
The content herein is derived from an original web document, originally posted by Soren Andersen, (a.k.a. Perlspinr), and now accessible only via this WayBack Machine archive; this, in turn, was inspired by a no‑longer‑accessible posting, by Charles (Chuck) Wilson, on a mailing‑list discussing Portable Network Graphics (PNG) implementation; the original content has been generalized, to eliminate PNG‑specific references, and expanded upon, in a MinGW‑specific context.
When a PE  file,
(typically, but not restricted to,
or a shared library
file), is created, the build‑time  linker,
(e.g. the MinGW linker ... not
the dynamic linker ),
embeds references, within the PE  file itself,
to any shared libraries on which it depends.
Each such reference takes the form of just a DLL file name,
without  any directory path name qualification,
and there is no direct analogue for the ELF
When the Windows dynamic linker  creates a new process image, it first loads the PE  executable program file into memory. It then attempts to load each shared library, named as a DLL reference within the PE  file, (and iteratively, any further named DLL references within the loaded DLLs themselves), mapping each one into the process address space, and resolving symbol references across DLL boundaries; only after all named DLLs have been loaded, and all symbol references successfully resolved, will execution of the process commence.
To locate each DLL, named in PE  file references, the MS‑Windows dynamic linker will search in each of the following directories, in turn; (this search will continue, through the directory sequence, only as far as is necessary to locate the first  DLL file, with a name which matches the reference):
PATHenvironment variable; (note that this is the path searched for executables themselves; the
LIBPATHenvironment variable is not considered, and
LD_LIBRARY_PATH— a standard environment variable which is commonly associated with ELF  shared libraries — has no defined purpose in the MS‑Windows environment).
Note that each uniquely named DLL file, irrespective of the directory path from whence it is loaded, will be mapped into the process address space only once. Furthermore, if the instance of each named DLL, which is located first in the above directory search sequence, fails to resolve all entry points  which it is expected to provide, process execution will fail; the search will not  be resumed, even if a similarly named DLL file, from a later directory in the search sequence, may be an alternative version, from which the missing entry points  could have been resolved.
It is important to ensure that,
if an application requires a particular version of any DLL,
that the correct DLL is installed in a location whence it will be identified
early in the preceding search sequence.
In a conventional MinGW installation,
this is normally achieved by installation of both
*.exe files, and  their associated DLLs,
in the common
so that DLL identification is completed in accordance with rule (1), above.
for any application whose
*.exe files are not
installed in the
C:\MinGW\bin will typically be listed within
PATH environment variable),
MinGW DLLs may be identified in accordance with rule (5).
When applications depend on this DLL identification stratagem,
it is strongly  recommended that all
MinGW DLLs be kept fully up to date,
to ensure that compatibility is maintained,
as explained below,
for all  dependent applications,
regardless of age.
The single value, as assigned as a MinGW shared library version number, is derived from an effective GNU libtool current:revision:age triplet, which itself, is managed in accordance with the convention described in libtool‑versioning section of the GNU libtool manual:
[...] libtool library versions are described by three integers:
current:revision:age attributes are assigned,
by the maintainer of the library,
as specified in the immediately following section of the GNU libtool manual:
Here are a set of rules to help you update your library version information:
0:0:0’ for each libtool library.
revision  (i.e. ‘
current:revision:age ’ becomes ‘
1:age ’ ).
current, and set
Never try to set the interface numbers so that they correspond to the release number of your package. This is an abuse that only fosters misunderstanding of the purpose of library versions. [...]
The following explanation may help [you] to understand the above rules a bit better: consider that there are three possible kinds of reactions from users of your library to changes in a shared library:
revision  only, don’t touch
0, bump [i.e. increment both]
current, set [both]
In the above description, programs using the library in question may also be replaced by other libraries using it.
To derive the single‑valued MinGW shared library version number,
from the GNU libtool compatible
we adopt the convention originally suggested by Gary Vaughan,
in a posting to the Cygwin mailing‑list,
to the effect that the effective shared library version should be
set equal to the version number of the oldest ABI  version
supported by the shared library;
this is equivalent to the result of the calculation
taking the individual values of
age  from the libtool triplet.
(Note that this does not require  use of libtool
for maintanence of the shared library;
it is sufficient to adopt the libtool numbering convention,
and to calculate
To further illustrate the evolution of MinGW shared library versions,
let us consider the development life‑cycle of
a hypothetical library,
for which the most recent release corresponds to a GNU libtool
this indicates that the current ABI  version of
this hypothetical library is
and that this version is fully backwardly compatible  with
each of the three  preceding releases,
with ABI  version numbers
thus, the MinGW library version,
yielding a versioned library name of
it may be observed that this version‑indicating name corresponds to
the oldest ABI  version which is fully compatible with
the current ABI  version
There are many evolutionary paths,
libfoo‑2.dll may have followed,
to become the equivalent of a libtool‑managed
the following example represents just one such possible path:
0:0:0, yielding a computed
age  value of
0, (or simply
0); thus, the MinGW designation for the initial release will be
revision  is incremented, at each release, through
..., but, since neither
age  is changed, the MinGW release designation remains as
This is correct,
because the interface  remains unchanged from
the initial  release;
programs linked against the initial release may continue to use
as a drop‑in replacement for the original,
while benefitting from any bug‑fixes
which may have been applied in the newer releases.
libfoo‑0.dll, corresponding to (say) libtool release
0:4:0, a new function entry point  is added, without  changing the established interface in any way. This introduces a forwardly incompatible  change in the API,  (because any new application which depends on the new entry point  will be incompatible with any earlier release of
libfoo‑0.dll); however, the API  remains backwardly compatible  with previous releases, (because none  of the previously existing entry points  exhibit any change in behaviour).
To reflect this change in compatibility,
current  version number
while resetting the
(to account for the addition of the new entry point );
at the same time,
is incremented in lock‑step,
(because backward  compatibility,
with the preceding release, is preserved).
Consequently, the libtool release identification becomes
since the result of computing
(which now becomes
remains equal to
0, and thus,
the MinGW library designation remains as
Once again, this is correct; in spite of the change
current  release number,
the oldest  value of
release, with which this release remains backwardly  compatible,
libfoo‑0.dll, at libtool release point
1:0:1, one of the publicly visible entry point  functions is deemed to have become obsolete, and is removed. This represents another change to the public interface, so once again the libtool
current  release number must be incremented, and the
revision  reset; however, this is not  a backwardly compatible  change, so, for this release,
age  is reset to
0, rather than being incremented. The effect of this is that the libtool release number advances to
2:0:0, and the MinGW release number, computed as
age, advances to
2, resulting in a new MinGW library designation of
Note that this is, once again, correct:
current  release number has advanced,
2; this release is no longer backwardly
compatible with any other release, older than itself,
and the MinGW release number has also advanced accordingly;
libfoo‑2.dll is not  suitable for
use as a drop‑in replacement for
and the DLL file name has been changed, to prevent any such misuse.
libfoo‑2.dll, may proceed as described in (2), above, thus requiring only the libtool
revision  to be incremented, without  affecting the MinGW release number, in any way. These may be interspersed with three further cycles, similar to that described in (3), above, in which any number of new entry points  are added, but none  are removed or modified; after the third such type (3) release, the libtool release number will have advanced through
4:0:2, and finally
5:0:3. If this is then followed by by four further type (2) releases, there will be four further increments in the libtool
revision, ultimately advancing the libtool release number to
5:4:3; at this stage in the release cycle sequence, the
age  computation will continue to yield a MinGW release number of
2, and the MinGW library will continue to be named
It may be observed that,
following the preceding sequence of release cycles,
whereas the libtool release number is able to convey the information that
the current library version implements revision
the implementation of version
5 of the interface,
and that this implementation is fully backwardly compatible
2 of this interface,
the MinGW release number cannot adequately convey any more than
the last of these pieces of information.
Although this limitation may appear to be problematic,
in practice it isn’t, provided  the installed
libfoo‑2.dll is its most recently
unlike ELF dynamic linkers,
the PE dynamic linker  simply isn’t smart enough
to select a DLL on the basis of a range  of supported
so the best we can hope for is that the selected library,
as named for its oldest  supported version,
covers the required range;
the most effective assurance that we can have for this
is that the selected library is the most recently released distribution,
with the specified name.
“DLL Hell” arises when two identically named shared library files provide different (incompatible) APIs  ... perhaps even incompatible versions of fundamentally the same API ; a common cause is that installation of some third‑party software product has overwritten an installed DLL file with an obsolete version.
Sometimes, a particular software product requires a particular version of a specific DLL, with which the most recent version of that DLL is not backwardly compatible,  (because the developer of that DLL may not have exercised good version control discipline). To avoid this kind of issue, MinGW has adopted a DLL version management discipline, conforming to the following conventions:
Adoption of these conventions ensures that, if the most recent release of each, and every required MinGW DLL is installed, at an appropriate location within the DLL directory search path, then, on account of the promise of backwards compatibility,  applications which are dependent on any releases of these DLLs will continue to operate as intended. Additionally, it allows releases of mutually incompatible, similarly named (but for the version identifier) DLLs to co‑exist, within the DLL search path, thus ensuring that applications which may depend on older, incompatible DLL versions, may continue to operate correctly.
Unfortunately, the conventions alone cannot  prevent any user, or third‑party package installer, from replacing the most recent MinGW release of any DLL with an older release, (or with an incompatible third‑party DLL with the same name). Since forward compatibility  is never  promised, for an older MinGW DLL release used in conjunction with an application which may be dependent on a more recent release, (nor is there any  expectation of any form of compatibility  from any  third‑party DLL), it becomes incumbent upon the user, to ensure that only  the most recent releases of MinGW DLLs are (and remain) installed.