I have a split project in Fortran with a subdirectory as a library:
# ./CMakeLists.txt
cmake_minimum_required (VERSION 2.8)
project (Simulation Fortran)
enable_language(Fortran)
add_subdirectory(lib)
add_executable(Simulation main.f90)
include_directories(lib)
add_dependencies(Simulation physicalConstants)
target_link_libraries(Simulation physicalConstants)
The root directory contains only a single Fortran source code file:
! ./main.f90:
program simulation
use physicalConstants
implicit none
write(*,*) "Boltzmann constant:", k_b
end program simulation
And my subdirectory lib
contains another CMakeLists.txt
as well as a Fortran module source file:
# ./lib/CMakeLists.txt:
cmake_minimum_required (VERSION 2.8)
enable_language(Fortran)
project(physicalConstants)
add_library( physicalConstants SHARED physicalConstants.f90)
! ./lib/physicalConstants.f90:
module physicalConstants
implicit none
save
real, parameter :: k_B = 1.38e-23
end module physicalConstants
I tried to build those using cmake. Make generates the physicalconstants.mod
in the lib
directory, but this file is not found during the build process of main.f90.o
:
Fatal Error: Can't open module file 'physicalconstants.mod' for reading at (1): No such file or directory
What am I missing here?
CMake Error at CMakeLists.txt:3 (project): No CMAKE_Fortran_COMPILER could be found. Tell CMake where to find the compiler by setting either the environment variable "FC" or the CMake cache entry CMAKE_Fortran_COMPILER to the full path to the compiler, or to the compiler name if it is in the PATH. -- Configuring incomplete, errors occurred!
If the target contains Fortran source files that provide modules and the compiler supports a module output directory this specifies the directory in which the modules will be placed. When this property is not set the modules will be placed in the build directory corresponding to the target's source directory.
When this property is not set the modules will be placed in the build directory corresponding to the target's source directory. If the variable CMAKE_Fortran_MODULE_DIRECTORY is set when a target is created its value is used to initialize this property.
mpifort is not a Fortran compiler, but a wrapper around one provided by the MPI implementation. CMake generally prefers to run compilers directly (because wrappers can do…funny things). Can the NAG compiler be taught about the .tbd suffix?
For target A to successfully use modules from target B, the directory where B stores module files must be among A's include directories.
One way to achieve that is to set the property Fortran_MODULE_DIRECTORY
on target B and then add that property's contents to include directories of A.
You're claiming to support ancient CMake 2.8.0, in which you'll need to do something like this:
add_executable(Simulation main.f90)
include_directories(lib)
# note that add_dependencies call is not necessary when you're actually linking
target_link_libraries(Simulation physicalConstants)
get_property(moduleDir TARGET physicalConstants PROPERTY Fortran_MODULE_DIRECTORY)
include_directories(${moduleDir})
In more modern CMake, you could do this instead:
add_executable(Simulation main.f90)
include_directories(lib)
target_link_libraries(Simulation physicalConstants)
target_include_directories(Simulation PUBLIC $<TARGET_PROPERTY:physicalConstants,Fortran_MODULE_DIRECTORY>)
You can even create a function for it:
function(LinkFortranLibraries Target)
target_link_libraries(Target ${ARGN})
foreach(Lib IN LISTS ARGN)
target_include_directories(Simulation PUBLIC $<TARGET_PROPERTY:${Lib},Fortran_MODULE_DIRECTORY>)
endforeach()
endfunction()
and then use it like this:
add_executable(Simulation main.f90)
include_directories(lib)
LinkFortranLibraries(Simulation physicalConstants)
If you do not use the Fortran_MODULE_DIRECTORY
property, module files are stored in the binary directory corresponding to the source directory of the target producing them. This can be retrieved from the target's property BINARY_DIR
, which you could use exactly as Fortran_MODULE_DIRECTORY
in variant 1.
However, CMake 2.8.0 does not support the target property BINARY_DIR
, so you will have to "reconstruct" its value manually:
add_executable(Simulation main.f90)
include_directories(lib ${CMAKE_CURRENT_BINARY_DIR}/lib)
target_link_libraries(Simulation physicalConstants)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With