0

I am working in Linux and I have a library written in Fortran 90 (written by 3rd party), that is reading from a file in the current working directory. I would like to be able to call the resulting library from other folders, hence I need to read the path where the library is installed. How can I know the path to the compiled library within the Fortran code?

I need to store in a variable the path within the code.

For who knows python, I want to achieve the same as

import os
os.path.dirname(os.path.abspath(__file__))

but in f90 (see Get location of the .py source file)

Using the suggestions in the comment I have done the following:

export DATAPATH=`pwd`
make

in the Makefile

ifort -O3 -fpic -fpp -DDATAPATH -c mysource.f90

in mysource.f90

subroutine mysub
  character(len=100)::dpath
#ifdef DATAPATH
  dpath=DATAPATH
#endif
  open(10,file=trim(dpath)//'initialise.dat')
  ....
  ....

the problem is that at compile time I get

mysource.f90(42): error #6054: A CHARACTER data type is required in this context.   [1]
    dpath=1
----------^
compilation aborted for mysource.f90 (code 1)
Community
  • 1
  • 1
simona
  • 2,009
  • 6
  • 29
  • 41
  • 1
    I don't understand at all. Are you asking where is the source code for your library on your hard drive? – Vladimir F Героям слава Oct 24 '16 at 13:48
  • yes, I added a line to the question, in the hope to be more clear – simona Oct 24 '16 at 13:53
  • the initialisation-file is in the same path of the source code (that is the same path as the compiled library). the library needs to know the path to the source code so it can find the initialisation-file – simona Oct 24 '16 at 14:17
  • the message is the following: the data are to be considered part of the source code, and they are not meant to be changed by the user. The user has to be able to run the library anywhere, without caring about where the data-file are stored. I know it is possible to do this on windows, because fortran can know where the library is at run time. I need to do this in linux. thank you – simona Oct 24 '16 at 14:30
  • 1
    In that case you can store the configuration with the path in a standard location like `/etc/yourpackage` `/usr/local/etc`, in your home directory or in an environment variable. Consider how modules work and how they set-up the environment variables. For example the variable `NETCDF_PATH` in the NetCDF library and similar. They certainly do not have a hard-coded path in their code. Windows uses registers. – Vladimir F Героям слава Oct 24 '16 at 14:47
  • @HighPerformanceMark I have a file.txt to read in the same folder as the source code. the folder of the source code can be moved to another location and recompiled, so i cannot hard code the path to the source code. – simona Oct 24 '16 at 15:05
  • @VladimirF ok so I could pass an environment variable at compile time. I was thinking about using something similar to `dladdr` but your method looks easier – simona Oct 24 '16 at 15:07
  • @HighPerformanceMark I am sorry I cannot properly explain my problem. My problem is the same as in https://software.intel.com/en-us/forums/intel-visual-fortran-compiler-for-windows/topic/299601 but in Linux – simona Oct 24 '16 at 15:11
  • Not compile time, run time! You want to be flexible. – Vladimir F Героям слава Oct 24 '16 at 15:24
  • Think about what Intel does when you run `source /opt/intel/your_version_path/ifortvars.sh intel64` – Vladimir F Героям слава Oct 24 '16 at 15:27
  • I certainly have not suggested what you did in EDIT2. I repeat, you **do not** want to fix the path at compile time! – Vladimir F Героям слава Oct 24 '16 at 15:58
  • @VladimirF I don't get your point, why don't I want to fix it at compile time? I would think it is good enough. I am not going to move the .so library after compilation. I require a .so library because that is used in the interface to a python code through CTYPES – simona Oct 24 '16 at 15:59
  • Is the library just for yourself for one computer? Then perhaps. But then you can just hardcode the path into the code by hand... – Vladimir F Героям слава Oct 24 '16 at 16:08
  • if you can provide a working example on how to pass a variable at runtime, it would be helpful. – simona Oct 24 '16 at 16:09
  • when you say "library" do you mean "executable"? – agentp Oct 24 '16 at 23:09
  • @agentp lib.so a shared library – simona Oct 25 '16 at 10:27

2 Answers2

1

If you wish you can fix the path at compile time. Something like

gfortran -cpp mylib.f90 -DPREFIX=\"/usr/local/\"

open(newunit=u,file=PREFIX//'mylib/initialise.dat')

You must than make sure the library is indeed installed in that place PREFIX/mylib/


You can create an environment variable containing the path of your data. This variable can be set by hand, in your .bashrc or .bash_profile or in the system /etc/profile.d/ or /etc/bash.bashrc, there are manyways and they depend if the library is just for one user or for all users of some large computer.

For example export MYLIB_PATH='/usr/local/mylib'

Then you can read the variable in Fortran as

CALL get_environment_variable("MYLIB_PATH", mylib_path, status=stat)

and the path is now in variable mylib_path. You can check the success by checking if stat==0.


This is not the only possible approach. You can also have a configuration file for your library in your home directory:

mkdir $HOME/.config/mylib/
echo "/usr/local/mylib" > $HOME/.config/mylib/path

and then you can try to read the path from this file if the environment variable was not set

if (stat/=0) then
  CALL get_environment_variable("HOME", home_dir)
  open(newunit=path_unit, file=home_dir//'/.config/mylib/path',status='old',action='read',iostat=stat)
  if (stat/=0) complain

  read(path_unit,'(a)',iostat=stat)  mylib_path
  if (stat/=0) complain
end if
1

So when you compiled with -DDATAPATH you have not passed the variable DATAPATH into your code only declared a symbol called DATAPATH as being true, so ifort will substitute DATAPATH as 1. What you need to do is pass it as a value:

-DDATAPATH="$(DATAPATH)"

For the compilation to work.

Rob
  • 574
  • 1
  • 4
  • 17