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]

DLL naming flamefest


Okay, I've just put the following packages up for test at
http://cygutils.netpedia.net/testing

zlib-1.1.3-5
libpng-1.0.8-2
jbigkit-1.2-3
jpeg-6b-3
tiff-3.5.503
gdbm-1.8.0-3
gettext-0.10.35-2
(cvs-1.11.0-1  not a library, but...)

The seven library packages have been recompiled to follow this naming
convention:

static lib:  libfoo.a     (not versioned)
import lib:  libfoo.dll.a (not versioned)
dll       :  cygfooX.dll  (versioned -- usually)

The header files have all been munged so that in 'normal' usage,
exported functions and data are decorated with __declspec(dllimport). 
Thus, under 'normal' usage, the client objects will be linked with the
dll.  Since the default behavior of ld is to link with .dll.a (the
import lib), this works.  Dynamic linking is the default behavior with
'my' libraries.  Usually, this means 'compile'N'go' -- dllized libs
*should* be transparent to clients.  However, on occaission a configure
script in a client package will cheat, requiring some workarounds.

To link statically, two changes are required.  When compiling the client
objects, a library-dependent -Ddefine must be used so that the library
function declarations in the header files are not decorated.  For zlib,
this is -DZLIB_STATIC.  Also, to force ld to link statically, the
'-Bstatic' ld option must be supplied (or just give gcc the '-static'
option).

None of this is new; the only change is the name of the dll's.  By using
the 'cyg' prefix, cygwin-specific libraries won't clash with other
system libraries with the same name.  For instance, I just ran into a
problem with MikTex -- it wants to use a particular native netpbm
distribution that contains libjpeg.dll, libtiff.dll, libpng.dll, etc. --
all native libraries.

Now, I can avoid conflicts by PATH settings so that in 'cygwin mode',
D:\cygwin\usr\bin is in the front of the path, and in 'normal mode'
D:\MikTek\netpbm is in the front.  However, this problem WILL bite
someone somewhere badly -- and in a way that cannot be finessed with
PATH settings.  With a recent addition to binutils-ld.exe (in cvs only,
no cygwin-package available yet) the 'cygfoo.dll' convention still
allows direct linking to the dll without using an import lib.  Although,
why you'd want to do this when an import lib is available, I dunno. 
I'll say more about this below.

So, IMO, cygfoo.dll is an improvement over libfoo.dll for cygwin
packages.  It makes us 'good neighbors' for other packages, and prevents
other packages from interfering with cygwin by using conflicting dlls.

Okay, so why the versioning?  Well, short answer: libpng.  libpng-2.x.y
is expected soon and will have an API that is incompatible
libpng-1.x.y.  So, clients that expect the libpng-1.x.y interface will
NOT work with libpng-2 dll's.  Clients that expect the 2.x.y interface
will NOT work with libpng-1 dll's. What if you want two libpng clients
on your system -- one that requires 1.x.y and the other requires 2.x.y. 
Somehow, you need both dll's on your system simultaneously.  Fine --
version them.  So, 1.x.y dll's are called "cygpng2.dll" and 2.x.y dll's
are called "cygpng3.dll" (why not "1" and "2"? Don't ask me -- the
png-developers specified "2" and "3" as the so-name versions on unix; so
we'll use 'em on cygwin).

So, IMO, cygfooX.dll is an improvement over cygfoo.dll.  It helps us
maintain a continuity of libraries and applications, so that when some
library modifies its API you don't have to go recompile every blasted
app on the system -- you can let both versions coexist, like the old/new
libc do (sortof) on linux.

I'll get to the drawbacks in a minute.

Next, why not version the static libs or import libs?  Well, because
that would make linking too difficult (for now).  Eventually, if you
wanted to have 27 different incompatible versions of a library
coexisting, then yeah -- you'd version the statlibs and implibs, and
probably use symlinks to force whichever link you want at build time. 
However, since the windows loader has to find the dll's, you can't use
symlinks for dlls because windows doesn't grok 'em.  Or, instead of
symlinking 'libfoo.a -> libfoo27.a', you'd specify -lfoo27 instead of
-lfoo on your link line.

But, since we probably only have one or two versions of any given
library, it makes since to *typically* let libfoo.a BE the statlib for
version #1. And let libfoo.dll.a BE the import lib for version #1.  When
version #2 comes out, THEN we worry about versioning statlibs & import
libs.  HOWEVER, you have to address the dll's NOW, because executables
compiled NOW will need to work THEN.  So, you can't rename dll's later;
they must be versioned in advance.

So what's this about a change to binutils?  CVS versions of binutils
accept a new
  '--dll-search-prefix=<prefix>' option.
This option changes the search order at link time, when doing a dynamic
link, to the following:
  libfoo.dll.a     (import libs are preferred)
  foo.dll.a
  libfoo.a         (then static libs -- which MIGHT 
                    be an import lib. There's also a 
                    more esoteric reason why this has 
                    to be here; I don't want to go 
                    into that now.)
  <prefix>foo.dll 
  libfoo.dll
  foo.dll

Eventually, (and don't pester the core team about this), the next
cygwin-binutils release will include this functionality.  At that time,
I'd like to get a patch into cygwin-gcc so that gcc calls ld with
'--dll-search-prefix=cyg'.  Then, when you specify '-lfoo' and there is
no import lib nor static lib, you can still link to cygfoo.dll using
DJ's on-the-fly virtual import lib spiffyness.  With these changes,
'cygfoo.dll' will be a fully supported, preferred *default* name for
dlls.

So, here's the downside:

This won't work as seamlessly for versioned dll's -- you'd have to
specify '-lfoo7' to link to cygfoo7.dll.  BUT, remember,
link-directly-to-dll-with-no-implib is an emergency fallback for dlls
that we don't have implibs for.  (Worse, if the dll is stripped you
can't link to it -- all of the dll's in the seven packages above are
stripped -- because I'm supplying implibs!)

Second, all the libraries have to be rebuilt to follow the new
convention. (Okay, I just did that. 'nuff said)  However, if someone
else out there has built, say, XEmacs, that depends on libpng.dll -- it
won't work anymore with the latest dot-releases of the libpng.  (That
is, libpng-1.0.9 will have nifty features, and since it's API compatible
with 1.0.8, you *could* just drop the new dll into /usr/bin and BANG!
instant XEmacs update.  However, the new libpng-1.0.9 dll will be called
cygpng2.dll -- but XEmacs will still use the old libpng.dll. Or bomb if
setup removes the old dll during the upgrade).

Basically, we version the dll's because we can't use symlinks -- Windows
is dumb.  We don't version the statlibs or import libs because we can
play symlink games later; all of our build tools DO understand
symlinks.  Also, dll's for 'frozen' libraries don't need to be
versioned.  zlib is NOT going to change its interface.  Neither is
gettext (libintl).  WAY too many things would break if those ever
changed their interface.  So, of the seven libraries listed above,
here's the breakdown:

UNVERSIONED  
zlib-1.1.3-5        very stable
gdbm-1.8.0-3        last update 2 yrs ago. next-to-last, 5 years.
gettext-0.10.35-2   last update 1.5 yrs ago.

VERSIONED
libpng-1.0.8-2
jbigkit-1.2-3
jpeg-6b-3
tiff-3.5.503

Now, before flaming, please read the following thread (all of it --
almost 200 messages!).  

"DLL naming conventions"
   http://www.cygwin.com/ml/cygwin/2000-08/msg01128.html
continues in the next month's archives:
   http://sources.redhat.com/ml/cygwin/2000-09/msg00000.html
there are lots of ancilliary branches.

"libtool"
   http://sources.redhat.com/ml/cygwin/2000-09/msg00137.html

"linking against shared libraries"
   http://sources.redhat.com/ml/cygwin/2000-09/msg00551.html

My opinions, and those of many others, underwent a shift during the
course of that debate.  My summary of the issue:
  (1) the core team doesn't care -- as long as they don't have to
recompile the packages for which they are responsible, just to match
this system.  They don't.  As it happens, every 'core' lib starts with
'cyg' anyway: cygwin, cygtcl, etc.
  (2) I was initially against it -- mostly out of laziness and the vain
hope that there was a better solution.  I now believe that hope was
vain.  So, I got off my lazy butt and recompiled.
  (3) Various other valid objections for a variety of good reasons. 
Michael Ring comes to mind here.  Even a few of MY objections were
valid. :-P
  (4) There's work going on in the libtool project that *may* eventually
make all this easier.  Gary Vaughan of the libtool group is up-to-date
on the ld--dll-search-prefix thing, and is aware of the cygfooX.dll
naming convention.  If this naming convention is accepted, "they" will
probably try to support it seamlessly (I may be speaking out of turn,
but that's *my* impression of various messages.)

<flame-retardant underwear ON>
<lexan faceshield ON>
<asbestos firesuit ON>

Okay, I'm ready!

--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]