[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