在 OS X 10.6.4 中链接混合 C 和 Fortran 时出现未定义符号
我正在尝试编译一个由混合的 Fortran 和 C 源文件组成的代码(不是我的),这些文件被编译到一个库中。该库可以直接链接,也可以(更有用)从 python 类驱动。我之前曾使用 g77 和 gcc 成功地将代码构建为 32 位,但我遇到过代码使用大块内存并且需要为 64 位的情况。
我尝试使用 gfortran 4.2.3(来自 AT&TR 项目的二进制版本)和系统 gcc (4.2) 构建为仅 64 位,或构建为通用二进制文件。源文件构建正确,但是当我尝试链接该库时,我收到许多 Fortran 函数的“未定义符号”错误。库上的 nm 表明这些符号似乎存在,但显然链接器没有找到它们。
这里有两个(许多)编译命令(不会产生错误):
/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
以及链接步骤,它会爆炸:
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
一个示例未定义符号:
"_acofz1", referenced from:
_HydrogenicDipole in libfac.a(coulomb.o)
_HydrogenicDipole in libfac.a(coulomb.o)
以及显示该符号存在的相应 nm:
niobe:atomic_data/fac[14] nm libfac.a | grep acof
0000000000000000 T _acofz1_
0000000000002548 S _acofz1_.eh
U _acofz1
我在做一些愚蠢的事情吗,比如不包括必须切换到链接器,还是这里发生了更微妙的事情?
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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
根据 Yuji 的建议:
处理 C/Fortran 兼容性问题的 cfortran.h 头文件(可在 Web 上找到,并且显然使用相当广泛)并不处理开箱即用的 gfortran。我(错误地)破解了它以忽略这一事实,并为我的无礼付出了代价。
具体问题是 gfortran 发出的目标代码包含尾随下划线的符号,而 gcc 则不会。
正确的做法是将环境变量 CPPFLAGS 设置为 -Df2cFortran。一旦设置了该宏,cfortran.h 就会向调用 C 函数的目标代码中的符号添加必要的下划线,链接器就会满意。
在这个特定实例中,另一个令人惊讶的事情是配置脚本在 F77 环境变量中查找 Fortran 编译器的名称。一旦我将 F77 设置为“/usr/local/bin/gfortran -arch x86_64”,生成的 Makefile 就是正确的,并且它仅生成 64 位目标代码。我不确定这是否是标准配置行为,或者是否是该特定脚本的特性。
结果是我现在有了一个 64 位共享库,它可以与我下载的 64 位 python 很好地配合。我正在考虑回去尝试创建一个可以与 python 系统一起工作的通用库,但我不确定我是否想尝试命运。
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.