linking C function from Fortran in a shared object library

I am using pgf90 on Linux (Redhat 8.0, Pentium III). I have several libraries (.a) that I am trying to link together to create a shared object library (.so). The command line essentially looks like this:

pgf90 -shared -Wl,–whole-archive libLIB1.a libLIB2.a -Wl,–no-whole-archive -lcurses -ltermcap -o

The -Wl option passes options to the linker, the --whole-archive option is required, or nothing from libLIBx.a is put into The first library contains C code generated by gcc. The second library contains F90 code generated by pgf90. The other libraries contain routines that are needed. There is a Fortran subroutine in libLIB2.a that is called from a C function in libLIB1.a. There are no problems there.

There is a C function in libLIB1.a that is called from a Fortran subroutine in libLIB2.a. This is where the problem is, this C function is listed as undefined in (using the objdump -t command). This was discovered when attempting to load Using objdump -t on libLIB1.a, the C function is there with the proper name, which exactly matches the undefined name listed in libLIB2.a. Somehow the linker is not able to connect the two together.

Using pgf90 to create a program using these two libraries works fine, i.e. no undefined references occur, and the program runs fine. It is a problem with generating the shared object library.

I tried using the linker option --export-dynamic, but this did not solve the problem. I tried swapping libLIB1.a and libLIB2.a on the command line, but the result was the same. I also tried surrounding libraries with --start-group and --end-group, but also the same results I have tried using the --trace and --trace-symbol=xxx options, but did not learn anything.

What happens when you put libLIB1.a both before and after libLIB2.a?

pgf90 -shared -Wl,--whole-archive libLIB1.a libLIB2.a libLIB1.a -Wl,--no-whole-archive -lcurses -ltermcap -o

You’ll see this type of error whenever libraries have circular dependencies because ld scans the objects in the order they appear and does not keep information about the objects that it has already found. So this means that definitions must appear after they are referenced since ld can’t “look” backwards.

I should have mentioned that I tried that too. I realized that I have a circular dependency, which is why I tried the --start-group/–end-group as this was suppose to get circular references by rescanning the libraries.

Remember the problem is not in linking the libraries into a program, which works fine. The problem is in creating the shared object library. I looked through the manual for ld looking for an option, but the manual is quite long, so it’s possible that I missed an option. The version of ld I am using is, is that’s any help.

What is the actual undefined reference? Fortran places an underscore after function names in order to keep the C and Fortran namespace separate. So your C functions that are referenced by Fortran must have an underscore appended to their names or you need the C pragma in all the fortran subroutines that use the C functions ( ex “C$PRAGMA C(mycfuncname)” ). Also, fortran function names are converted to lower case while C names keep what ever case was used. So if your C function contains any uppercase letters, the linker wont be able to find it. (unless you compile the Fortran with -Mupcase") See chapter 10 of the PGI user’s guide for more info. Of course, this might not be it since you were able to link these libs into a program (unless the name in question wasn’t referenced then it would link fine).

Also try extracting the objects out of LIB1 and LIB2 using “ar x” and then link them in directly to see if the problem’s with “–whole-archive”

Were the library objects compiled with “-fPIC”?

As a side note, you can see the linker command by using the “-v” flag. This way you can take pgf90 out of the equation and work directly with this command.