[CMake] Fortran MinGW on Windows

Leek, Jim leek2 at llnl.gov
Wed Jun 12 00:55:20 EDT 2013


This is a follow-up post to document the eventual solution to this issue.

The problem turned out to be where I decided to put enable_language(Fortran).  This project is largely C++, but has a few optional Fortran libraries.  I did not want Fortran to be required if the user does not want to use the libraries that require Fortran.  Therefore I had the CMakeLists.txt files divided like this:

In the main CMakeLists.txt file, the user can choose to use a Fortran library, MARS in this case:
if (USE_MARS)
  include_directories ("${PROJECT_SOURCE_DIR}/External/MARS")
  add_subdirectory (External/MARS) 
  set (EXTRA_LIBS ${EXTRA_LIBS} mars)
  add_definitions(-DHAVE_MARS)
endif (USE_MARS)

Then I had another CmakeLists.txt file in External/MARS that builds the MARS library with Fortran:
enable_language(Fortran)
add_library(mars ${LIBRARY_TYPE} mars36_fort.f)
install (TARGETS mars DESTINATION lib)

This built the Fortran libraries correctly.  However, then I tried to build the main executable statically, it neglected to include the necessary Fortran libraries.  (Building shared libraries actually worked fine.)

/usr/bin/c++       CMakeFiles/psuade-bin.dir/Src/Main/Psuade.cpp.o  -o psuade -rdynamic libpsuade.a External/Bose/libbose.a External/MARS/libmars.a -llapack -lblas -Wl,-rpath,:::::::::::::
External\MARS\libmars.a(mars36_fort.f.obj):mars36_fort.f:(.text+0x21fce): undefined reference to `_gfortran_transfer_integer_write'

The build line should look like this (have -lgfortran):
/usr/bin/c++       CMakeFiles/psuade-bin.dir/Src/Main/Psuade.cpp.o  -o psuade -rdynamic libpsuade.a External/Bose/libbose.a External/MARS/libmars.a -llapack -lblas -lgfortran -lquadmath -Wl,-rpath,::::::::::::::

CMake is supposed to detect the required libraries automatically, what's wrong?

Well, I'm not sure if this would be considered a cmake bug or a user error.  I couldn't find any documentation on it either way.  But I should have had enable_language(Fortran) in the main CMakeLists.txt file like this:

if (USE_MARS)
  enable_language(Fortran)
  include_directories ("${PROJECT_SOURCE_DIR}/External/MARS")
  add_subdirectory (External/MARS) 
  set (EXTRA_LIBS ${EXTRA_LIBS} mars)
  add_definitions(-DHAVE_MARS)
endif (USE_MARS)

then the CMakeLists.txt file in External/MARS can look like this:
add_library(mars ${LIBRARY_TYPE} mars36_fort.f)
install (TARGETS mars DESTINATION lib)

So, there you go.  enable_language(Fortran) can be optional, but it must be in the main CMakeLists.txt file.

Jim


More information about the CMake mailing list