1

I'm trying to compile a code (not mine) that consists of mixed Fortran and C source files, which are compiled into a library. This library can either be linked against directly, or (more usefully) driven from a python class. I have previously successfully built the code as 32-bit with g77 and gcc, but I've encountered a situation in which the code uses big chunks of memory, and needs to be 64-bit.

I've attempted to build as both 64-bit only, or as a universal binary, with gfortran 4.2.3 (binary dist from the AT&T R project) and the system gcc (4.2). The source files build correctly, but when I attempt to link against the library, I get many "Undefined Symbols" errors for a number of the Fortran functions. An nm on the library shows that the symbols appear to exist, but obviously the linker isn't finding them.

Here are two (of many) of the compile commands (which produce no errors):

/usr/local/bin/gfortran -arch ppc -arch i386 -arch x86_64  -fPIC -fno-strength-reduce -fno-common -ff2c -Wall -c  lsame.f

gcc -c -I/Users/keriksen/Research/atomic_data/fac -I/Users/keriksen/Research/atomic_data/fac/faclib -O2 -fPIC -fno-strength-reduce -fno-common pmalloc.c

And the link step, which bombs:

gcc -o sfac sfac.c stoken.c -I/Users/keriksen/Research/atomic_data/fac -I/Users/keriksen/Research/atomic_data/fac/faclib -O2 -fPIC -fno-strength-reduce -fno-common -L/Users/keriksen/Research/atomic_data/fac -lfac -lm -lgfortran -lgcc

A sample Undefined Symbol:

  "_acofz1", referenced from:
      _HydrogenicDipole in libfac.a(coulomb.o)
      _HydrogenicDipole in libfac.a(coulomb.o)

and the corresponding nm that shows that symbol exists:

    niobe:atomic_data/fac[14] nm libfac.a | grep acof

0000000000000000 T _acofz1_
0000000000002548 S _acofz1_.eh
                 U _acofz1

Am I doing something stupid, like not including a necessary switch to the linker, or is something more subtle going on here?

Yuji
  • 34,103
  • 3
  • 70
  • 88
  • 1
    `U _acofz1` means `_acofz1` is undefined. What's defined is `T _acofz1_`, with another trailing `_`. Quite independently, please update to 10.6.8. And I'm sorry I can't help you... is there a source code which reproduces the problem, which we can compile here to see more problems? – Yuji Aug 23 '11 at 03:59
  • Actually, you helped quite a bit, Yuji. The absent trailing "_" (I can't believe I missed that -- had been looking at this code for too long) was the key. The original author used a header file called cfortran.h to handle the C/Fortran interface. It didn't support gfortran, and the hack I used to get the code to compile was incorrect. For the record, when using cfortran.h with gfortran, make sure the -Df2cFortran flag is set at compile time. (I set it in the environment variable CPPFLAGS). The cfortran.h CPP macros will add the necessary trailing underscore. – Kris Eriksen Aug 23 '11 at 14:03
  • Why don't you write it as an aswer yourself, Kris? That might help somebody else who finds this entry by Google/Bing. – Yuji Aug 23 '11 at 15:14

1 Answers1

1

Per Yuji's suggestion:

The cfortran.h header file (available on the Web, and apparently fairly widely used) that handles the C/Fortran compatibility issues does not handle gfortran out of the box. I hacked it (incorrectly) to ignore this fact, and paid for my insolence.

The specific issue is that gfortran emits object code containing symbols with a trailing underscore, gcc does not.

The correct thing to do was to set the environment variable CPPFLAGS to -Df2cFortran. Once this macro is set, cfortran.h adds the necessary underscore to the symbols in the calling C functions' object code, and the linker is happy.

The other surprising thing in this particular instance was the configure script looks at the F77 environment variable for the name of the fortran compiler. Once I set F77 to "/usr/local/bin/gfortran -arch x86_64" the generated Makefile was correct, and it produced 64-bit only object code. I'm not sure if this is standard configure behavior, or if it a peculiarity of this particular script.

The upshot is that I now have a 64-bit shared library which plays nicely with a 64-bit python I downloaded. I'm half-considering going back and trying to produce a universal library that will work with the system python, but I'm not sure I want to tempt fate.