[CMake] Compiling Fortran Modules And

Pritchett-Sheats, Lori lpritch at lanl.gov
Tue May 14 10:36:18 EDT 2013


Lori A. Pritchett-Sheats
Los Alamos National Laboratory
CCS-2, Computational Physics
505-665-6675

________________________________________
From: Andreas Mohr [andi at lisas.de]
Sent: Tuesday, May 14, 2013 1:14 AM
To: cmake at cmake.org
Cc: Pritchett-Sheats, Lori
Subject: Re: Compiling Fortran Modules And

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).


I've replaced CMAKE_CURRENT_SOURCE_DIR with <PROJECT_NAME>_SOURCE_DIR where PROJECT_NAME is my current project name. Did not change the behavior of the error. CMake still can not find rules to make the files I listed below.


>   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.).

I'm aware that this is a frequent usage pattern. However, in this case I have numerous directories, Fortran module dependencies across these directories and at the end instead of a single library to install, I would have over 20 libraries. If I can not maintain the  old directory structure, I would rather flatten the entire src tree.


Creating a CMakeLists.txt file for each directory 
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!).

As I mentioned above, I have already tried explicit project name variables and it did not change the behavior.

HTH,

Andreas Mohr

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


More information about the CMake mailing list