Subsections


6 Compiling and Linking User Code against an ESMF Installation

Building user applications against an ESMF installation requires that the compiler and linker be able to find the appropriate ESMF header, module and library files. If this procedure has been documented by the installer of the ESMF library on your system then follow the directions provided.

In the absence of installation specific instructions there are two standard methods supported by ESMF to build user code against the installation. The first method is based on a GNU makefile fragment that can be included by the user code build infrastructure. This method requires that the user application also uses the GNU Make system. The second method is based on CMake.


6.1 esmf.mk method

Every ESMF installation provides a file named esmf.mk that contains the information needed to build a user application gainst the installation. The location of the esmf.mk file should be documented by the party that installed ESMF on the system. We recommend that a single ESMF specific environment variable, ESMFMKFILE, be provided by the system that points to the esmf.mk file. See section 9.9 for the related discussion aimed at the person that installs ESMF on a system.

The information in esmf.mk is defined in form of variables. In fact, syntactically esmf.mk is a makefile fragment and can be imported by an application specific makefile via the include command. All the variables in esmf.mk start with the "ESMF_" prefix to prevent conflicts. The information in esmf.mk is fully specified and is not affected by any variables set in the user's environment.

The information defined in esmf.mk includes Fortran compiler and linker, as well as C++ compiler and linker. It further includes the recommended Fortran and C++ specific compiler and linker flags for building ESMF applications. One way of using the esmf.mk is to glean the necessary information from it. This information can then be used either directly on the command line when compiling a user application, or to hardwire the settings into the application specific build system. However, the recommended use of esmf.mk is to include this file in the application specific makefile directly via the include command.

The Makefile template below demonstrates how a user build system can be constructed to leverage the esmf.mk file. In practice, most user build systems will be more complex. However, this template does show that the added complexity introduced by using esmf.mk is minimal. Examples of how to use this build system in realistic user scenarios can be found in the external demos.

The advantages of using esmf.mk, over hard coding suitable compiler and linker flags into the user build system directly, are robustness and portability. Robustness is a consequence of the fact that everything defined in esmf.mk corresponds to the exact settings used during the ESMF library build (consistency) and during the ESMF test suite build. Using esmf.mk thus guarantees that the user application is build in the exact same manner as the ESMF test suite applications that undergo strict regression testing before every ESMF release. Portability means that a user build system, which uses esmf.mk in the way the template Makefile demonstrates, will function as expected on any system where ESMF was successfully installed and tested, without the need of modifying anything. Every esmf.mk is generated during a specific ESMF installation using the ESMF tested settings for the host platform.

################################################################################
### Makefile template for user ESMF application, leveraging esmf.mk mechanism ##
################################################################################

################################################################################
### Finding and including esmf.mk ##############################################

# Note: This fully portable Makefile template depends on finding environment
#       variable "ESMFMKFILE" set to point to the appropriate "esmf.mk" file,
#       as is discussed in the User's Guide.
#       However, you can still use this Makefile template even if the person
#       that installed ESMF on your system did not provide for a mechanism to
#       automatically set the environment variable "ESMFMKFILE". In this case
#       either manually set "ESMFMKFILE" in your environment or hard code the
#       location of "esmf.mk" into the include statement below.
#       Notice that the latter approach has negative impact on portability.

ifneq ($(origin ESMFMKFILE), environment)
$(error Environment variable ESMFMKFILE was not set.)
endif

include $(ESMFMKFILE)

################################################################################
### Compiler and linker rules using ESMF_ variables supplied by esmf.mk ########

.SUFFIXES: .f90 .F90 .c .C

.f90:
	$(ESMF_F90COMPILER) -c $(ESMF_F90COMPILEOPTS) $(ESMF_F90COMPILEPATHS) \
          $(ESMF_F90COMPILEFREENOCPP) $<
	$(ESMF_F90LINKER) $(ESMF_F90LINKOPTS) $(ESMF_F90LINKPATHS) \
          $(ESMF_F90LINKRPATHS) -o $@ $*.o $(ESMF_F90ESMFLINKLIBS)        

.F90:
	$(ESMF_F90COMPILER) -c $(ESMF_F90COMPILEOPTS) $(ESMF_F90COMPILEPATHS) \
          $(ESMF_F90COMPILEFREECPP) $(ESMF_F90COMPILECPPFLAGS) $<
	$(ESMF_F90LINKER) $(ESMF_F90LINKOPTS) $(ESMF_F90LINKPATHS) \
          $(ESMF_F90LINKRPATHS) -o $@ $*.o $(ESMF_F90ESMFLINKLIBS)        
        
.c:
	$(ESMF_CXXCOMPILER) -c $(ESMF_CXXCOMPILEOPTS) \
          $(ESMF_CXXCOMPILEPATHSLOCAL) $(ESMF_CXXCOMPILEPATHS) \
          $(ESMF_CXXCOMPILECPPFLAGS) $<
	$(ESMF_CXXLINKER) $(ESMF_CXXLINKOPTS) $(ESMF_CXXLINKPATHS) \
          $(ESMF_CXXLINKRPATHS) -o $@ $*.o $(ESMF_CXXESMFLINKLIBS)

.C:
	$(ESMF_CXXCOMPILER) -c $(ESMF_CXXCOMPILEOPTS) \
          $(ESMF_CXXCOMPILEPATHSLOCAL) $(ESMF_CXXCOMPILEPATHS) \
          $(ESMF_CXXCOMPILECPPFLAGS) $<
	$(ESMF_CXXLINKER) $(ESMF_CXXLINKOPTS) $(ESMF_CXXLINKPATHS) \
          $(ESMF_CXXLINKRPATHS) -o $@ $*.o $(ESMF_CXXESMFLINKLIBS)

################################################################################
### Sample targets for user ESMF applications ##################################

all: esmf_UserApplication esmc_UserApplication

esmf_UserApplication:

esmc_UserApplication:

################################################################################

Notice that the ESMF_F90LINKPATHS, ESMF_F90LINKRPATHS, ESMF_CXXLINKPATHS, and ESMF_CXXLINKRPATHS variables used in the linking targets might contain paths to the specific compiler version, MPI implementation, and 3rd party libraries (see section 9.4) used when building ESMF. The paths are explicitly included in order to simplify the process of writing an application build system that is consistent with the ESMF library that is used.

There are, however, situations where it is desirable to let the application decide what compiler version, MPI version, and/or 3rd party library verson (e.g. NetCDF) to use. To this end, esmf.mk defines an alternative set of variables: ESMF_F90ESMFLINKPATHS, ESMF_F90ESMFLINKRPATHS, ESMF_CXXESMFLINKPATHS, and ESMF_CXXESMFLINKRPATHS. These variables only encode the precise path to the ESMF library, and do not specify where to find the compiler, MPI, and/or 3rd party libraries. When using this alternative set of variables, it becomes the responsibility of the application build system to ensure the required libraries can be found by the linker, and are compatible with the ESMF installation.

6.2 CMake method

An ESMF CMake find file is located at: <ESMF source directory>/cmake/FindESMF.cmake

The find file will parse the esmf.mk file created following a successful ESMF build. (See 6.1 for a description of the esmf.mk file.) The CMake module sets esmf.mk variables as global CMake variables. When using the find file, ESMFMKFILE must be set to the filepath of esmf.mk. If this is NOT set, then ESMF_FOUND will always be FALSE. If ESMFMKFILE exists, then ESMF_FOUND=TRUE and all ESMF makefile variables will be set in the global scope. Optionally, set ESMF_MKGLOBALS to a string list to filter makefile variables. For example, to globally scope only ESMF_LIBSDIR and ESMF_APPSDIR variables, use this CMake command in CMakeLists.txt: set(ESMF_MKGLOBALS "LIBSDIR" "APPSDIR")

esmf_support@ucar.edu