Reputation: 43
I have modules compiled on their own and then linked in an executible to form a program. I am calling symbols from the cgns library, but some of them throw an undefined reference error, even though the symbol exists in the library.
This code seems to compile fine in older gcc ~4 to 8 versions, but not my current version 13. I am also using the mpif90 compiler from mpich.
So I recreated the problem with a dummy code. Here is my setup with a dummy code that recreates the issue exactly:
dnf install gcc gfortran
dnf install mpich-devel
dnf install cgnslib-mpich-devel
dnf install hdf5-mpich-devel
(not sure if relevant here)The reference in question is cg_nbases_f
, so doing
me@pc:dir$ objdump -T $MPI_LIB/libcgns.so | grep cg_nbases_t
00000000000a44b0 g DF .text 0000000000000055 Base cg_nbases_f
The dummy code consists of two files, a module cgnsreading.f90
and a program cgnsread.f90
cgnsreading.f90
:
module cgnsreading
implicit none
private
public talk_to_cgns
contains
subroutine error_check()
print *, 'hi I am the bane of arthropods'
end subroutine error_check
subroutine talk_To_cgns()
character(100) :: errmsg
integer :: i = 1
integer :: nbases = 1
integer :: ierr
call cg_get_error_f(errmsg)
print *, errmsg ! Should print that there is no error
call error_check() ! Should print its guts
call cg_nbases_f(i,nbases,ierr) ! Throws undefined reference error
end subroutine talk_To_cgns
end module cgnsreading
cgnsread.f90
:
program cgnsread
use cgnsreading
implicit none
call talk_to_cgns()
end program cgnsread
Compiling it and linking in the following way produces the error:
me@pc:dir$ mpif90 cgnsreading.f90 -c
me@pc:dir$ mpif90 cgnsread.f90 -c
me@pc:dir$ mpif90 cgnsreading.o cgnsread.o -lcgns -o cgnsread
/usr/bin/ld: cgnsreading.o: in function `__cgnsreading_MOD_talk_to_cgns':
cgnsreading.f90:(.text+0x95): undefined reference to `cg_nbases_f_'
collect2: error: ld returned 1 exit status
My thought was that there were either some issues related to the module having private subroutines, but that is ruled out because the error occures by calling the public subroutine.
I was also suspecting that it's due to the compiler ignoring the linking flag (flags order), but when that happens, cg_get_error_f
throws the same error. Hence, why I tested that as well.
I expected that the references would only be available in the devel versions of the cgns library, but that doesn't seem to be the case because I am using the devel version.
There was a suspicion that a different library was installed somewhere else, and indeed there is, but it also contains the missing reference.
I do not know if this is a specific problem to cgns or its installation, but I haven't tested this with something else.
Why would a library provide a symbol but not the other, even though both exist in the same library.
The same error occures on another pc with the same setup as mentioned above. So the problem can be replicated.
Upvotes: 1
Views: 134
Reputation: 6554
Check the symbol names defined in the library:
nm -D /usr/lib/x86_64-linux-gnu/libcgns.so | grep nbases
0000000000047070 T cg_nbases
0000000000084900 T cg_nbases_f
The symbol that we are looking for is there, but the mpif90
compiler has appended an underscore to the name. In principle this is to prevent clashes between Fortran and C names.
Update cgnsreading.f90
and add use cgns
:
module cgnsreading
use cgns
implicit none
private
public talk_to_cgns
contains
subroutine error_check()
print *, 'hi I am the bane of arthropods'
end subroutine error_check
subroutine talk_to_cgns()
character(100) :: errmsg
integer :: i = 1
integer :: nbases = 1
integer :: ierr
call cg_get_error_f(errmsg)
print *, errmsg ! Should print that there is no error
call error_check() ! Should print its guts
call cg_nbases_f(i,nbases,ierr) ! Throws undefined reference error
end subroutine talk_to_cgns
end module cgnsreading
When you compile that you'll need to specify the include path for cgns.mod
, which should be located at /usr/include/cgns.mod
.
mpif90 cgnsreading.f90 -c -I/usr/include/
mpif90 cgnsread.f90 -c
mpif90 cgnsreading.o cgnsread.o -lcgns -o cgnsread
I don't have a Fedora 39 system but I can replicate with Docker. Follow these steps to get it set up.
FROM fedora:39
RUN dnf install -y wget gcc-gfortran hdf5-devel cgnslib openmpi openmpi-devel
RUN wget https://dl.fedoraproject.org/pub/fedora/linux/releases/39/Everything/x86_64/os/Packages/c/cgnslib-devel-4.4.0-2.fc39.x86_64.rpm && \
rpm -i cgnslib-devel-4.4.0-2.fc39.x86_64.rpm && \
rm -f cgnslib-devel-4.4.0-2.fc39.x86_64.rpm
ENV PATH=$PATH:/usr/lib64/openmpi/bin/
COPY *.f90 .
RUN mpif90 cgnsreading.f90 -c -I/usr/lib64/gfortran/modules/
RUN mpif90 cgnsread.f90 -c
RUN mpif90 cgnsreading.o cgnsread.o -lcgns -o cgnsread
Upvotes: 2