Search code examples
cmakefortran

CMake multiple version of fortran *.mod files


Fortran uses so-called mod files. They work similarly to a library. They are, however, important during compile stage of the objects. Now I am writing a CMake build for an older Fortran project. CMake luckily can recognise module dependencies. When CMake is compiling objects for a target they are stored in separed folder like:

CMakeFiles/target_name.dir/src/

Mod files are not. Instead, they are stored in the compiler execution directory. In order to make compile and link stage work I add:

 target_include_directories( ${EXECUTABLE}
   PRIVATE
     ${CMAKE_CURRENT_LIST_DIR}
   )

So in the end *.o files are stored in separate directories and *.mod are in the build directory. This has worked well for me for some time. But now I have a project where it is not possible. I have multiple targets that are compiled out of the same source files using different precompiled options. There are no problems with *.o files because they are stored in separate directories. But if *.mod files are changed by these directives they cannot be stored in the same build directory.

I was thinking to move *.mod files into a separate directory after each compile stage and linking them with ${CMAKE_CURRENT_LIST_DIR}/PRECOMPILER_OPTION_A, but still I would have a problem with race conditions if I would use parallel make.

Is there a solution where I can specify the compiler execution path per target? Or are you aware of some other solution that would work?


Solution

  • I found a solution here.

    Basically the easiest solution is to manage Fortran_MODULE_DIRECTORY separatly for each target:

    add_library(A OBJECT source.f90)
    set_target_properties(A PROPERTIES Fortran_MODULE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/A)
    target_include_directories(A PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/A)
    
    add_library(B OBJECT source.f90)
    set_target_properties(B PROPERTIES Fortran_MODULE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/B)
    target_include_directories(B PUBLIC ${CMAKE_CURRENT_BINARY_DIR}/B)