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

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



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

--
Vincent Rivière