Question

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.

Was it helpful?

Solution 4

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

OTHER TIPS

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.

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

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top