在 Ubuntu 上编译 Fortran netCDF 程序 [英] Compiling Fortran netCDF programs on Ubuntu

查看:35
本文介绍了在 Ubuntu 上编译 Fortran netCDF 程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

好的,这里是新手问题.

Ok, newb question here.

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

I'm trying to compile simple_xy_wr.f90 -- a netCDF example program -- using gfortran on Ubuntu, and I must be doing something pretty silly; I don't have much experince compiling Fortran.

首先,我安装了 libnetcdf-dev 包,其中包括文件喜欢

First, I've got the libnetcdf-dev package installed, which includes files like

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

所以,我尝试使用(各种命令等)编译代码

So, I've tried to compile the code with (various command like)

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 应该在那里:

I think that I'm including the right libraries. E.g. it seems that __netcdf_MOD_nf90_strerror should be there:

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

我做错了什么?

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

(FWIW, a few relevant references I've looked at are below.

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

gfortran 和 NETCDF 的编译问题

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

)

推荐答案

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

Ordering of object files and archives on the linker command line is very important on Unix systems since the default linker behaviour is to search for symbol definitions only in archives that follow the object file or archive, where an unresolved reference was found, referred to single pass linking.

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

This means that if your code references __netcdf_MOD_nf90_strerror, then the archive that contains the definition of this symbol (libnetcdff.a) must appear after the list of object files from your program. libnetcdff.a itself references symbols from the C library libnetcdf.a, hence it must be linked after libnetcdff.a. So the correct link order is:

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

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

where /tmp/ccE6g7sr.o is the temporary object file that the assembler produces from the compiled source file. The correct command line to compile your code is then:

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

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

In this case the linker is not called directly, rather the compiler does it. GCC compilers pass all link-related things in the same order to an intermediate utility called collect2 which then calls the actual linker ld.

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

Note that if shared object versions of the netCDF library archives are also present (i.e. there are libnetcdff.so and libnetcdf.so), then the linker would prefer them to the static archives (unless static linking is enabled with the -static option) and the final link phase would be handled to the run-time link editor (RTLD) (/lib64/ld-linux-x86-64.so.2 on Ubuntu). In this case the same command line as in your question would actually succeed without link errors, despite the fact that both libraries are positioned before the code that references them, as the missing symbol references would be resolved by the RTLD while it is loading the executable file.

这篇关于在 Ubuntu 上编译 Fortran netCDF 程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆