UMBC High Performance Computing Facility : Linking Programs on HPC
This page last changed on Jan 11, 2009 by straha1.
Turning source code (ie.: .c, .f, .f90 files) into executables is a multi-step process. Depending on how you compile, some or all of the steps are hidden from you. If you are compiling only a single source file into an executable, you can ignore all of the steps and have the compiler directly convert your source code to an executable. We did that in the Compiling C Programs on HPC page and its Fortran 77, Fortran 90 and C++ equivalents. However, if you are creating a single executable from multiple source files then you must use a two step process. The rest of this page describes that process. If you never use more than one source file to create an executable, then you can ignore this page.
The two steps in this process are:
Each language needs a different set of libraries in order to link. A library is a file that contains multiple archived object files (.o files). Those archived object files contain implementations of functions external to your program such as C's printf, Fortran's write statement and MPI's MPI_Bcast. Each language has libraries to which you must link your object files when compiling a program. For example, C programs are linked to the libc.so library. In order to use MPI, you must link with the libraries that implement the MPI that you chose to use. Generally, MPI implementations have a separate library for each language: one for C, one for Fortran and one for C++.
The rest of this page assumes you are compiling MPI code (parallel jobs). However, all of this material works for serial code as well. If you wish to compile serial code, you will need to replace the mpicc, mpif90, mpif77 and mpicxx commands throughout this page with other commands:
When you use mpicc, mpif90, mpif77 or mpicxx (which I will refer to collectively as mpiXXX), your program is linked with the libraries appropriate for that language. If you are using only one language, linking is simple: use the mpiXXX for that language. When you use more than one language in your source files, you must use an mpiXXX that links your code with libraries for all of the languages involved.
In the next two sections, we cover the mechanics of each of the two steps in this process: compiling and linking.
To compile your source code to an object file, use the appropriate command for the language of the source file:
Each of those commands creates an object file (the .o file) that contains a binary version of the corresponding source file (.f, .f90, .c or .cc). You must run that command once for each source file that you have.
The compilation-options in the above commands should be replaced by any compiler flags that you need for your program to compile. See below for more information on that. The -c tells the mpiXXX program that you are not linking; you are creating an object file instead of an executable.
The command to link object files depends on the particular combination of languages. In general, the command has this syntax:
The my_executable should be replaced with the name of the executable you want to create. The linker-options should be replaced with any compiler flags you need for your program to link. See below for more information. The "object_file_1.o object_file_2.o object_file_3.o ..." should be replaced with a complete list of all object files that you created for this program. In general, this includes your main program (the file with your PROGRAM block in Fortran or your main(int,char**) for C and C++) plus all object files needed to implement the functions and procedures that your main program calls.
The mpiXXX should be replaced with one of mpif90, mpif77, mpicc or mpic++. You must use the mpiXXX that links your programs with the necessary libraries for all of the languages you are using. Some compilers generate extra files that the linker needs later (such as .mod module files for Fortran 90 modules). You must use an mpiXXX that knows how to use those files as well. For example, if you are compiling Fortran 90 and C code, you must use the mpif90 since it gives you all of the Fortran 90 and C libraries and knows about the Fortran 90 module files. For other combinations:
Linking C++ code with Fortran code is a special case. None of the four mpiXXX programs will link your code with both the Fortran and C++ libraries. Also, when using Fortran 90, you need mpif90 so that the compiler will be able to use the Fortran module files. However, mpif90 does not include the C++ libraries when linking. You should be able to compile the two languages by sending the -l and -L and other flags required for C++ to the mpif90 command.
There are also issues with Fortran code calling C++ code. Fortran cannot catch C++ exceptions, and it cannot access class methods. There are other, more complex issues as well. For example, suppose you have a C++ function that calls a Fortran function which calls another C++ function. If the innermost C++ function throws an exception, the Fortran function may not properly pass that exception on to the outer C++ function. Whether it does or not depends on the compiler's C++ exception implementation. Also, the Fortran function may not deallocate any arrays that were in the heap instead of the stack. In general, you can simplify this situation by creating a C-like wrapper around your C++ code, and have Fortran call the wrapper functions.
If you need to use C++ with Fortran 77 or 90 and you do not know how to do it, email user support and ask for help. See Contact Information for the user support email address. Furthermore, if you got that combination of languages working on HPC, please tell us what you did and we will post it on this website.
When you compile a program directly from source code to an executable, there are a number of options (also called switches or flags) you often use. For example, in C and C++ programs, you will often use -I /path/to/include/dir. With Fortran, you may use -module /path/to/module/dir or -M/path/to/module/dir. With both languages, you may use -L/path/to/lib/dir -llibrary-name to link with libraries (such as NetCDF, HDF or atlas). Some of these flags are used by the compilation phase (creating object files from source code) and some are used by the linking phase (creating an executable from object files). Usually, you can get away with sending all of the options to mpiXXX in both phases. Then mpiXXX will ignore the options that are inappropriate for the particular phase.
However, sometimes the compiler will get confused by the presence of options for the wrong phase. In particular, if you use multiple languages together, the mpiXXX command that you use to link will not understand the flags for other languages. For example, if you are using C and Fortran 90 code, you will compile your C code with mpicc and your Fortran code with mpif90. You will then link with mpif90. If you send C-specific compilation phase options to mpif90 when linking, mpif90 may not recognize those options. If it does not recognize them, it will give you an error.
If you run into such problems, you should try splitting your option list into two groups: one for the compilation phase and one for the linking phase. The man page for your compiler (pgf90, pgf77, pgcc, pgCC, gcc, g++ or gfortran) will tell you which option goes with which phase. The table below is a summary of which category of options goes with which phase:
|Document generated by Confluence on Mar 31, 2011 15:37|