且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

在 Ubuntu 上编译 Fortran netCDF 程序

更新时间:2023-11-10 12:53:22

在 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.