Cross Compiling C and Fortran

From assela Pathirana
Jump to: navigation, search

Recently I had to mix two large models written in C and Fortran (95 standard) to build a single monolithic program. In theory cross compilation is easy -- in practice its far from it. Your run off the mill 'hello world' implemented in C and called from Fortran (or vice versa) is one thing, but marrying off two large programs (numerous code files in each) written in two languages is a whole different story. Following is an account of my experience:

What worked for me 1) Sun Studio 11 works brilliantly. It's only available on Linux & Solaris platforms (not on Windows), but that is what got me though. (Free as in beer) 2) Intel compilers are also good. But, getting them to work effectively is a real pain. Download multiple gigabyte Microsoft Visual Studio 90 day trial from Microsoft (Even if you don't want to use their compilers!), then download C and Fortran compiler trial versions from Intel!! 3) Eclipse CDT/Photran (no that is not a spelling mistake!) is nice. But, you must know your way around configuring eclipse -- its a massive system that includes everything plus the Kitchen Sink. But, the good news is it is Free and Open Source (Free as in speech).

First the Theory

To repeat, cross compiling should simply work -- in theory. But in practice, there are numerous points to get straight before anything works. The following two web sites helped me a great deal for learning the 'rules'.

  1. Using C/C++ and Fortran together
  2. Using C and C++ with Fortran

Most important things I learned:

  • Fortran compiler and C compiler does name mangling in very different ways. It totally depends on the specific compiler and flags used. One common pattern is
CALL FOO( K, value) void foo_(int * bar, double * bat)
  • Fortran does not know the difference between UPPER and lower case. Often you have to tell the compiler to use lowercase and make sure all your c functions are written in lowercase.
  • Fortran always pass arguments by reference. And in C these look as memory addresses. (Notice the dereference on the C side in above table.)
  • C function returns does not mean a thing to Fortran. Values should be sent using (pointer) arguments.
C -- incorrect C -- Correct Fortran -- Calling
double foo_(int * k) void foo_(int * k, double * p) CALL FOO(valin, valout)

For example look at the C function get_swmm_dt and how it is called from Fortran.

10 void get_swmm_dt_(double * dt){
11 	*dt=RouteStep;
12 }
100 real*8 swmmdt 
101 ...
102 call get_swmm_dt(swmmdt)
  • Compile C code with C compiler, Fortran with Fortran compiler (kind of obvious!), but always link with the Fortran linker.
For Example
g++ -c ctest.c 
gfortran -c ftest.f90 
gfortran *.o -lstdc++ -o test_prog

Now the practice

Following are the things I learned the hard way.

My first platform to try this on was Eclipse . Eclipse has a C-development environment (CDT) that use GNU compilers gcc, g++ and their excellent debugger gdb. Then there is the Fortran extension, Photran that provides support for GNU fortran compilers (Fortran 77, 90, 95, and 2003). All these work on both Linux and Windows. I could get the system to compile my code properly. But, things started to get uncomfortable when the program started producing some NaNs. The GNU compilers do not support Floating Point Exception Trapping (Floating_point), except with platform dependant API calls. Debugging across C and Fortran code also did not work very well for me.

What came to rescue was the Sun Studio which is a proprietary, but free platform that works on Linux and Solaris. Now this provides only

  1. A C/C++ Compiler
  2. A Fortran Compiler
  3. A debugger
  4. An an extremely simple IDE based on NetBeans system.

Now this is a demonstration of the wisdom of doing a little, but doing that well. The system works like a dream (I tried it on my 64-bit Ubuntu Karmic installation) and allowed me to compile C and Fotran in a single IDE project (with automake -- a kind of system that the IDE writes the makefiles for you.), debug code across both languages, trap IEE floating point exceptions. What more can one hope for!

Since I needed to give the compiled code to my students, who use only windows system, later I compiled the (already properly working) code on Windows using Intel Compilers + Visual Studio 2008. But, Intel/Microsoft system has several limitations compared to Sun Studio.

  1. You can have only one language in one IDE project. So, I needed to create a C static libarary project, compile the C code to a static library, compile the Fortran code and link with the created static library in another project. Of course the build process can be automated. But, its an unnecessary complication. Debugging also can be a bit difficult.
  2. Here you face a situation similar to Eclipse+CDT+Photran combo. Three tools (Intel Fortran, Intel C/C++, Visual Studio 2008) that has to be taught to work together -- a bit messy. Then, it is provided by two companies and the system is expensive!
  3. I learned (the hard way) that Intel C and Fortran compilers refused to do anything with each other (e.g. linking a library created by Intel C version 11.x.y with Fortran linker version 11.k.p). So, if you must go the Intel path, download compilers of identical version.
  4. The system is huge! I ended up downloading more than 3GB of programs!

My Advice

Here's my two cents' worth based on experience:

  1. If you know something, anything, about working with Linux do yourself a favour and develop in Linux with Sun Studio. Do this even if you deploy (later) in windows. (If you don't know any Linux of course you are missing a world of fun. Go and download Linux Mint -- a very user friendly Ubuntu variant and burn a Live CD. You don't even have to install it to try!)
  2. Whatever you do, develop in a platform that has 1) easy IEEE Floating Point trapping 2) a decent debugger.
  3. First try something like the obligatory 'hello world' to learn the tricks and to test your build environment before trying the complicated code. Here's a tutorial.