[CMake] CMake and Preprocessing

Michael Wild themiwi at gmail.com
Tue Nov 17 15:55:39 EST 2009


On 17. Nov, 2009, at 19:13 , Anastasia Shchupak wrote:

> Hello,
> I'm porting multiplatform fortran project build system to CMake. Due  
> to OpenMP code, I need to use FPP preprocessor always (before  
> compiling by any compiler, because some fortran compilers use just  
> CPP as preprocessor, that does not support OpenMP).
> Is there a common solution using CMake to split preprocessing from  
> compiling and set up a preprocessor that differs from that is  
> incorporated into a compiler?
> Thanks.
> Anastasia.

Hi

Not that I'd know of. However, what you can do is define custom  
function which takes a list of files and generate rules to feed them  
through FPP and write them to the binary tree. The resulting files are  
returned in a list which you can then pass to ADD_LIBRARY or  
ADD_EXECUTABLE.

As an example, the library function might look something like this (I  
don't have FPP, so you might need to adjust the ADD_CUSTOM_COMMAND):

# find FPP
find_program(FPP_EXECUTABLE fpp)
if(NOT FPP_EXECUTABLE)
   message(SEND_ERROR "Could not find the Fortran Preprocessor FPP")
endif()

# - Function to pass Fortran files through FPP
#   PREPROCESS_FORTRAN(outputfiles inputfile ...)
# The function determines if the file is a Fortran file based on
# its extension. This implementation feeds .f, .F, .f90, .F90, .f95  
and .F95
# through the preprocessor.
function(preprocess_fortran outvar)
   # determine include directories
   get_directory_property(incdirs INCLUDE_DIRECTORIES)
   set(incflags)
   foreach(i ${incdirs})
     set(incflags "${incflags} -I${i}")
   endforeach()
   # set up defines (not configuration specific)
   get_directory_property(defines COMPILE_DEFINITIONS)
   set(defflags)
   foreach(d ${defines})
     set(defflags "${defflags} -D$d")
   endforeach()
   # loop over all arguments
   set(srcs)
   foreach(f ${ARGN})
     # is it a Fortran file?
     if(f MATCHES "\\.[Ff](9[05])?")
       message(STATUS "Got fortran file: ${f}")
       # construct output filename
       if(NOT IS_ABSOLUTE "${f}")
         get_filename_component(f "${f}" ABSOLUTE)
       endif()
       file(RELATIVE_PATH r "${CMAKE_CURRENT_SOURCE_DIR}" "${f}")
       get_filename_component(e "${r}" EXT)
       get_filename_component(n "${r}" NAME_WE)
       get_filename_component(p "${r}" PATH)
       set(of "${CMAKE_CURRENT_BINARY_DIR}/${p}${n}_fpp${e}")
       message(STATUS "Output name: ${of}")
       # preprocess the thing
       add_custom_command(OUTPUT "${of}"
         COMMAND ${FPP_EXECUTABLE} ${incflags} "${defflags}" "${f}" "$ 
{of}"
         IMPLICIT_DEPENDS Fortran "${f}"
         COMMENT "Preprocessing ${f}"
         VERBATIM
       )
       list(APPEND srcs "${of}")
     else()
       list(APPEND srcs "${f}")
     endif()
   endforeach()
   # return the (preprocessed) sources
   set(${outvar} "${srcs}" PARENT_SCOPE)
endfunction()


All of this is, of course, untested but should give you an idea.

HTH

Michael


More information about the CMake mailing list