Using External Functions Written in F90 with Ferret for Linux


Brent A. McDaniel, Department of Earth and Atmospheric Sciences, Georgia Tech, Atlanta, Ga.
brent.mcdaniel@eas.gatech.edu

This is written as a supplement to Glenn Carver's write-up on using F90 functions with Ferret that is linked off the External Functions web page. It comes out of much trial and error in trying to get certain functions to work when called by Ferret. Some of what is included here might need to be tweaked slightly to work with your machines (paths etc.) but the basic idea will hopefully be clear.

What you need to have/do to get F90 functions to work:

1. Nag fortran compiler

2. Tweak the makefile to work with your compiler and F90.

3. Use the F90 include files (EF_Util_f90.inc and EF_mem_subsc_f90.inc)

4. Edit the file platform_specific_flags.mk.i386-linux to include certain necessary .so files and to use the f95 compiler.
 

Details:

1. Compiler: I was unable to call external functions through ferret that were compiled with anything other than the NAG fortran compiler. I tried with lf95 (Lahey-Fujitsu compiler) and also g77. Neither would work. This page assumes the user is running NAG f95.

2. Makefile: The makefile that ships with ferret is not set up to compile F90 files. An .F90 must be added to the .SUFFIXES line as well as a set of rules to compile F90 functions such as:

.F90.so:
$(F77) $(FFLAGS) $<
$(LD) $(LD_DYN_FLAGS) $(SYSLIBS) $(COMPLIBS) $*.o -o $*.so

3. The F90 include files are included in this tar file:  extfunctswithf95.tar

4. The first thing you might need to do is rename (or symbolically link) the platform_specific_flags.mk.i386-linux file to platform_specific_flags.mk.i386 due to the way the makefile calls the file. The makefile uses include ../ef_utility/platform_specific_flags.mk.$(HOSTTYPE)" which on my system (running rh 7.0) returns ../ef_utility/platform_specific_flags.mk.i386".  See the environment variable HOSTTYPE.  Some linux systems may be i486-linux for example. If you have problems with the makefile then check the include line carefully. Next you need to change the compile flags to remove the -f77. The function will not be callable if it is written in F90 and you compile it with -f77!

I also added a new variable:
COMPLIBS = /usr/local/lib/NAGWare/libf96.so /usr/local/lib/NAGWare/quickfit.o

This is called during the link stage of the make. The purpose of this is to include certain libraries that the ferret executable doesn't know where to find. These are path dependent so edit the path to fit your system.
 

Common problems:

* You try to make the file (make myextfunction.so) and get the message
make: *** No rule to make target `myextfcn.so'. Stop.
Solution: make sure that you added the .F90 to the .SUFFIXES line in the makefile.

* The makefile says it can't find certain files.
Solution: Check the include paths carefully in the makefile and in the code itself.

* The makefile tries to compile the source and a large number of errors occurs.
Solution: Make sure that you've included the EF_Util_f90.inc and EF_mem_subsc_f90.inc files and not the f77 ones that come with the standard ferret external function files.

* The makefile works properly and returns a dynamically linked (.so) file. You attempt to call this from within ferret and get a messages such as: "/usr/local/ferret/ext_func/libs/myextfcn.so: undefined symbol: ef_version_test__".
Solution: This is a result of compiling with the -f77 flag. Remove this flag and recompile. The way to tell if this is your problem is that the undefined symbol will be a ferret function call with 2 underscores on the end.

* A function is compiled successfully but when you attempt to call it from within ferret you get a message like:

ERROR in External Function myextfcn:
Dynamic linking call dlopen() returns --
"/usr/local/ferret/ext_func/libs/myextfcn.so: undefined symbol:
__NAGf90_already_allocated".
Solution: This results from the compiler not knowing explicitly where to find certain objects. The COMPLIBS variable in the platform_specific_flags  file is where you explicitly specify what other shared objects to include. See Glenn Carver's F90 page on how to determine which files need to be included. As a side note, I also had to set the variable LD_RUN_PATH to the directory that includes the NAG shared objects. I did this by adding the lines in my .bash_profile:
 
LD_RUN_PATH=/usr/local/lib/NAGWare
export LD_RUN_PATH
Hopefully that should help you get on your way to creating and running your own external functions. I'd like to say thanks to Ansley Manke and the rest of the Ferret team for helping me get this up and running. If you have questions or problems getting your own external functions up and running on linux, email me and I'll try to help you out. Hopefully this page plus the attached files should help out.

Cheers,
Brent

Return to Ferret External Functions page


Dept of Commerce / NOAA / OAR / PMEL / TMAP