This is the mail archive of the
mailing list for the Cygwin project.
Re: dll vs static importing on cygwin
- From: Charles Wilson <cwilson at ece dot gatech dot edu>
- To: prapp <prapp at erols dot com>
- Cc: cygwin at cygwin dot com
- Date: Sun, 06 Jan 2002 15:43:23 -0500
- Subject: Re: dll vs static importing on cygwin
- References: <email@example.com>
Please don't send cygwin related questions to me personal. This belongs
on the cygwin list. I have copied the list and reset the Reply-To:
> I was just reading this:
The libtool macros referred to in that message are for the old-style
libtool (called "libtool-stable" and based on libtool-1.4.2 -- see
http://sources.redhat.com/ml/cygwin-apps/2001-12/msg00179.html for more
New-style libtool (not even in official libtool CVS yet, but Gary
Vaughan has promised to include them "eventually"; called
"libtool-devel" in msg00179 above) doesn't need special -Ddefines...
> and follow up articles.
> I'm trying to figure out how to fix a makefile
> for a unix program (lifelines.sourceforge.net, not that it
> matters) which uses ncurses, and I'm hitting what is probably
> a standard problem -- it is not linking to the dll version of
> ncurses, and therefore it fails linking.
How do you know this? What *exactly* is the error message?
> I don't actually
> understand why it fails linking -- (if libncurses.a is the static
> library, it should contain full code, and it ought to have all
> the symbols the dll exports too, I'd think).
Nope, you're wrong. The static lib contains only "_foo" representing
the foo "export". You CAN'T link directly to the DLL -- you must use an
import lib (GNU ld provides a mechanism where you can list the DLL on
the link line, but you STILL aren't linking directly to the DLL; ld
creates a virtual import lib on-the-fly and actually links your code to
THAT. This only works with functions, not variables)
The import lib provides a symbol "__imp__foo" (leaving questions of
auto-import and auto-export for later; back in August there were some
changes that simplify this whole nightmare. I'll get to that)
If your object file was compiled with a header that declared "foo" thusly:
extern __declspec(dllimport) int foo(.....)
Then the object file will attempt to link to the symbol "__imp__foo".
OTOH, if your object file was compiled with a header that declared "foo"
extern int foo(.....)
Then the object file will attempt to link to the symbol "_foo". In the
past (and present, for many packages) the header files themselves had a
tricky set of #defines to control how symbols are declared, so that "The
Right Thing" happens. But, it means you have to do BOTH of the following;
set the correct -Ddefines when COMPILING your object code
use the correct options when LINKING your code to the library
e.g. for cygwin's version of libjpeg, the header files assume you want
to link to the dll, and ensures that the symbols are declared with the
__declspec(dllimport) modifier. Also, GNU's ld has been modified so
that it searches for "lib????.dll.a" BEFORE "lib????.a" in ordinary
circumstances (although if .dll.a is not found, it will still link to .a
-- which can be a source of problems. Unfortunately, we cannot eliminate
this behavior because of backward compatibility issues) Therefore, to
build and link against the libjpeg DLL, you do this:
gcc -c myfile.c -o myfile.o
gcc -o myfile myfile.o -ljpeg
This actually links myfile.o with libjpeg.dll.a (but the RUNTIME
dependency is satisfied by cygjpeg6b.dll). This should be the default
case for most client packages...
However, if you want to link statically to libjpeg, then you must do this:
gcc -DJPEG_STATIC -c myfile.c -o myfile.o
gcc -static -o myfile myfile.o -ljpeg
The -DJPEG_STATIC insures that when myfile.c includes jpeg.h, jpeg.h
will declare the functions WITHOUT the __declspec(dllimport) modifier.
The '-static' flag to gcc tells it (to tell ld) to search for
"lib????.a" and NOT for "lib????.dll.a".
However, you could get undefined symbol problems if your .o was compiled
with -DJPEG_STATIC but you linked against the .dll.a, or if your .o was
compiled "normally" but you linked against the .a.
There are also #defines that are used to make jpeg.h declare the symbols
with __declspec(dllexport) -- that's DLLEXPORT, not dllimport -- but
this is only used when actually building the DLL itself.
Back in August, Paul Sokolovsky's auto-import/auto-export functionality
was added to GNU ld. By cleverly adding some extra symbols to the DLL
and to the import lib, Paul found a way to make the whole
declspec(dllimport) thing unneccessary. Note that ncurses as of version
5.2-7 was built "new style".
The import lib now contains __imp__foo as well as __nm__foo. If your
object file "wants" __imp__foo (that is, it was compiled with
__declspec(dllimport) modifiers on the imported symbols) then no
problems -- everything works as before. However, if your object file
was compiled WITHOUT those modifiers, then it wants "_foo". That's where
Paul's auto-import magic happens:
The __nm__* symbols contain the "devectorized" address of the import
symbols. If _foo isn't found, then ld adds __nm_ and links against
THAT. Then, during runtime, the windows PE loader will rewrite the
address with the correct offsets so that the references to _foo become
pointers to __imp__foo and then everything works. (Obvious question:
why don't you add "__imp_" and then link, instead of the "extra" step
with __nm_? Because it won't work. The Windows PE loader will screw
Okay, so what does all that mean? For NEW STYLE dlls and import libs,
it means the following will work:
1) header files NEVER declare symbols with __declspec(dllimport) [or
even __declspec(dllexport)]. Symbols are always declared the same way.
No need for ugly -DJPEG_STATIC or -DJPEG_I_AM_BUILDING_THE_DLL or
2) client object files can be compiled once and then linked with either
the import lib or the static lib. (And when building libraries, you can
build the object files once and then 'ar' them into a static lib or 'gcc
-shared' them into a dll/import libpair.)
3) Just use 'gcc ...' to link with the implib or 'gcc -static ...' to
link with the static lib.
gcc -o myfile.o myfile.c
gcc -o myfile myfile.o -ljpeg
gcc -static -o myfile-static myfile.o -ljpeg
> Maybe my problem
> is that I'm not linking to either library at link time!
> (I thought of this after typing out the rest of this email.)
Yeah, if you had provided the actual error message that gcc/ld reported,
then we could figure that out...
REALLY OLD SUBTHREAD:
> >The problem is, I really don't know how to look at a given
> >executable, say foo.exe, which depends on bar.dll and baz.dll, and say:
> > Ah, yes, foo is linked by name to bar.dll, but its linked by ordinal
> >to baz.dll.
> >So, how can you test anything if you don't know how to 'evaluate' the
> This ought to be answerable by looking at in the PE (portable executable)
> file in the imports section. I had somewhere around a utility by Matt
> Pietrick I think that read PE format & printed out info -- I mean, with
> source code. Unfortunately I lost it. If you still have this need, I'd
> be willing to try to find it again, and see if I can look into this
> (can I tell from the imports table which way it is importing -- I think
> answer must be yes -- revise program to do so, and send you).
That would be useful. Actually, adding this functionality to objdump
would be better, instead of a whole new utility. objdump is part of the
binutils distribution. (While you're mucking with the objdump source
code, there's a core dump that happens in certain cases when objdumping
new-style dll's -- search the list for more info. Fixing that problem
would be nice, too...)
> It was a sample distributed by Microsoft, and had some GPF that I had to
> fix (twice, because I lost the source & got it again before), and the fix
> is not obvious, so if I do this again, it is definitely going onto the
> development code CDs I burn & keep regularly now!
But MS copyright code is not allowed in binutils...so objdump changes
must be "original" code, not cut-n-paste from MS samples.
> Anyway, I'd be grateful if you might pass on (to me) any urls or
> notes you happen to have laying about, about how to link to dll import
> libs (.dll.a), or if not, suggestions on keywords I might try in web
> searching :)
Check the cygwin-apps archive, keyword "shared static" (May 2000).
Keyword "auto-import" (July 2001). That's all I can think of, right now.
> $ ld --version
> GNU ld version 2.11.92 20011001
> (I think that is both linker & loader, right ?)
Nope. We use the MS Windows builtin runtime loader for both implicit
dependencies and explicit dependencies. (implicit: foo.exe was linked
against "bar.dll". explicit: foo.exe dlopen()'s "baz.dll" in order to
access symbol "grue") However, there is no libdl library. Explicit
dlopen and dlsymbol function calls are handled by cygwin1.dll -- which
then relies on the windows runtime loader to actually load the dlopen'ed
DLL into memory.
Also, there is no "ld.so.conf" or whatnot -- the Windows loader uses the
executable PATH to find shared libraries (DLLs); there is no "builtin"
shared lib search path, and LD_LIBRARY_PATH has no effect.
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple
Bug reporting: http://cygwin.com/bugs.html