[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