From: Keith Marshall Date: Mon, 22 Nov 2021 22:14:05 +0000 (+0000) Subject: Publish note on DLL version management. X-Git-Url: http://git.osdn.net/view?p=mingw%2Fwebsite.git;a=commitdiff_plain;h=1be8036421b4832b76a9ee9f6483554500e17758;ds=sidebyside Publish note on DLL version management. * dllver.html: New file. * docrefs.html: Add reference link. --- diff --git a/dllver.html b/dllver.html new file mode 100644 index 0000000..d5c3828 --- /dev/null +++ b/dllver.html @@ -0,0 +1,603 @@ + + + +
+

Introduction

+

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. +

+
+ +
+

Definitions

+
+
PE
+
The Microsoft Portable Executable  +file format; an adaptation of the common object file format, +it is sometimes identified as PE‑COFF. +
+
ELF
+
Executable and Linkable Format ; +this is an alternative executable, and shared library file format, +used by GNU/Linux, and several Unix systems; +it is not used by MS‑Windows. +
+
DLL
+
A dynamic link library ; +this is the terminology favoured by Microsoft, +when referring to shared libraries. +
+
Dynamic Linker
+
An operating system facility, +responsible for loading executable program files, +and shared libraries, +and resolving (linking) symbolic references across +executable file and shared library boundaries, +to construct a run‑time process image. +
+
Entry Point
+
This is any one of the publicly visible variable names, +or function names, which is exported by a specific DLL. +
+
Interface
+
This represents the aggregate of all entry points, +which are exported by the DLL. +
+
API
+
This represents the application programming interface ; +it is, effectively, the interface, +characterized by the entry point names, +data types, and function prototypes. +
+
ABI
+
This is the application binary interface ; +it represents, and is characterized by, +the machine‑level implementation of the interface. +
+
+ +
+

How the MS‑Windows Dynamic Linker Resolves Shared Library References

+

When a PE  file, +(typically, but not restricted to, +an executable  +‘*.exe ’, +or a shared library  +‘*.dll ’ +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  +rpath ’ +feature. +

+

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): +

    +
  1. The directory from which the executable file, itself, was loaded. +
  2. +
  3. The current working directory, at process start‑up time. +
  4. +
  5. The Windows system directory; +the path name for this directory may be identified, +by calling the GetSystemDirectory() function. +
  6. +
  7. The Windows directory; +the path name for this directory may be identified, +by calling the GetWindowsDirectory() function. +
  8. +
  9. The sequence of directories, taken in turn, +listed in the PATH environment variable; +(note that this is the path searched for executables themselves; +the LIBPATH environment 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, +(typically in C:\MinGW), +this is normally achieved by installation of both  +the *.exe files, and  their associated DLLs, +in the common C:\MinGW\bin directory, +so that DLL identification is completed in accordance with rule (1), above. +

+

Alternatively, +for any application whose *.exe files are not  +installed in the C:\MinGW\bin directory, +(since C:\MinGW\bin will typically be listed within +the user’s 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. +

+
+ +
+

How MinGW Shared Library Version Numbers are Assigned

+

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
+
The most recent interface [ABI version] number +that this library implements. +
+
revision
+
The implementation [revision] number of +the current  interface. +
+
age
+
The difference between [the ABI version numbers of] +the newest and oldest interfaces that this library implements. +In other words, +the library implements all the interface numbers in the range from number +current-age  +to current. +
+
+

These 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: +

    +
  1. Start with version information of ‘0:0:0’ +for each libtool library. +
  2. +
  3. Update the version information only immediately before a public release +of your software. More frequent updates are unnecessary, and only guarantee +that the current interface number gets larger faster. +
  4. +
  5. If the library source code has changed at all, +since the [version information was last updated], +then increment revision(i.e. +‘current:revision:age ’ becomes +‘current:revision+1:age ’ ). +
  6. +
  7. If any interfaces have been added, removed, +or changed since the last update, +increment current, +and set revision  to 0. +
  8. +
  9. If any interfaces [i.e. entry points ] +have been added since the last public release, +then increment age. +
  10. +
  11. If any interfaces [i.e. entry points ] have been removed, +or [the data type or function prototype +of any entry point has been] changed since the last public release, +then set age  to 0. +
+

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: +

    +
  1. Programs using the previous version +may use the new version as drop-in replacement, +and programs using the new version can also work with the previous one. +In other words, no recompiling nor relinking is needed. +In this case, bump revision  only, +don’t touch current  +[or] age. +
  2. +
  3. Programs using the previous version +may use the new version as drop-in replacement, +but programs using the new version may use APIs +[which are] not present in the previous one. +In other words, a program linking against the new version +may fail with “unresolved symbols” +if [deployed with] the old version at runtime: +set revision  to 0, +bump [i.e. increment both] current  +and age. +
  4. +
  5. Programs may need to be changed, +recompiled, and relinked in order to use the new version. +Bump current, +set [both] revision  +and age  to 0. +
+

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 +current:revision:age  triplet, +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 +current-age, +taking the individual values of current, +and 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 +current-age  +manually). +

+
+ +
+

Evolution of MinGW Shared Library Versions

+

To further illustrate the evolution of MinGW shared library versions, +let us consider the development life‑cycle of +a hypothetical library, libfoo.dll, +for which the most recent release corresponds to a GNU libtool +current:revision:age  triplet +of 5:4:3; +this indicates that the current ABI  version of +this hypothetical library is 5, +and that this version is fully backwardly compatible  with +each of the three  preceding releases, +with ABI  version numbers 4, +3, and 2; +thus, the MinGW library version, +computed as current-age, +will be 2, +yielding a versioned library name of libfoo-2.dll; +it may be observed that this version‑indicating name corresponds to +the oldest ABI  version which is fully compatible with +the current ABI  version 5 release. +

+

There are many evolutionary paths, +which libfoo‑2.dll may have followed, +to become the equivalent of a libtool‑managed 5:4:3 release; +the following example represents just one such possible path: +

    +
  1. Regardless of the path followed, +the starting point is always equivalent to +libtool release 0:0:0, yielding a computed +current-age  +value of 0-0, +(or simply 0); +thus, the MinGW designation for the initial release +will be libfoo‑0.dll. +
  2. +
  3. The library goes through several release cycles, +without any change in, addition to, +or removal from its public interface ; +the libtool revision  is incremented, +at each release, +through 0:1:0, 0:2:0, ..., +but, since neither current, +nor age  is changed, +the MinGW release designation remains as libfoo‑0.dll. +

    This is correct, +because the interface  remains unchanged from +the initial  release; +programs linked against the initial release may continue to use +this libfoo‑0.dll, +as a drop‑in replacement for the original, +while benefitting from any bug‑fixes +which may have been applied in the newer releases. +

  4. +
  5. Following the release of 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, +the libtool current  version number +is incremented, +while resetting the revision  +to 0, +(to account for the addition of the new entry point ); +at the same time, age  +is incremented in lock‑step, +(because backward  compatibility, +with the preceding release, is preserved). +Consequently, the libtool release identification becomes 1:0:1, +since the result of computing +current-age, +(which now becomes 1-1), +remains equal to 0, and thus, +the MinGW library designation remains as +libfoo‑0.dll. +Once again, this is correct; in spite of the change +in libtool current  release number, +the oldest  value of current  +release, with which this release remains backwardly  compatible, +is still 0. +

  6. +
  7. After the release of 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 +current-age, +advances to 2, resulting in a new MinGW library designation +of libfoo‑2.dll. +

    Note that this is, once again, correct: +the libtool current  release number has advanced, +to 2; this release is no longer backwardly  +compatible with any other release, older than itself, +and the MinGW release number has also advanced accordingly; +this libfoo‑2.dll is not  suitable for +use as a drop‑in replacement for libfoo‑0.dll, +and the DLL file name has been changed, to prevent any such misuse. +

  8. +
  9. The next few release cycles, +following the preceding release of 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 +3:0:1, 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 +current-age  +computation will continue to yield a MinGW release number of 2, +and the MinGW library will continue to be named libfoo‑2.dll. +
+

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 4 of +the implementation of version 5 of the interface, +and that this implementation is fully backwardly compatible  +with version 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 +version of libfoo‑2.dll is its most recently +released distribution; +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 +interface  versions, +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. +

+
+ +
+

Conclusion

+

“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. +

+
+ + diff --git a/docrefs.html b/docrefs.html index c70cce8..90c5cf6 100644 --- a/docrefs.html +++ b/docrefs.html @@ -86,6 +86,9 @@ HOWTO Interpret the Names of Packages Distributed by MinGW.OSDN
HOWTO Write Specifications for Packages to be Distributed by MinGW.OSDN
+
+HOWTO Manage a Collection of Installed MinGW Dynamic Link Libraries +