[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [MiNT] g++ problem with archives & linking



On Thu, 2008-02-21 at 23:03 +0100, Vincent Rivière wrote:
> Alan Hourihane wrote:
> > this works fine on Linux, even with using -static or without.
> 
> First of all, run the gcc link command using -v in order to see the ld 
> command line:
> 
> $ m68k-atari-mint-gcc -o main libtest.a -v
> Using built-in specs.
> Target: m68k-atari-mint
> Configured with: ../gcc-4.2.3-mint-20080217/configure 
> --target=m68k-atari-mint --prefix=/usr/local/cross-mint 
> --enable-languages=c,c++ --disable-nls --disable-libstdcxx-pch
> Thread model: single
> gcc version 4.2.3 (MiNT 20080217)
>  
> /usr/local/cross-mint/lib/gcc/m68k-atari-mint/4.2.3/../../../../m68k-atari-mint/bin/ld.exe 
> -o main 
> /usr/local/cross-mint/lib/gcc/m68k-atari-mint/4.2.3/../../../../m68k-atari-mint/lib/crt0.o 
> -L/usr/local/cross-mint/lib/gcc/m68k-atari-mint/4.2.3 
> -L/usr/local/cross-mint/lib/gcc/m68k-atari-mint/4.2.3/../../../../m68k-atari-mint/lib 
> libtest.a -lgcc -lc -lgcc
> /usr/local/cross-mint/lib/gcc/m68k-atari-mint/4.2.3/../../../../m68k-atari-mint/lib/libc.a(main.o):main.o:(.text+0x312): 
> undefined reference to `_main'
> /usr/local/cross-mint/lib/gcc/m68k-atari-mint/4.2.3/../../../../m68k-atari-mint/lib/libc.a(main.o):main.o:(.text+0x61e): 
> undefined reference to `_main'
> 
> 
> The input files are (the order is important):
> /usr/local/cross-mint/m68k-atari-mint/lib/crt0.o
> libtest.a
> -lgcc	#/usr/local/cross-mint/lib/gcc/m68k-atari-mint/4.2.3/libgcc.a
> -lc	#/usr/local/cross-mint/m68k-atari-mint/lib/libc.a
> -lgcc	#/usr/local/cross-mint/lib/gcc/m68k-atari-mint/4.2.3/libgcc.a
> 
> The key to the explanation is that ld searches for undefined symbols in 
> the next input files, but not in the previously unused input files.
> 
> The linker begins by linking the first file (crt0.o) and it tries to 
> resolve the externals.
> 
> $ m68k-atari-mint-nm -u /usr/local/cross-mint/m68k-atari-mint/lib/crt0.o
>           U ___Ident_gem
>           U ___Ident_gnulib
>           U ___Ident_socketlib
>           U __acc_main
>           U __app
>           U __base
>           U __crtinit
>           U __heapbase
>           U __stksize
> 
> We see that crt0.o has several undefined externals (notably __crtinit) 
> but no reference to the _main symbol.
> 
> Then the linker looks to libtest.a. It contains none of the required 
> externals (only a useless _main symbol), so it is totally skipped.
> 
> Same skip for libgcc.a (the first one)
> 
> Then it looks to libc.a (the MiNTLib). The symbol __crtinit is resolved, 
> but a new unresolved external for _main is generated.
> 
> Then it looks to libgcc.a (second time). Most symbols are now resolved, 
> but not _main.
> 
> There are no more input files.
> 
> So no definition of _main is found after the reference, it is a link error.
> 
> A trick is to provide the linker a reference to _main before the definition:
> 
> $ m68k-atari-mint-gcc -o main -lc libtest.a # That works !
> 
> 
> I tried your testcase with Cygwin, and like in Linux, it works fine 
> without any trick from the user.
> How ? The explanation is in Cygwin's file crt0.c:
> http://cygwin.com/cgi-bin/cvsweb.cgi/~checkout~/src/winsup/cygwin/crt0.c?rev=1.4&content-type=text/plain&cvsroot=src
> The startup code calls cygwin_crt0() (the equivalent of our MiNTLib 
> _crtinit() with the main function as a parameter. So the startup code 
> has a reference to main(). So the main() function provided by the user 
> is always linked, even if it is in a library.
> 
> It would be easy to do get the same behavior with the MiNTLib: we just 
> have to add a "main" parameter to _crtinit()
> 
> However, I don't know if such a behavior should be assumed to be a 
> standard...

Ah, thanks for the solution Vincent. I'm going to modify my MiNTlib to
do this.

Alan.