Subject: Re: Some problems in making DLL's for C++ programs with GCC
From: [email-masked] (Fergus Henderson)

14 Feb 1997 12:44:11 -0800
Approved: [email-masked]
Distribution: cygnus
Message-ID: <[email-masked]>
Content-Type: text
Original-To: [email-masked] (Nick van Eijndhoven)
Original-Cc: [email-masked] (gnu-win32)
In-Reply-To: <[email-masked]> from "Nick van Eijndhoven" at Feb 12, 97 01:45:30 pm
X-Mailer: ELM [version 2.4 PL24]
Original-Sender: [email-masked]

Nick van Eijndhoven wrote:
> 
> > 1) Put all your compiled c++ stuff into a library using ar
> >    ar rc lib.a <objects>
[...]
> > 2) generate the .def file from lib.a
> >    echo EXPORTS > foo.def
> >    nm lib.a | grep " [CT] " | sed '/ _/s// /' | awk '{print $3; }' >> foo.def

I'm using

	%.def: %.a
		echo EXPORTS > $@
		nm $< | grep '^........ [T] _' | sed 's/[^_]*_//' >> $@

	%.exp %.stubs.a : %.def
		dlltool --def $< --dllname $*.dll \
			--output-exp $*.exp \
			--output-lib $*.stubs.a

in my GNUMake file. 

> ld -o foo.dll foo.exp *.o
> 
> --> here I got the following error msgs with the result that no .dll was created.
>     The error msgs were :
> 
>     ...../LD.EXE: warning: cannot find entry symbol _mainCRTStartup:
>                   defaulting to 00401000

That one seems safe to ignore.

>     aap.o<.text +0x10>:aap.cc: undefined reference to `cout'
>     ... and some more undef refs. to standard iostream stuff.
[...]
>     I therefore tried :
> 
> g++ -o foo.dll foo.exp *.o

THat is a bad idea, I think.  That will link in `crt0.o', which you
don't want to do.  `crt0.o' is the startup code that calls main(),
and it has an undefined reference to main().

>     ..../i386-cygwin32/lib/libcygwin.a<libcmain.o>: In function `main':
>     /pizza/mushroom/noer/beta17/src/winsup/libcmain.cc:30:
>      undefined reference to `WinMain@16'
> 
>     This error message I really don't understand (note that I didn't provide
>     a main() at all) and would appreciate if someone could help me out.

This is the due to the linker dragging in main() from the library.
libcmain.cc has a definition of main() that calls WinMain().

Instead of `g++ -o foo.dll foo.exp *.o', just use

	ld -o foo.dll foo.exp *.o `gcc --print-file-name=libg++.a`

This will link in libg++.a.

Actually I'm not sure whether this will link in _all_ of libg++.a,
even the bits you're not using.  If so, it would be better to do

	LIBGPP_FILE=`gcc --print-file-name=libg++.a`;
	LIBGPP_DIR=`dirname $LIBGPP_FILE`;
	ld -o foo.dll foo.exp *.o -L$(LIBGPP_DIR) -lg++

Now, even this is not quite enough.  I have found that you need to change
that to

	LIBGPP_FILE=`gcc --print-file-name=libg++.a`;
	LIBGPP_DIR=`dirname $LIBGPP_FILE`;
	ld -o foo.dll fixup.o foo.exp *.o -L$(LIBGPP_DIR) -lg++
		      ^^^^^^^

where fixup.s contains the following assembler code:

	.section .idata $3
	.long 0,0,0,0, 0,0,0,0

This avoids various problems where the file links OK but won't run.

Now, can anyone tell me what the situation with global variables in DLLs is?

--
Fergus Henderson <[email-masked]>   |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>   |  of excellence is a lethal habit"
PGP: finger [email-masked]         |     -- the last words of T. S. Garp.
-
For help on using this list, send a message to
"[email-masked]" with one line of text: "help".