7

好的,这里是新手问题。

我正在尝试在 Ubuntu 上使用 gfortran 编译simple_xy_wr.f90——一个 netCDF 示例程序,而我一定是在做一些非常愚蠢的事情;我没有太多编译 Fortran 的经验。

首先,我安装了libnetcdf-dev包,其中包括像

/usr/lib/libnetcdf.a
/usr/lib/libnetcdff.a
/usr/include/netcdf.mod

所以,我试图用(各种命令,如)编译代码

f95 -o xy -I/usr/include/ -L/usr/lib/ -lnetcdff -lnetcdf simple_xy_wr.f90

我得到以下输出

/tmp/ccE6g7sr.o: In function `check.1847':
simple_xy_wr.f90:(.text+0x72): undefined reference to `__netcdf_MOD_nf90_strerror'
/tmp/ccE6g7sr.o: In function `MAIN__':
simple_xy_wr.f90:(.text+0x284): undefined reference to `__netcdf_MOD_nf90_create'
simple_xy_wr.f90:(.text+0x2b6): undefined reference to `__netcdf_MOD_nf90_def_dim'
simple_xy_wr.f90:(.text+0x2e8): undefined reference to `__netcdf_MOD_nf90_def_dim'
simple_xy_wr.f90:(.text+0x432): undefined reference to `__netcdf_MOD_nf90_def_var_manydims'
simple_xy_wr.f90:(.text+0x468): undefined reference to `__netcdf_MOD_nf90_enddef'
simple_xy_wr.f90:(.text+0x4aa): undefined reference to `__netcdf_MOD_nf90_put_var_2d_fourbyteint'
simple_xy_wr.f90:(.text+0x4cb): undefined reference to `__netcdf_MOD_nf90_close'
collect2: error: ld returned 1 exit status

我认为我包含了正确的库。例如,似乎 __netcdf_MOD_nf90_strerror 应该在那里:

$ nm /usr/lib/libnetcdff.a | grep __netcdf_MOD_nf90_strerror
000000000004a100 T __netcdf_MOD_nf90_strerror

我究竟做错了什么?

(FWIW,我看过的一些相关参考资料如下。

  1. 使用 netcdf 库的未定义引用

  2. gfortran 和 NETCDF 的编译问题

  3. 编译和运行 Fortran 程序 - 基本指南

)

4

2 回答 2

10

在 Unix 系统上,链接器命令行上的目标文件和存档的顺序非常重要,因为默认的链接器行为是仅在目标文件或存档之后的存档中搜索符号定义,其中找到未解析的引用,称为单遍链接。

这意味着如果您的代码引用__netcdf_MOD_nf90_strerror,则包含此符号 ( libnetcdff.a) 定义的存档必须出现程序的目标文件列表之后。libnetcdff.a它本身引用了 C 库中的符号libnetcdf.a,因此它必须在libnetcdff.a. 所以正确的链接顺序是:

/tmp/ccE6g7sr.o libnetcdff.a libnetcdf.a

/tmp/ccE6g7sr.o汇编器从编译的源文件生成的临时目标文件在哪里。编译代码的正确命令行是:

f95 -o xy -I/usr/include/ simple_xy_wr.f90 -lnetcdff -lnetcdf

在这种情况下,不会直接调用链接器,而是编译器会这样做。GCC 编译器将所有与链接相关的东西以相同的顺序传递给一个名为的中间实用程序collect2,然后该实用程序调用实际的链接器ld

请注意,如果 netCDF 库存档的共享对象版本也存在(即存在libnetcdff.solibnetcdf.so),那么链接器会更喜欢它们而不是静态存档(除非使用该-static选项启用静态链接)并且最终链接阶段将被处理为运行时链接编辑器 (RTLD)(/lib64/ld-linux-x86-64.so.2在 Ubuntu 上)。在这种情况下,与您的问题相同的命令行实际上会成功而不会出现链接错误,尽管这两个库都位于引用它们的代码之前,因为丢失的符号引用将由 RTLD 在加载可执行文件时解决文件。

于 2012-12-19T13:20:13.693 回答
6

In Ubuntu 12.10, the order of the libraries is the trick (as Hristo suggested):


angelv@palas:~$ gfortran  -o xy -I/usr/include/ -L/usr/lib/  -lnetcdf -lnetcdff simple_xy_wr.f90
/tmp/ccj95anF.o: In function `check.1847':
simple_xy_wr.f90:(.text+0x72): undefined reference to `__netcdf_MOD_nf90_strerror'
/tmp/ccj95anF.o: In function `MAIN__':
simple_xy_wr.f90:(.text+0x284): undefined reference to `__netcdf_MOD_nf90_create'
simple_xy_wr.f90:(.text+0x2b6): undefined reference to `__netcdf_MOD_nf90_def_dim'
simple_xy_wr.f90:(.text+0x2e8): undefined reference to `__netcdf_MOD_nf90_def_dim'
simple_xy_wr.f90:(.text+0x432): undefined reference to `__netcdf_MOD_nf90_def_var_manydims'
simple_xy_wr.f90:(.text+0x468): undefined reference to `__netcdf_MOD_nf90_enddef'
simple_xy_wr.f90:(.text+0x4aa): undefined reference to `__netcdf_MOD_nf90_put_var_2d_fourbyteint'
simple_xy_wr.f90:(.text+0x4cb): undefined reference to `__netcdf_MOD_nf90_close'
collect2: error: ld returned 1 exit status

angelv@palas:~$ gfortran  -o xy -I/usr/include/ simple_xy_wr.f90 -L/usr/lib/  -lnetcdf -lnetcdff 

angelv@palas:~$ ./xy 
           0          12          24          36
 *** SUCCESS writing example file simple_xy.nc! 
于 2012-12-19T10:44:58.387 回答