views:

106

answers:

4

Hello,

I'm trying to compile some fortran code and I'm running into some confusing linking errors. I have some code that I compile and place into a static library:

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

I then try to compile against that library with some simple test code and get the following:

>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

It's not in the object naming because everything looks fine:

>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_

I can check the original object file too:

>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_

The test code simply contains a single call to a function defined in bdout.o:

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

I can't figure out what the problem is. Does anyone have any suggestions? Maybe even just a way to track the problem down?

Cheers.

A: 

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.

janneb
Yeah, I just tried putting linker command last but the problem persists.The -L. means -L in the . (current) directory.
Brandon
I meant, in your question you have an empty -L, without the "."
janneb
Ah sorry, didn't notice that. It was lost in the typing of the question. Obviously that wasn't the problem either.
Brandon
I added another suggestion to my answer, maybe that helps?
janneb
A: 

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.

High Performance Mark
A: 

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
Donal Fellows
A: 

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...

Brandon