Ok, newb question here.
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.
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
and I get the following output
/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
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
What am I doing wrong?
(FWIW, a few relevant references I've looked at are below.
undefined reference using netcdf library
Compiling problems with gfortran and NETCDF
Compiling and Running Fortran Programs - a basic guide
)
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.
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
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
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
.
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.
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!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With