multiple definition of `ftn_allocated'

Hi,
I am getting a problem with pgf90 linking code (PGI 11.1, intel xeon a E5620 @ 2.40GHz, CentOS release 5.5). It seems that pgf90 is getting confused whether it should take allo.o from libpgftnrtl.a or from
libpgf90.a. Can you suggest some solution? How do I make pgf90 to look only into libpgftnrtl.a or libpgf90.a? I
Below is a quote from my compilation.


Compilation command:

pgf90 -Bstatic_pgi -i8 -r8 ‘-mcmodel=medium’ -mp=nonuma -tp p7-64 -Mreentrant -Mrecursive -Mnosave -Minfo -Mneginfo -time -fast -O2 -Munroll -Mvect=assoc,recog,cachesize:12582912 -o l101.exe ml101.o l101.a util.a bsd/libf77blas-em64t.a bsd/libatlas-em64t.a -lpthread -lm -lc

The result if compilation:

/opt/pgi/linux86-64/11.1/libso/libpgftnrtl.a(allo.o): In function ftn_allocated': allo.c:(.text+0x0): multiple definition of ftn_allocated’
/opt/pgi/linux86-64/11.1/libso/libpgf90.a(allo.o):allo.c:(.text+0x1060): first defined here
/usr/bin/ld: Warning: size of symbol ftn_allocated' changed from 36 in /opt/pgi/linux86-64/11.1/libso/libpgf90.a(allo.o) to 87 in /opt/pgi/linux86-64/11.1/libso/libpgftnrtl.a(allo.o) /opt/pgi/linux86-64/11.1/libso/libpgftnrtl.a(allo.o): In function ftn_allocate’:
allo.c:(.text+0x60): multiple definition of ftn_allocate' /opt/pgi/linux86-64/11.1/libso/libpgf90.a(allo.o):allo.c:(.text+0x10d0): first defined here /usr/bin/ld: Warning: size of symbol ftn_allocate’ changed from 61 in /opt/pgi/linux86-64/11.1/libso/libpgf90.a(allo.o) to 208 in /opt/pgi/linux86-64/11.1/libso/libpgftnrtl.a(allo.o)
/opt/pgi/linux86-64/11.1/libso/libpgftnrtl.a(allo.o): In function ftn_alloc': allo.c:(.text+0x210): multiple definition of ftn_alloc’
/opt/pgi/linux86-64/11.1/libso/libpgf90.a(allo.o):allo.c:(.text+0x1110): first defined here
/usr/bin/ld: Warning: size of symbol ftn_alloc' changed from 57 in /opt/pgi/linux86-64/11.1/libso/libpgf90.a(allo.o) to 144 in /opt/pgi/linux86-64/11.1/libso/libpgftnrtl.a(allo.o) /opt/pgi/linux86-64/11.1/libso/libpgftnrtl.a(allo.o): In function ftn_dealloc’:
allo.c:(.text+0x2a0): multiple definition of ftn_dealloc' /opt/pgi/linux86-64/11.1/libso/libpgf90.a(allo.o):allo.c:(.text+0x1f00): first defined here /usr/bin/ld: Warning: size of symbol ftn_dealloc’ changed from 21 in /opt/pgi/linux86-64/11.1/libso/libpgf90.a(allo.o) to 204 in /opt/pgi/linux86-64/11.1/libso/libpgftnrtl.a(allo.o)
/opt/pgi/linux86-64/11.1/libso/libpgftnrtl.a(allo.o): In function ftn_deallocate': allo.c:(.text+0x370): multiple definition of ftn_deallocate’
/opt/pgi/linux86-64/11.1/libso/libpgf90.a(allo.o):allo.c:(.text+0x1ee0): first defined here
/usr/bin/ld: Warning: size of symbol `ftn_deallocate’ changed from 21 in /opt/pgi/linux86-64/11.1/libso/libpgf90.a(allo.o) to 14 in /opt/pgi/linux86-64/11.1/libso/libpgftnrtl.a(allo.o)

I am getting this error also when I move the code to different machine (also xeon, RH 5.5). What should I do?
Please help,

Jacek

Presumably, the occurrence of multiple definitions of symbols is attributable to using objects (or components of object libraries) compiled from F77 and those compiled from F9x sources.

The linker flag “-z muldefs” is available in Linux/Unix to tell the linker to use the first occurrence of a symbol. The Microsoft linker has a similar option, /FORCE:multiple.

See the compiler options for your platform to see how to get the compiler to pass an option to the linker rather than appropriating the option to itself.

Thanks a lot for your suggestion.

  1. Indeed, util.a was compiled with pgf77… I thought that compatibility between pgf90 and pgf77 allows to link main code compiled with pgf90 with those compiled with pgf77. I am right?

    \
  2. I checked your suggestion. Unfortunately, the switch “-z muldefs” is not known to pgf90 (I use: pgf90 11.1-0 64-bit target on x86-64 Linux -tp nehalem):

pgf90 -help -z
Reading rcfile /opt/pgi/linux86-64/11.1/bin/.pgf90rc
pgf90-Error-Unknown switch: -z
pgf90-Error-Unknown switch: -z

What is the right switch for the linker? I checked the full list from “pgf90 -help”, but I do not see anything similar to “-z muldefs”. What are your suggestions?

To tell the PGI compiler to pass options to the linker, the common Unix convention is used: prefix linker options with -Wl, using commas to delimit multiple linker options. For example, with at least one subroutine repeated in main.f90, sub1.f and sub2.f:

$ pgf77 -c sub1.f sub2.f
$ pgf95 main.f90 sub1.o sub2.o -Wl,-z,muldefs

Hi Jacek,

N. Shamsundar’s solution should get you around the linker error. Though I generally don’t recommend user doing this since if the reference the linker picks is the wrong one, then it can cause runtime errors. In this case, it’s probably ok since they’re the same routine in both libraries. What I’d like to discover is why you’re getting is in the first place.

I have seen this type of problem when users include the PGI runtime as part of their library, or when using ld’s “whole-archive” flag when creating shared libraries. I don’t think that this is the problem, but can you please double check if you’re including PGI runtime in your libraries?

Thanks,
Mat

Dear N. Shamsundar and Matt,

Thank you fro your responses.

  1. the linker option “-Wl,-z,muldefs” worked. The code compiled. I run some simple tests and the binaries work. I have some question about this linker option --Matt has already asked for me. As I understand “-z muldefs” causes linker to pick the first occurence function when multiple versions exist/are provided.

1.A) Is there a way (argument or flag passed to linker) in which I can explicitly turn off to one version of the library?

1.B) Where I can find the documentation about available options/arguments for linker?I cannot find in the PGI documentation “-z muldefs” flag. I assume that there might be other interesting flags.


2. I compared util.a with libpgf90.a and libpgftnrtl.a to see if the contents are similar. Util.a was compiled with pgf77 while the rest with pgf90. As I understand compiler recognized it and provided libpgftnrtl.a for util.a and libpgf90 for the rest. I hope I will see problems popiong out later when I will run the code for production.

With best regards,
Jacek

Hi Jacek,

1.A) Is there a way (argument or flag passed to linker) in which I can explicitly turn off to one version of the library?

There isn’t a flag. You can add the “-v” (verbose) flag to have the compiler show the various phases of the link. Next, copy the “ld” command, removing the extra library. Though, you’ll most likely get an undefined reference error.

1.B) Where I can find the documentation about available options/arguments for linker?I cannot find in the PGI documentation “-z muldefs” flag. I assume that there might be other interesting flags

The linker is part of your system’s binutils package. To see the available option see “man ld”. The “-Wl,” tells the compiler to pass the flag to the linker.

  1. I compared util.a with libpgf90.a and libpgftnrtl.a to see if the contents are similar. Util.a was compiled with pgf77 while the rest with pgf90.

Linking pgf77 compiled libraries with pgf90 compiler objects should work fine and it’s unclear why you are getting this error.

  • Mat

    \
  • Mat