CMake Fortran design patterns

CMake is excellent for building very complex Fortran projects across operating systems and computing platforms from embedded systems to HPC. Here are a few common Fortran CMake patterns.

specify linker options for all targets using add_link_options()

add_link_options(-myflag)

or for a particular target (or static linkers) with

set_property(TARGET myexe PROPERTY STATIC_LIBRARY_OPTIONS -myflag)

For hand-written Makefile the order of libraries matters completely. CMake attempts to determine the graph for library files, starting from the user specified order. CMake will try a finite multiplicity to resolve the graph, but in tough cases of library interdependency library ordering may need to be influenced by add_dependencies() or even object libraries.

“Undefined reference to” occurs at linking of main executable: be sure the library is actually linked to the user library with

cmake --build build -v

Fortran module include: be sure the *.mod file directory is included, particularly to the main executable by setting the target properties like:

include(GNUInstallDirs)

target_include_directories(mymod INTERFACE ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR})

set_property(TARGET mymod PROPERTY Fortran_MODULE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR})

this can be done for numerous targets in a loop instead of repeatedly specifying by a foreach() loop:

foreach(t foo bar biz baz)
  target_include_directories(${t} INTERFACE ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR})

  set_property(TARGET ${t} PROPERTY Fortran_MODULE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_INSTALL_INCLUDEDIR})
endforeach()

To ensure the build system is completely updated, do

cmake --build build --clean-first