我有自己编译的模块,然后链接到可执行文件中以形成程序。我正在从 cgns 库调用符号,但其中一些会抛出未定义的引用错误,即使该符号存在于库中也是如此。
这段代码似乎可以在较旧的 gcc ~4 到 8 版本中编译良好,但不能在我当前的版本 13 中编译。我还使用 mpich 的 mpif90 编译器。
所以我用虚拟代码重新创建了问题。这是我的设置,其中包含一个虚拟代码,可以准确地重现问题:
dnf install gcc gfortran
dnf install mpich-devel
dnf install cgns-mpich-devel
dnf install hdf5-mpich-devel
(不确定此处是否相关)有问题的参考是
cg_nbases_f
,所以这样做
me@pc:dir$ objdump -T $MPI_LIB/libcgns.so | grep cg_nbases_t
00000000000a44b0 g DF .text 0000000000000055 Base cg_nbases_f
虚拟代码由两个文件组成,一个模块
cgnsreading.f90
和一个程序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
按以下方式编译并链接会产生错误:
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
我的想法是,要么存在一些与具有私有子例程的模块相关的问题,但这被排除了,因为错误是通过调用公共子例程发生的。
我还怀疑这是由于编译器忽略了链接标志(标志顺序),但是当发生这种情况时,
cg_get_error_f
会抛出相同的错误。因此,为什么我也测试了它。
我预计这些引用仅在 cgns 库的开发版本中可用,但情况似乎并非如此,因为我正在使用开发版本。
有人怀疑在其他地方安装了不同的库,确实存在,但它也包含丢失的引用。
我不知道这是否是cgns或其安装的特定问题,但我还没有用其他东西测试过。
为什么一个库会提供一个符号而不提供另一个,即使两者都存在于同一个库中。
在另一台具有与上述相同设置的电脑上也会出现同样的错误。所以这个问题是可以复制的。
检查库中定义的符号名称:
nm -D /usr/lib/x86_64-linux-gnu/libcgns.so | grep nbases
0000000000047070 T cg_nbases
0000000000084900 T cg_nbases_f
我们正在寻找的符号就在那里,但
mpif90
编译器已在名称后附加了一个下划线。原则上这是为了防止 Fortran 和 C 名称之间的冲突。
更新
cgnsreading.f90
并添加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
编译时,您需要指定
cgns.mod
的包含路径,该路径应位于 /usr/include/cgns.mod
。
mpif90 cgnsreading.f90 -c -I/usr/include/
mpif90 cgnsread.f90 -c
mpif90 cgnsreading.o cgnsread.o -lcgns -o cgnsread