加载库并包含所需符号时出现 Fortran 未定义引用

问题描述 投票:0回答:1

我有自己编译的模块,然后链接到可执行文件中以形成程序。我正在从 cgns 库调用符号,但其中一些会抛出未定义的引用错误,即使该符号存在于库中也是如此。

这段代码似乎可以在较旧的 gcc ~4 到 8 版本中编译良好,但不能在我当前的版本 13 中编译。我还使用 mpich 的 mpif90 编译器。

所以我用虚拟代码重新创建了问题。这是我的设置,其中包含一个虚拟代码,可以准确地重现问题:

  • 软呢帽 39
  • 海湾合作委员会 13 通过
    dnf install gcc gfortran
  • MPICH 4.1 通过
    dnf install mpich-devel
  • CGNS 4.4 来自
    dnf install cgns-mpich-devel
  • HDF5 1.12.1 通过
    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或其安装的特定问题,但我还没有用其他东西测试过。

为什么一个库会提供一个符号而不提供另一个,即使两者都存在于同一个库中。

在另一台具有与上述相同设置的电脑上也会出现同样的错误。所以这个问题是可以复制的。

fortran linker-errors mpich cgns
1个回答
0
投票

检查库中定义的符号名称:

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

© www.soinside.com 2019 - 2024. All rights reserved.