This is the mail archive of the cygwin@sources.redhat.com mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

Re: DLL naming conventions


"Gary V. Vaughan" wrote:
> 
> Charles S. Wilson wrote:
> >
> > There is *something* in the windows system that gets notified that
> > myapp.exe depends on mydll.dll whenever you execute myapp.exe.  This
> > *something* searches the file system according to the search path
> > described earlier in this thread, loads the dll into the executable
> > process's memeory space (rebasing the memory location if necessary), and
> > fixes up all the internal pointers to match the in-process virtual
> > memory location.
> >
> > Isn't that considered a dynamic linker? (Whether you call that
> > *something* a dynamic linker or not is really immaterial.  The
> > *something* is a runtime loader, and that's what the reference above is
> > discussing)
> 
> Nope.  Tor is correct.  The libtool versioning system assumes that the
> runtime loader is smart enough to choose the most recent compatible
> version of each dll that an application was linked with.  Many of the
> operating systems that libtool supports have different rules for how
> to name these versions so that the runtime loader can do it's stuff.
> Libtool maps the unified version number scheme it exposes to the user
> onto the versioning rules for the host platform.  That is why it is
> okay to have libc5 and libc6 in the same directory on your Linux box.
> Infact I could have several incompatible versions of libc6 in my lib
> directory, and the runtime loader would choose the newest one that is
> binary compatible with the version that the application was originally
> linked with.

Hmmm....you can do this sort of thing -- in a limited way, of course --
with appropriate naming of the dll and importlib.  Recall that import
libs contain the hardcoded name of the dll for which they were built.

Also, there are two separate issues being discussed here: (1) how to
(compile-time) link against the 'right' version of a library, and (2)
how to insure that the 'right' dll is loaded at run-time.  In the first
case, 'right' just means the correct version that supports the necessary
interface; in the second case, 'right' means the correct version
compiled for the right environment -- since you can have windows-native
dlls, Paul's unix-emulation-environment-based dll's (PW), cygwin dll's,
UWin dll's -- all with (potentially) the same name.  Since windows-dll
loading is based on the executable path, and not 'LD_LIBRARY_PATH' or
similar, you've got a problem.

It would be nice if you could create a 'cygwin LD_LIBARY_PATH' and a 'PW
LD_LIBRARY_PATH' etc.  But that probably requires that you abandon dll's
altogether, create your own 'so' file format, write an ld.so (ld.dll?)
that will load .so's 'just like unix (tm)'.  And, for this to work
cleanly, such a beast would have to be written for ALL the major unix
emulation environments.  However, we're just concerned with cygwin,
here.  (I can't take credit for this idea; both Tor Lillqvist and Chris
Faylor have on occaision mentioned something similar)

While not abandoning the preceding idea, it IS a lot of work (and there
are a lot of implementation details to work out).  Although, it *will*
fix point (1) *and* point (2) above.  

Now, you can (mostly) fix point (2: runtime loading) by the simple
expedient of insuring that all dll's and exe's go into the same
directory. Ugly, but much easier that the above semi-proposal.  An
alternative solution to point (2) is to choose a unique prefix for dll's
built on each platform -- e.g. Paul's suggestion of 'cygfoo.dll' for
cygwin and 'pwfoo.dll' for his PW environment.  NOTE: you only need to
munge the prefix of the dll itself; the import lib and/or static lib can
still be 'libfoo.dll.a' or 'libfoo.a' -- because at
compiletime/linktime, we *control* the library search path and are not
limited by the global windows executable path.

You can (mostly) fix point (1: compiletime version) by careful naming
and use of import libs + careful naming and use of dll's.

For instance:

  libpng.dll.a  --> libpng3.dll.a  
                ^^
              symlink

  libpng30.dll.a  (most recent API, corresponds to png-2.0.x)
    embeds the name "libpng3.dll"
  libpng20.dll.a  (older API, corresponds to png-1.0.x)
    embeds the name "libpng2.dll"

Programs linked against '-lpng' will be dependent at runtime on
libpng3.dll. Programs linked against -lpng2 (or against '-lpng' before
version 2.0.x was installed -- e.g. when libpng.dll.a --> libpng2.dll.a)
will be dependent at runtime on libpng2.dll

Now, suppose that the png folks release a newer version, say png-2.1.x
that exposes some additional features, but is backwards compatible with
png-2.0.x.  Great.  You build it, but create:

  libpng31.dll.a (embeds the name libpng31.dll.a)
  libpng.dll.a -> libpng31.dll.a
  libpng3.dll (replaces the old version (*))

Now, /usr/lib contains:
  libpng.dll.a -> libpng31.dll.a
  libpng31.dll.a
  libpng30.dll.a
  libpng20.dll.a
and /usr/bin contains:
  libpng3.dll
  libpng2.dll

(*) you can't play simlink games with the dll's themselves, because the
windows loader doesn't grok cygwin's symlinks.  You *can* play simlink
games, as I've shown here, with the import libs, because the cygwin ld
and cygwin gcc do grok symlinks.

This scheme will work without the help of libtool (e.g. you can still
build & link dependent packages without being *forced* to use libtool)
but it's similar enough to the 'unix way' that libtool should be able to
handle it.

> 
> Libtool doesn't version dll's on Windows correctly right now, it uses
> the linux versioning scheme to calculate the numbers.  It should
> probably name them after the oldest ``interface'' (see the document
> quoted above) that the library fully supports.  That is, if you build
> a dll using libtool's --version 5:4:3, you would get library2.dll
                                                       ^^^^^^^^^^^^
                   I think you mean library3.dll (supports v5, v4, & v3)

> (this version is at interface 5, but fully supports the last 3
> interfaces).  This gives the windows loader the best chance of finding
> the newest binary compatible dll.

In my scheme, --version 5:4:3 will give you library3.dll (assuming my
correction above is right), but you'd also get:

 library.dll.a --> library5.dll.a
 library5.dll.a (embeds the name library2.dll)

And these are still hanging around from previous builds
 library4.dll.a (embeds the name library2.dll)
 library3.dll.a (embeds the name library2.dll)
 library2.dll.a (embeds the name library1.dll)
 library1.dll

> 
> Unfortunately Windows makes no distinction between the application
> search path and the library search path, so the scheme I propose is
> still flawed =(O|  You might have a newer bugfixed binary compatible
> version of the dll you need, but if it is further down the application
> search path than the buggy version you originally linked with, you get
> the broken version.  Nice one Bill...

Yeah, but you're still assuming that the link lib and the runtime lib
are the same file.

> 
> Maybe Cygwin should put all of it's libtool built libraries (or any
> others that are correctly versioned w.r.t the runtime loader) into a
> single directory that is near the front of the default path.  /usr/lib
> seems like a good place.

That's part of my 'easy' solution above.  It may fix the cygwin problem,
but the requirement is not nice to native apps or other unix-on-win
emulations that the user may have.

Relying on 'get dll's from same dir as .exe' works -- but only if EVERY
cygwin exe and EVERY cygwin dll are piled into the same dir.

I *think* the combination of implib/dll versioning described above, plus
(sigh) unique prefixes for different platforms -- e.g. 'cygfoo.dll' --
will solve most of the problems brought up w.r.t compiletime/linktime
versioning, and runtime loading.  Without interfering too much with
native apps or other unix-emul packages.  So what do you lose?

-1) Can't link directly to a dll; you must use an import lib.  (why? #1,
ld only hunts for libfoo.dll & foo.dll, not cygfoo.dll. #2, if you link
directly to dll's without using import libs, you lose the clean
separation between 'runtime links' and 'development links' -- see
http://www.debian.org/Lists-Archives/lsb-spec-9905/msg00011.html.  I
know, there aren't really any 'runtime' symlinks, but at least you can
separate the major so-names...)

-2) It's a helluva lot of work to change everything on a platform (say,
cygwin) so that all dll's start with 'cyg' instead of 'lib'

-3) It mostly solves a lot of the issues, but not completely. Not
ideally. Not perfectly.

-4) Still requires significant changes to libtool to handle dll's and
importlibs.

What do you gain?

+1) mostly solves the problem
+2) you can still link dynamically or statically, without the use of
libtool if you so choose
+3) you don't have to develop an ld.so 'smart' runtime loader

Is +3) a bigger win than work involved in -2) ?
Will Chris, DJ, Corinna, et. al. even go for -2) ?

Developing an ld.so runtime loader requires far fewer changes to
libtool, and since you *can* link directly to dll's (*) it'll work 'just
like unix (tm). But developing ld.so will be a tough job.

(*) DJ has pushed a feature into ld that generates a 'virtual' import
lib on-the-fly if you put a dll in the link line.

--Chuck

--Chuck

--
Want to unsubscribe from this list?
Send a message to cygwin-unsubscribe@sourceware.cygnus.com


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]