2

我正在尝试编译一些 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

4 回答 4

1

Don't know if this helps this particular issue, but generally, always put the linker commands AFTER the object files. Secondly, if libgeo.a is in the current directory, you need to add that explicitly, an empty -L AFAIK does nothing. I.e.

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

EDIT: Also note that the "U" in the nm output means that the symbol is undefined. I.e. that the .o file references said symbol, but the symbol is actually in some other file. I.e. you might need to explicitly link in the library that defines the ncwrite1_ symbol.

于 2010-04-01T20:39:28.547 回答
1

The problem is that you're not linking against the library that contains that function. There are two possible reasons for this:

  1. The ncwrite1 function isn't defined in the libraries that you are linking against. Use nm to verify that this is (or is not) the case.
  2. The libraries are placed before the object/source code files on the command line(!) Linkers are quite the most stupid things ever, and do not attempt to resolve everything against everything else (and this is occasionally useful for advanced techniques) but that means you need to put the libraries after everything else. If you have many libraries, you need to use a topological sort on the dependencies between them to determine the correct order to list them to the linker.

If we assume that the geo library has the function you're after (check that!) then you should build and link like this:

gfortran -o mytest -L. mytest.F -lgeo
于 2010-04-02T07:54:58.003 回答
0

The problem may be that the call to ncwrite1 does not match the signature of the library definition of the subroutine and what the error message is really trying to tell you is that it can't find a version of ncwrite1 with a signature to match the call. Your program doesn't seem to use an explicit interface to ncwrite1 so type errors like this won't be caught at compile-time.

于 2010-04-02T06:51:19.150 回答
0

First, thanks to everyone who answered. I'm posting to put an official end to this thread. It turns out that the person who wrote the library (libgeo.a) had placed several #ifdef statements in the code that were turned on using compiler flag macros -D(macro). These #ifdef's would then be used to expand the function names with specific parameters. Without supplying the appropriate macros to the compiler the function names were left unexpanded, and The symbols were thus undefined. Grrrr...

于 2010-04-07T14:56:52.660 回答