CMake is perfectly capable of handling Fortran code; however, examples
are less abundant than for C or C++. In the example below we write a
very small CMakeLists.txt
to wrap a simple Fortran project.
The motivation for this was to easily compile Fortran code that came
with the NORMA package. The
distribution NORMA-1.0.tgz was downloaded and unpacked. following
CMakeLists.txt
was placed into
the ./software
directory where the NORMA sources are stored.
To build one would typically create a build directory at the same level
as software
:
mkdir build && cd build
ccmake ../software
make
make install
and then configure, build and install.
The project is very simple:
- There are only a few fortran source code files in the software directory.
- There are no library dependencies.
- Executables are typically installed in a bin directory in the
package itself (i.e.
NORMA/bin
) although the user is free to to change the installation prefix. - Two shell scripts are also installed alongside.
The CMakeLists.txt
is commented and additional
comments can be found after it.
Example CMakeLists.txt
# CMake project file for NORMA
cmake_minimum_required (VERSION 2.6)
project (NORMA)
enable_language (Fortran)
# make sure that the default is a RELEASE
if (NOT CMAKE_BUILD_TYPE)
set (CMAKE_BUILD_TYPE RELEASE CACHE STRING
"Choose the type of build, options are: None Debug Release."
FORCE)
endif (NOT CMAKE_BUILD_TYPE)
# default installation
get_filename_component (default_prefix ".." ABSOLUTE)
set (CMAKE_INSTALL_PREFIX ${default_prefix} CACHE STRING
"Choose the installation directory; by default it installs in the NORMA directory."
FORCE)
# FFLAGS depend on the compiler
get_filename_component (Fortran_COMPILER_NAME ${CMAKE_Fortran_COMPILER} NAME)
if (Fortran_COMPILER_NAME MATCHES "gfortran.*")
# gfortran
set (CMAKE_Fortran_FLAGS_RELEASE "-funroll-all-loops -fno-f2c -O3")
set (CMAKE_Fortran_FLAGS_DEBUG "-fno-f2c -O0 -g")
elseif (Fortran_COMPILER_NAME MATCHES "ifort.*")
# ifort (untested)
set (CMAKE_Fortran_FLAGS_RELEASE "-f77rtl -O3")
set (CMAKE_Fortran_FLAGS_DEBUG "-f77rtl -O0 -g")
elseif (Fortran_COMPILER_NAME MATCHES "g77")
# g77
set (CMAKE_Fortran_FLAGS_RELEASE "-funroll-all-loops -fno-f2c -O3 -m32")
set (CMAKE_Fortran_FLAGS_DEBUG "-fno-f2c -O0 -g -m32")
else (Fortran_COMPILER_NAME MATCHES "gfortran.*")
message ("CMAKE_Fortran_COMPILER full path: " ${CMAKE_Fortran_COMPILER})
message ("Fortran compiler: " ${Fortran_COMPILER_NAME})
message ("No optimized Fortran compiler flags are known, we just try -O2...")
set (CMAKE_Fortran_FLAGS_RELEASE "-O2")
set (CMAKE_Fortran_FLAGS_DEBUG "-O0 -g")
endif (Fortran_COMPILER_NAME MATCHES "gfortran.*")
# build executables
set (NMPROGRAMS "diagstd" "diagrtb" "proj_modes_bin" "pdbmat")
set (EXECUTABLES "NORMA.exe" ${NMPROGRAMS})
set (SCRIPTS "gen_pert.sh" "pert_multi_mode.sh")
add_executable ("NORMA.exe" "NORMA.f")
foreach (p ${NMPROGRAMS})
add_executable (${p} "${p}.f")
endforeach (p)
# install executables and scripts
install (TARGETS ${EXECUTABLES}
RUNTIME DESTINATION "bin")
install (PROGRAMS ${SCRIPTS}
DESTINATION "bin")
Comments on CMakeLists.txt
- Use cmake v2.6 or better for optimum Fortran support.
- Make sure that we build a RELEASE by default (and let the user know in the GUI); uses example code from the docs.
- Set the default prefix to the non-standard installation scheme in which one installs all component into the package directory. This directory is assumed to be one above relative the build directory. The full canonical path is obtained with the get_filename_component function.
- As it is typical for scientific Fortran code, the compiler optimizations are fairly specific. Here we are trying to detect a few common ones (gfortran, Intel ifort, g77) and set the compile options accordingly. If all else fails we use -O2 and hope for the best (but let the user know).
- The
NORMA.exe
binary is built from the sourceNORMA.f
so we have to say this explicitly with the add_executable ("NORMA.exe" "NORMA.f") line but the other binaries are simply built from corresponding .f files and we write this as a simple foreach-loop. - Executables are installed in the
bin
dir (which is relative to the prefix). - Finally, scripts are copied to the
bin
directory, too.
This page was initially populated by conversion from its original location in another wiki.