[MITgcm-support] G95 build issue: f2c name mangling
Mark Hadfield
m.hadfield at niwa.co.nz
Sun Oct 8 21:38:23 EDT 2006
I am trying to build MITgcm with g95 (http://www.g95.org/). Why am I
doing this when I already have the model working OK with other
compilers? Bloody-mindedness mostly, but I like g95's bounds-checking
and the fact that its behaviour at run time can be determined with
environment variables.
Anyway, I've run into a problem with Fortran-C linking. I understand the
problem, up to a point, and I can think of various ways to work around
it. But there's an aspect that's really bugging me.
Working on Windows/Cygwin, I made a copy of cygwin_ia32_g77 as
cygwin_ia32_g95, changed FC in the latter to "g95" and removed an
unsupported compiler switch (-Wimplicit). The build process then went
ahead uneventfully until the final linking stage, where I got the
following error
timers.o:timers.for:(.data+0x2e8): undefined reference to `system_time__'
timers.o:timers.for:(.data+0x2ec): undefined reference to `user_time__'
I've tried with G95 on Linux with the same results.
Like I said, I understand this up to a point. Functions user_time,
system_time and timenow are written as C code in timer_stats.c and
called by Fortran code in timers.F. According to the G95 manual, "G95
follows the f2c convention of adding an underscore to public names, or
two underscores if the name contains an underscore." MITgcm handles
Fortran-C name-mangling with the FC_NAMEMANGLE macro, which in this case
is defined as:
#define FC_NAMEMANGLE(X) X ## _
This adds a single underscore to the function names where they are
declared in timer_stats.c. This means that the linker (g95) can link to
"timenow_", but not "user_time_" or "system_time_".
There are various possible solutions to this problem. Just adding a
second underscore to the FC_NAMEMANGLE macro doesn't work, as it makes
timenow invisible to the linker. (As far as I can tell, it is not
possible to make a cpp macro that will emulate the weird f2c behaviour.)
G95 supports an "-fno-second-underscore" option, which would solve the
problem nicely, but I then need to rebuild the netCDF library and my
initial attempts to do so did not work. The easiest workaround is to
define a special preprocessor symbol
cygwin_ia32_g95:
DEFINES='-D_BYTESWAPIO -DWORDLENGTH=4 -DG95'
and some special-case code:
timer_stats.c:
#if defined G95
double user_time__ (void)
#else
double FC_NAMEMANGLE(user_time) (void)
#endif
That's what I've done, but it's not very pretty, is it?
OK, but the question that's really bugging me is this. G77 also follows
the f2c name-mangling convention; the documentation says so and I have
confirmed this with some toy examples. For example:
$ cat main.f
program main
call c_sub()
end
$ cat c_sub.c
void c_sub_() {}
$ gcc -c c_sub.c
$ nm c_sub.o
00000000 b .bss
00000000 d .data
00000000 t .text
00000000 T _c_sub_
g77 main.f c_sub.o
/tmp/cc0iOz7I.o:main.f:(.text+0x7): undefined reference to `_c_sub__'
collect2: ld returned 1 exit status
So how does the G77 linker recognise the one-underscore names,
"user_time_" and "system_time_", in timer_stats.o when it doesn't
recognise "c_sub_" in the toy case above?
--
Mark Hadfield "Kei puwaha te tai nei, Hoea tahi tatou"
m.hadfield at niwa.co.nz
National Institute for Water and Atmospheric Research (NIWA)
More information about the MITgcm-support
mailing list