1

Background: I am in a situation where I have to make use of an old Fortran95 library in a new C++ project. The F95 library is extensive, has tons of small modules, poorly documented, and it was mostly auto-generated about a decade ago by some obscure computer algebra system (by people on a different continent). So basically heirloom code, but it works and it is currently irreplaceable.

Luckily I have the source code and it can be compiled with current versions of ifort, but I am not too familiar with Fortran, and would rather not touch the old code in any significant way.

So suppose I have this Fortran code (pes_shell.f90):

subroutine pes_init()
  use pes,wp=>pes_wp
  implicit none
  real,parameter::auang=0.5291772083
  call pes0_init (dir='coef')
  call pes1_init (pes_x3y1z1u1_sysall)
return
end subroutine pes_init

The functions pes0_init(...) and pes1_init(...) lead into the abyssal depths of the Fortran library and they are contained in the pes module.

I can compile this to an object file, if I give ifort the path for the modules:

ifort -r8 -O2 -c pes_shell.f90 -I/home/debianuser/PES/PES_library/lib/mod

My POC C++ code, calling pes_init():

extern "C"{
void pes_init_();
}

int main(){
    pes_init_();
    return 0;
}

This can also be compiled to an object file, with icpc:

icpc -c PEStest.cpp

However I cannot figure out how to link the two object files, plus the truckload of fortran modules, into a final executable. I have tried just simply using icpc, but it cannot seem to be able to find the Fortran functions, even if I give it the location of the module files:

    icpc -I/home/debianuser/PES/PES_library/lib/mod -o test.x pes_shell.o PEStest.o
    pes_shell.o: In function `pes_shell_mp_f_':
    pes_shell.f90:(.text+0x595): undefined reference to `pes_x3y1z1u1_mp_pes_x3y1z1u1_pot_'
    pes_shell.o: In function `pes_shell_mp_pes_init_':
    pes_shell.f90:(.text+0x5f0): undefined reference to `pes0_mp_pes0_init_'
    pes_shell.f90:(.text+0x603): undefined reference to `pes1c_mp_pes1_init_'
    PEStest.o: In function `main':
    PEStest.cpp:(.text+0x2b): undefined reference to `pes_init_'

EDIT: Pointing the linker to the directory where libpes.a can be found eliminates the problem of locating the function that was referenced in the c++ code, but icpc still cannot find the fortran functions that are being called from fortran codes:

  icpc -I/home/debianuser/PES/PES_library/lib/mod -L/home/debianuser/PES/PES_library/lib/pes-xyz -lpes -o test.x PEStest.o pes_shell_new.o
    pes_shell_new.o: In function `f_':
    pes_shell_new.f90:(.text+0x585): undefined reference to `pes_x3y1z1u1_mp_pes_x3y1z1u1_pot_'
    pes_shell_new.o: In function `pes_init_':
    pes_shell_new.f90:(.text+0x5e0): undefined reference to `pes0_mp_pes0_init_'
    pes_shell_new.f90:(.text+0x5f3): undefined reference to `pes1c_mp_pes1_init_'
uLoop
  • 225
  • 1
  • 8
  • 2
    You probably need to tell icpc where to find the *other* Fortran object files. With luck, they are all compiled in a library, and you can just specify that with something like `-L/home/debianuser/PED/PES_library/lib -lpes` (which will look for a file called libpes.a in the specified directory). – Martin Bonner supports Monica Aug 08 '16 at 11:02
  • Is the `pes_init` subroutine itself in a module? – IanH Aug 08 '16 at 11:30
  • @IanH no it is not, but I have tried doing that and made no difference – uLoop Aug 08 '16 at 11:32
  • @MartinBonner there is indeed a libpes.a, but giving the path and -lpes does not solve all problems, it only gets rid of the last undefined reference – uLoop Aug 08 '16 at 11:36
  • Ok - as you have things now you don't want it to be in a module. You may need `pes_shell.o` to follow `PEStest.o` when you are linking. Please update your question with the results when you include the library (or other object files) mentioned by Martin Bonner. – IanH Aug 08 '16 at 11:39
  • 1
    For several years now, ifort and icpc have been required to be installed in the same path. .mod files are used only when building objects, so don't need to be visible to icpc. If you use icpc to drive the link step, you will need to add some ifort library -l references. If you use ifort for the link step, -lstdc++ may be sufficient to take care of the C++. – tim18 Aug 08 '16 at 13:11
  • @tim18 Thanks, this is a helpful insight, I will keep it in mind, even though it does not solve my current problem. – uLoop Aug 08 '16 at 13:29
  • That mention of "old fortran" sounds a bit value laden. You probably want some !DIR$ ATTRIBUTES : "pec_init":: PEC_INIT that still may require the name_mp_name , unless it is all in a module. There is also sometimes drama with the trailing underscore. Lastly have you tried linking with ifort rather than icpc? (And what does the C code do for you?) – Holmz Aug 09 '16 at 10:46
  • Library references (-lxxx) in command lines may need to follow the object files that contain references to symbols in those libraries, due to the [manner in which the linker searches for symbols](http://stackoverflow.com/a/409470/1234550) – IanH Aug 09 '16 at 21:05

0 Answers0