未定义的引用

时间:2010-04-01 20:22:58

标签: linker fortran static-linking

我正在尝试编译一些fortran代码,而且我遇到了一些令人困惑的链接错误。我有一些代码可以编译并放入静态库中:

>gfortran -c -I../../inc -o bdout.o bdout.F
>ar rv libgeo.a bdout.o

然后我尝试使用一些简单的测试代码针对该库进行编译,并获得以下内容:

>gfortran -o mytest -L -lgeo mytest.F
/tmp/cc4uvcsj.o: In function `MAIN__':
mytest.F:(.text+0xb0): undefined reference to `ncwrite1_'
collect2: ld returned 1 exit status

它不在对象命名中,因为一切看起来都很好:

>nm -u libgeo.a

bdout.o:
     U _gfortran_exit_i4
     U _gfortran_st_write
     U _gfortran_st_write_done
     U _gfortran_transfer_character
     U _gfortran_transfer_integer
     U ncobjcl_
     U ncobjwrp_
     U ncopencr_
     U ncopenshcr_
     U ncopenwr_
     U ncwrite1_
     U ncwrite2_
     U ncwrite3_
     U ncwrite4_
     U ncwritev_

我也可以查看原始目标文件:

>nm -u bdout.o

     U _gfortran_exit_i4
     U _gfortran_st_write
     U _gfortran_st_write_done
     U _gfortran_transfer_character
     U _gfortran_transfer_integer
     U ncobjcl_
     U ncobjwrp_
     U ncopencr_
     U ncopenshcr_
     U ncopenwr_
     U ncwrite1_
     U ncwrite2_
     U ncwrite3_
     U ncwrite4_
     U ncwritev_

测试代码只包含对bdout.o中定义的函数的单个调用:

program hello
        print *,"Hello World!"
        call ncwrite1( istat, f, ix2, ix3, ix4, ix5, ih )
end program hello

我无法弄清问题是什么。有没有人有什么建议?也许只是一种追踪问题的方法?

干杯。

4 个答案:

答案 0 :(得分:1)

不知道这是否有助于解决这一特定问题,但一般情况下,始终将链接器命令放在目标文件之后。其次,如果libgeo.a在当前目录中,则需要显式添加,空-L AFAIK不执行任何操作。即。

gfortran -o mytest mytest.F -L. -lgeo

编辑:另请注意,nm输出中的“U”表示符号未定义。即.o文件引用了所述符号,但该符号实际上是在其他文件中。即您可能需要在定义ncwrite1_符号的库中显式链接。

答案 1 :(得分:1)

问题是您没有链接到包含该功能的。这有两个可能的原因:

  1. 您要链接的库中未定义ncwrite1函数。使用nm验证是否(或不是)情况。
  2. 库被放置在命令行上的对象/源代码文件之前(!)连接器是有史以来最愚蠢的东西,并且不会尝试解决所有其他问题(这对于高级技术偶尔有用)但这意味着您需要将库放在其他所有内容之后。如果您有许多库,则需要对它们之间的依赖关系使用拓扑排序,以确定将它们列出到链接器的正确顺序。
  3. 如果我们假设geo库具有您正在使用的功能(检查!),那么您应该像这样构建和链接:

    gfortran -o mytest -L. mytest.F -lgeo
    

答案 2 :(得分:0)

问题可能是对ncwrite1的调用与子例程的库定义的签名不匹配,而错误消息实际上告诉你的是它无法找到带有签名的ncwrite1版本匹配电话。您的程序似乎没有使用ncwrite1的显式接口,因此在编译时不会捕获这样的类型错误。

答案 3 :(得分:0)

首先,感谢所有回答的人。我发帖是为了正式结束这个帖子。事实证明,编写库(libgeo.a)的人在使用编译器标志宏-D(宏)打开的代码中放置了几个#ifdef语句。然后,这些#ifdef将用于扩展具有特定参数的函数名称。如果没有向编译器提供适当的宏,则函数名称保持未展开状态,因此符号未定义。 GRRRR ...