[CMake] Problem with Fortran module enclosed in #ifdef

Martin Apel martin.apel at simpack.de
Fri Jan 9 08:05:57 EST 2009


Michael Wild wrote:
> On 9. Jan, 2009, at 10:26, Martin Apel wrote:
>
>   
>> Michael Wild wrote:
>>     
>>> On 9. Jan, 2009, at 9:27, Martin Apel wrote:
>>>
>>>
>>>       
>>>> Hi all,
>>>>
>>>> I am experiencing a problem with one Fortran source file
>>>> containing a
>>>> module definition. Unfortunately the whole source file is enclosed
>>>> in
>>>> '#ifdef WINDOWS'. On Linux this causes the build process to fail,
>>>> because cmake wants to copy a generated .mod file, which does not
>>>> exist.
>>>> The file containing the module has the suffix ".f". When changing
>>>> the
>>>> suffix to ".F", everything works fine.
>>>> CMake probably thinks, the file need not be preprocessed before
>>>> scanning, if it has the suffix ".f". Is there any way to tell CMake,
>>>> that files with the suffix ".f" have to be preprocessed before
>>>> dependency scanning?
>>>>
>>>> Regards,
>>>>
>>>> Martin
>>>>
>>>>
>>>>         
>>> Hi
>>>
>>> I think it is fairly non-standard to have a .f file preprocessed. All
>>> Fortran compilers I'm acquainted with only preprocess a file if it
>>> has
>>> a .F extension (unless forced, of course).
>>>
>>> But since it is the whole file, can't you just exclude it in the
>>> CMake
>>> code?
>>>
>>> set( SRCS foo.f bar.f )
>>> if(WIN32)
>>>   list( APPEND SRCS winspecific.f )
>>> endif(WIN32)
>>>
>>> add_executable( super_cow ${SRCS} )
>>>
>>>       
>> You are right, that this is uncommon. But I'm trying to replace an
>> existing "build system" for some thousands of files, which
>> preprocesses
>> all Fortran files, even those with ".f" suffix. Unfortunately this is
>> something I can't change.
>> I could use the approach you suggest, but I'd like a more general
>> solution, because I cannot be sure, that this is the only file, where
>> preprocessing makes a difference. There might
>> be other files containing a USE directive enclosed in ifdefs.
>>
>> Regards,
>>
>> Martin
>>
>>     
>
> I just constructed a small test case, and it works for me (using
> CMake-2.6 and gfortran). See below.
>
> Michael
>
> test.f90:
> =========
>
> program test
> #ifdef MORE
>    use test_module
> #endif
>    implicit none
>
>    print *, "This is a test"
>
> #ifdef MORE
>    call hello()
> #endif
>
> end program test
>
>
> modules/test_module.f90
> =======================
>
> #ifdef MORE
> module test_module
>    implicit none
>    contains
>    subroutine hello()
>      implicit none
>      print *,"Hello World"
>    end subroutine
> end module test_module
> #endif
>
>
> CMakeLists.txt
> ==============
>
> project( test Fortran )
>
> cmake_minimum_required( VERSION 2.6 )
>
> option( DEFINE_MORE "If set to ON, -DMORE will be defined" OFF )
> # force gfortran to preprocess the input files
> # change this to "-fpp" for ifort (that's the ones i know...)
> set( FORTRAN_PREPROCESS_FLAG "-x f95-cpp-input" CACHE STRING
>    "Flags to force the Fortran compiler to preprocess the source
> files.")
>
> if( DEFINE_MORE )
>    add_definitions( -DMORE )
> endif( DEFINE_MORE )
>
> add_executable( test test.f90 modules/test_module.f90 )
>
> set_target_properties( test PROPERTIES COMPILE_FLAGS $
> {FORTRAN_PREPROCESS_FLAG} ))
>
> .
>
>   
Good idea, but unfortunately this doesn't help in my case. The fact,
that I have two nested '#if defined' statements, seems to make a
difference. I have searched the CMake sources a bit. I found a comment
in cmDependsFortran.cxx as follows:
  /* Note: The current parser is _not_ able to get statements like
   *   #if 0
   *   #if 1
   *   #if MYSMBOL
   *   #if defined(MYSYMBOL)
   *   #if defined(MYSYMBOL) && ...
   * right.  The same for #elif.  Thus in
   *   #if SYMBOL_1
   *     ..
   *   #elif SYMBOL_2
   *     ...
   *     ...
   *   #elif SYMBOL_N
   *     ..
   *   #else
   *     ..
   *   #endif
   * _all_ N+1 branches are considered.  If you got something like this
   *   #if defined(MYSYMBOL)
   *   #if !defined(MYSYMBOL)
   * use
   *   #ifdef MYSYMBOL
   *   #ifndef MYSYMBOL
   * instead.
   */

I have exactly the first case with two nested '#if defined' directives.
Changing these to '#ifdef' solved the problem for me. Not nice,
but this works around CMake's problem.

Thanks for your help,

Martin
____________
Virus checked by G DATA AntiVirus
Version: AVF 19.215 from 08.01.2009




More information about the CMake mailing list