G77, libg2c and a linking problem
Dave Korn
dave.korn@artimi.com
Thu Sep 21 18:42:00 GMT 2006
On 19 September 2006 23:05, Angelo Graziosi wrote:
> What would be 'unusual or incorrect' in
>
> $ cat hello.F
> program hello
> implicit none
> write(*,*) 'Hello!'
> end
>
> (1)
> $ g77 hello.F -o hello -L/usr/lib/gcc/i686-pc-cygwin/3.4.4 -lg2c
>
/usr/lib/gcc/i686-pc-cygwin/3.4.4/../../../libcygwin.a(libcmain.o):(.text+0xab
):
> undefined reference to `_WinMain@16'
> collect2: ld returned 1 exit status
Well, the -L option adds a standard library directory to the wrong point in
the library search path, and the -l option adds a standard library to the
wrong point in the link order. You're meant to leave CRT stuff to the driver,
which *knows* what to do. If you wanted to do it yourself, and guarantee to
get it right, you'd have to reimplement the entire specs mechanism in your
makefile.
> (2)
> $ g77 hello.F -L/usr/lib/gcc/i686-pc-cygwin/3.4.4 -lg2c -o hello
>
> $ ./hello
> Hello!
I'll do the -v thing myself then, shall I?
--------------------------------<snip>--------------------------------
$ g77 -v hello.F -o hello -L/usr/lib/gcc/i686-pc-cygwin/3.4.4 -lg2c
/usr/lib/gcc/i686-pc-cygwin/3.4.4/collect2.exe -Bdynamic
--dll-search-prefix=cy
g -o hello.exe
/usr/lib/gcc/i686-pc-cygwin/3.4.4/../../../../i686-pc-cygwin/lib/
crt0.o -L/usr/lib/gcc/i686-pc-cygwin/3.4.4 -L/usr/lib/gcc/i686-pc-cygwin/3.4.4
-
L/usr/lib/gcc/i686-pc-cygwin/3.4.4
-L/usr/lib/gcc/i686-pc-cygwin/3.4.4/../../../
../i686-pc-cygwin/lib -L/usr/lib/gcc/i686-pc-cygwin/3.4.4/../../..
/win/c/DOCUME
~1/dk/LOCALS~1/Temp/ccOxEzrm.o -lg2c -lgcc -lcygwin -luser32 -lkernel32
-ladvapi
32 -lshell32 -lgcc
/usr/lib/gcc/i686-pc-cygwin/3.4.4/../../../../i686-pc-cygwin/lib/libcygwin.a(l
ib
cmain.o): In function `main':
/usr/build/src-winsup/winsup/cygwin/lib/libcmain.c:40: undefined reference to
`_
WinMain@16'
collect2: ld returned 1 exit status
$ g77 -v hello.F -L/usr/lib/gcc/i686-pc-cygwin/3.4.4 -lg2c -o hello
/usr/lib/gcc/i686-pc-cygwin/3.4.4/collect2.exe -Bdynamic
--dll-search-prefix=cy
g -o hello.exe
/usr/lib/gcc/i686-pc-cygwin/3.4.4/../../../../i686-pc-cygwin/lib/
crt0.o -L/usr/lib/gcc/i686-pc-cygwin/3.4.4 -L/usr/lib/gcc/i686-pc-cygwin/3.4.4
-
L/usr/lib/gcc/i686-pc-cygwin/3.4.4
-L/usr/lib/gcc/i686-pc-cygwin/3.4.4/../../../
../i686-pc-cygwin/lib -L/usr/lib/gcc/i686-pc-cygwin/3.4.4/../../..
/win/c/DOCUME
~1/dk/LOCALS~1/Temp/ccwxRLEP.o -lg2c -lfrtbegin -lg2c -lgcc -lcygwin -luser32
-l
kernel32 -ladvapi32 -lshell32 -lgcc
--------------------------------<snip>--------------------------------
When you snip out all the extraneous options and just look at the input
files and -L and -l options, here's what you get:
--------------------------------<snip>--------------------------------
$ g77 -v hello.F -o hello -L/usr/lib/gcc/i686-pc-cygwin/3.4.4 -lg2c
/usr/lib/gcc/i686-pc-cygwin/3.4.4/../../../../i686-pc-cygwin/lib/crt0.o
-L/usr/lib/gcc/i686-pc-cygwin/3.4.4
-L/usr/lib/gcc/i686-pc-cygwin/3.4.4
-L/usr/lib/gcc/i686-pc-cygwin/3.4.4
-L/usr/lib/gcc/i686-pc-cygwin/3.4.4/../../../../i686-pc-cygwin/lib
-L/usr/lib/gcc/i686-pc-cygwin/3.4.4/../../..
/win/c/DOCUME~1/dk/LOCALS~1/Temp/ccOxEzrm.o
-lg2c -lgcc -lcygwin -luser32 -lkernel32 -ladvapi32 -lshell32 -lgcc
$ g77 -v hello.F -L/usr/lib/gcc/i686-pc-cygwin/3.4.4 -lg2c -o hello
/usr/lib/gcc/i686-pc-cygwin/3.4.4/../../../../i686-pc-cygwin/lib/crt0.o
-L/usr/lib/gcc/i686-pc-cygwin/3.4.4
-L/usr/lib/gcc/i686-pc-cygwin/3.4.4
-L/usr/lib/gcc/i686-pc-cygwin/3.4.4
-L/usr/lib/gcc/i686-pc-cygwin/3.4.4/../../../../i686-pc-cygwin/lib
-L/usr/lib/gcc/i686-pc-cygwin/3.4.4/../../..
/win/c/DOCUME~1/dk/LOCALS~1/Temp/ccwxRLEP.o
-lg2c -lfrtbegin -lg2c -lgcc -lcygwin -luser32 -lkernel32 -ladvapi32 -lshell32
-lgcc
--------------------------------<snip>--------------------------------
A single glance at the last line shows that the difference is -lfrtbegin.
Further, because you specified -lg2c yourself, the g77 driver specs assume
you know what you're doing, and in particular that -lfrtbegin must be
specified *before* -lg2c. The specs would have taken care of that, but you
overrode them; you can fix the buggy version of your command line by manually
adding -lfrtbegin:-
--------------------------------<snip>--------------------------------
$ g77 hello.F -o hello -L/usr/lib/gcc/i686-pc-cygwin/3.4.4 -lg2c
/usr/lib/gcc/i686-pc-cygwin/3.4.4/../../../../i686-pc-cygwin/lib/libcygwin.a(l
ib
cmain.o): In function `main':
/usr/build/src-winsup/winsup/cygwin/lib/libcmain.c:40: undefined reference to
`_
WinMain@16'
collect2: ld returned 1 exit status
$ g77 hello.F -o hello -L/usr/lib/gcc/i686-pc-cygwin/3.4.4 -lfrtbegin -lg2c
dk@rainbow /tmp/g77>
--------------------------------<snip>--------------------------------
For full information, read .../gcc-3.4.4/gcc/f/g77spec.c, look in particular
at the function lang_specific_driver and the variables and comments:
--------------------------------<snip>--------------------------------
/* This will be NULL if we encounter a situation where we should not
link in libf2c. */
const char *library = FORTRAN_LIBRARY;
/* 0 => -xnone in effect.
1 => -xfoo in effect. */
int saw_speclang = 0;
/* 0 => initial/reset state
1 => last arg was -l<library>
2 => last two args were -l<library> -lm. */
int saw_library = 0;
/* 0 => initial/reset state
1 => FORTRAN_INIT linked in */
int use_init = 0;
[ ... snip ... ]
/* First pass through arglist.
If -nostdlib or a "turn-off-linking" option is anywhere in the
command line, don't do any library-option processing (except
relating to -x). Also, if -v is specified, but no other options
that do anything special (allowing -V version, etc.), remember
to add special stuff to make gcc command actually invoke all
the different phases of the compilation process so all the version
numbers can be seen.
--------------------------------<snip>--------------------------------
Ach, there's the bug! If -lg2c is the very last option on the line, it has
saw_library=1, and then it exits and never does anything about it. Adding any
option, even another -v, makes it go round the loop again and it all works.
Hmm... it could try to prepend FORTRAN_INIT if it hadn't got use_init set by
the time it sets saw_librry to 1. Dunno why it doesn't. Probably a
corner-case.
cheers,
DaveK
--
Can't think of a witty .sigline today....
--
Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple
Problem reports: http://cygwin.com/problems.html
Documentation: http://cygwin.com/docs.html
FAQ: http://cygwin.com/faq/
More information about the Cygwin
mailing list