[CMake] Compiling Fortran Modules And

Andreas Mohr andi at lisas.de
Tue May 14 03:14:08 EDT 2013


Hi,

On Mon, May 13, 2013 at 09:31:46PM -0400, cmake-request at cmake.org wrote:
> I'm converting a Fortran package that was using GNU make to build to CMake, but I've run into a problem compiling F90 module code where the source code is stored under many directories.
> 
> The package has a directory structure
> 
> src/
>       src/dir1
>       src/dir2
>       :
>       :

Ooook...


> Each dir* has *.F files that must be preprocessed to *.f90 files and then compiled. In the original build system, the package had an empty 'build' directory under src. The processed files were created there and then the library was built from these files was also generated there. I tried to do something similar with CMake but I see errors  from make about 'No rules to make target ' pointing to files that do not exist under the CMakeFiles directories, however the object file and the *.mod files are there, so I know I'm compiling correctly.

The semi-famous "No rules to make target" error, hinting at
wrong-directory issues.

> Here's my CMakeLists.txt snippet in the src directory
> 
> 
> set(DIR1_FILES dir1/file1_module.F dir2/file2_module.F)
> set(DIR2_FILES dir2/file3_module.F dir2/file4_module.F)
> set(F_PREPROCESS_FILES ${DIR1_FILES} ${DIR2_FILES})

Hmm. Files with directory specification.

But then...

> set(F90Library_SOURCE_FILES)
> foreach (src_file ${F_PREPROCESS_FILES})
> 
>   get_filename_component(filename "${src_file}" NAME_WE)
>   set(F_file ${CMAKE_CURRENT_SOURCE_DIR}/${src_file})

...using filename-only prepended with a questionably precise
*current source dir* (if that was a function/macro invoked from
somewhere else, then I'd buy that argument since
CMAKE_CURRENT_SOURCE_DIR likely *would* be meaningful each,
but since it seems it's processing over that F_PREPROCESS_FILES loop
open-coded right there, the dir does seem out-of-place versus each
of the input file dirs).

>   set(new_file_f90 ${CMAKE_CURRENT_BINARY_DIR}/${filename}.f90)
>   message(STATUS "new_file_f90=${new_file_f90}")
> 
>   add_custom_command(OUTPUT "${new_file_f90}"
>       COMMAND ${CMAKE_C_COMPILER} -E ${CMAKE_CPP_FLAGS} ${F_file} ${grep_filter} | grep -v \\!\\!CPP\\!\\! | grep -v ^\#  > ${new_file_f90}
>       IMPLICIT_DEPENDS Fortran "${F_file}"
>       COMMENT "\tPreprocessing ${src_file}"
>       VERBATIM)
>   list(APPEND PGSLibIface_SOURCE_FILES ${new_file_f90})
> endforeach()
> 
> 
> # --- Library
> add_library(mylib ${F90Library_SOURCE_FILES})
> 
> 
> When I try to build, the error I see is the following
> 
>   Preprocessing dir1/file1_module.F
>   Preprocessing dir1/file2_module.F
>   Preprocessing dir2/file3_module.F
>   Preprocessing dir2/file4_module.F
>   Scanning dependencies of target mylib
>   Building Fortran object src/CMakeFiles/mylib.dir/file1_module.f90.o
> make[2]: *** No rule to make target `src/file1_module.f90.provides', needed by `src/CMakeFiles/mylib.dir/file1_module.mod.proxy'.  Stop.
> make[1]: *** [src/CMakeFiles/mylib.dir/all] Error 2
> make: *** [all] Error 2


A frequent CMake pattern is to have one CMakeLists.txt per each files
directory (to always have processing symmetrically going from foo_SOURCE_DIR to
foo_BINARY_DIR, such as configure_file() etc.).
Thus without even analyzing the problem (apologies!), I'd suggest
having CMakeLists.txt per dir which then calls into a common
macro/helper (to be implemented by a module) which will do that per-file
processing, *with* *correct* *directory* *arguments* *each*
(implicitly!).

HTH,

Andreas Mohr

-- 
GNU/Linux. It's not the software that's free, it's you.


More information about the CMake mailing list