# Problem using 'C' preprocessor with gfortran

**URL:** https://fortran-lang.discourse.group/t/problem-using-c-preprocessor-with-gfortran/64
**Category:** Help
**Created:** [May 25, 2020, 5:18am UTC](https://fortran-lang.discourse.group/t/problem-using-c-preprocessor-with-gfortran/64 "2020-05-25T05:18:51Z")
**Posts on this page:** 11
**Page:** 1

<div class="post-metadata">

### Author: ![stavros](https://avatars.discourse-cdn.com/v4/letter/s/51bf81/32.png) [@stavros](https://fortran-lang.discourse.group/u/stavros)
#### Post date: [May 25, 2020, 5:18am UTC](https://fortran-lang.discourse.group/t/problem-using-c-preprocessor-with-gfortran/64/1 "2020-05-25T05:18:51Z")

</div>

Hi all, I have the following problem:  
A sample code:

```auto
program testing_ground
    implicit none
    #ifdef _WIN32
      print *,'Windows'
    #else
      print *,'Linux'
    #endif
end program testing_ground

```

Tested in Windows 10 with: `GNU Fortran (x86_64-posix-seh-rev0, Built by MinGW-W64 project) 8.1.0`  
And in WSL with: `GNU Fortran (Ubuntu 9.3.0-10ubuntu2~18.04) 9.3.0`

compiling with either: `gfortran -o test test.F90` or `gfortran -cpp -o test test.f90` produces the following error:

```auto
test.f90:4:5:

    4 | #ifdef _WIN32
      | 1
Error: Invalid character in name at (1)
test.f90:6:5:

    6 | #else
      | 1
Error: Invalid character in name at (1)
test.f90:8:5:

    8 | #endif
      | 1
Error: Invalid character in name at (1)

```

However in the next test everything works fine:

```auto
#include "macros.fi"
program testing_ground
    implicit none
    print*,'file name:', FL
    print*,'line:', LN
end program testing_ground

```

where [macros.fi](http://macros.fi) is a separate file with:

```cpp
#ifndef FL
#define FL __FILE__
#endif

#ifndef LN
#define LN __LINE__
#endif

```

```auto
$ gfortran -o test test2.F90
$ ./test

```

result:

```auto
file name:test2.F90
line: 5

```

Why the first case that I check the operating system does not work? Am I missing something?

---

<div class="post-metadata">

### Author: ![vmagnin](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/vmagnin/32/28_2.png) [@vmagnin](https://fortran-lang.discourse.group/u/vmagnin)
#### Post date: [May 25, 2020, 7:44am UTC](https://fortran-lang.discourse.group/t/problem-using-c-preprocessor-with-gfortran/64/2 "2020-05-25T07:44:33Z")

</div>

@stavros  
I think you can not indent the C directives:

```auto
program testing_ground
    implicit none
#ifdef _WIN32
      print *,'Windows'
#else
      print *,'Linux'
#endif
end program testing_ground

```

I am not 100% sure, but I do not remember having ever seen # indentation in C code (for the first level of directives).

**Updated:** it works without indentation

```bash
$ gfortran -cpp test2.f90
$ ./a.out
 Linux

```

---

<div class="post-metadata">

### Author: ![vmagnin](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/vmagnin/32/28_2.png) [@vmagnin](https://fortran-lang.discourse.group/u/vmagnin)
#### Post date: [May 25, 2020, 8:23am UTC](https://fortran-lang.discourse.group/t/problem-using-c-preprocessor-with-gfortran/64/3 "2020-05-25T08:23:04Z")

</div>

The 1999 C standard says:

> A preprocessing directive consists of a sequence of preprocessing tokens that satisfies the following constraints: The first token in the sequence is a # preprocessing token that (at the start of translation phase 4) is either the first character in the source file (optionally after white space containing no new-line characters) or that follows white space containing at least one new-line character. The last token in the sequence is the first new-line character that follows the first token in the sequence.143) A new-line character ends…

But I do not know what is the “translation phase 4” in the compilation process, so it does not really help…

---

<div class="post-metadata">

### Author: ![stavros](https://avatars.discourse-cdn.com/v4/letter/s/51bf81/32.png) [@stavros](https://fortran-lang.discourse.group/u/stavros)
#### Post date: [May 25, 2020, 10:27am UTC](https://fortran-lang.discourse.group/t/problem-using-c-preprocessor-with-gfortran/64/4 "2020-05-25T10:27:46Z")

</div>

> [@vmagnin](#):
>
> I think you can not indent the C directives

Thank you so much! This was the issue. I must have spent the whole afternoon yesterday looking for a solution…☹ It never occurred to me that it would be the indentation.

---

<div class="post-metadata">

### Author: ![stavros](https://avatars.discourse-cdn.com/v4/letter/s/51bf81/32.png) [@stavros](https://fortran-lang.discourse.group/u/stavros)
#### Post date: [May 25, 2020, 7:39pm UTC](https://fortran-lang.discourse.group/t/problem-using-c-preprocessor-with-gfortran/64/5 "2020-05-25T19:39:37Z")

</div>

Ok it seems that I solved the compile error, but I haven’t solved my main problem, i.e. identifing the OS. For some reason non of the predefined macros are recognised in both WSL and Windows10. Just because (in the previous post) I had `#else` it printed Linux, with `#elif` it doesn’t find it.  
sample code:

```auto
program testing_ground
implicit none
#ifdef __linux__
  print*,' __linux__'
#elif linux 
  print*,'linux'
#elif __unix__
  print*,' __unix__'
#elif __gnu_linux__
  print*,' __gnu_linux__'
#elif _WIN32
  print*,'_WIN32'
#elif _WIN64
  print*,'_WIN64'
#elif __CYGWIN__
  print*,' __CYGWIN__'
#elif __MINGW64__
  print*,' __MINGW64__'
#endif 
end program testing_ground

```

ps. I tested a sample code I found in SO in c++ compiled with gcc and it works fine, I just can’t make it work with gfortran.

---

<div class="post-metadata">

### Author: ![certik](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/certik/32/4_2.png) [@certik](https://fortran-lang.discourse.group/u/certik)
#### Post date: [May 25, 2020, 8:09pm UTC](https://fortran-lang.discourse.group/t/problem-using-c-preprocessor-with-gfortran/64/6 "2020-05-25T20:09:10Z")

</div>

I think the only robust way to identify the OS is from the build system (such as CMake, later `fpm`, etc.), that passes the proper defines into source files and then you can use the pre-processor to distinguish.

---

<div class="post-metadata">

### Author: ![lkedward](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/lkedward/32/72_2.png) [@lkedward](https://fortran-lang.discourse.group/u/lkedward)
#### Post date: [May 25, 2020, 8:44pm UTC](https://fortran-lang.discourse.group/t/problem-using-c-preprocessor-with-gfortran/64/7 "2020-05-25T20:44:11Z")

</div>

Hi @stavros  
After a little digging around (with MINGW) it seems that `gfortran` does not have the same predefined macros as `gcc`.

To see predefined macros for gfortran and gcc respectively:

```auto
$ touch foo.f90; gfortran -cpp -E -dM foo.f90

```

```auto
$ gcc -dM -E - < /dev/null

```

Even when I ran your snippet through gcc (`gcc -E`) it seems to have detected the fortran file extension and it still didn’t work.

I was able to get it working by passing it to `cpp` directly:

```auto
$ cpp -P testing_ground.F90
program testing_ground
implicit none
  print*,'_WIN32'
end program testing_ground

```

I will point out that on my system, both `_WIN32` and `_WIN64` are defined as well as both ` __MINGW32__ ` and `__MINGW64`, so I agree with @certik that this may not be so robust or portable.

---

<div class="post-metadata">

### Author: ![CandL](https://avatars.discourse-cdn.com/v4/letter/c/d26b3c/32.png) [@CandL](https://fortran-lang.discourse.group/u/CandL)
#### Post date: [May 26, 2020, 9:52am UTC](https://fortran-lang.discourse.group/t/problem-using-c-preprocessor-with-gfortran/64/8 "2020-05-26T09:52:53Z")

</div>

I concur with Certik, Let CMake determine the OS. For me the process is CMake -\> Ninja. (The new version of Ninja picks up native FORTRAN support … you no longer need the Kitware version)

The WIN32 & WIN64 issue is not unique, I see those in the C/C++ compilers too.

Be careful with using preprocessor directives… they are a bit like spices. A few make life very pleasant, to many and it just doesn’t work. I have on package about 25 yrs old that has too many directives, and some seem to contradict one another… So document them well and stay consistent

---

<div class="post-metadata">

### Author: ![certik](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/certik/32/4_2.png) [@certik](https://fortran-lang.discourse.group/u/certik)
#### Post date: [May 27, 2020, 7:45pm UTC](https://fortran-lang.discourse.group/t/problem-using-c-preprocessor-with-gfortran/64/9 "2020-05-27T19:45:16Z")

</div>

@CandL excellent comments, I fully agree. Welcome!

---

<div class="post-metadata">

### Author: ![zerothi](https://avatars.discourse-cdn.com/v4/letter/z/c5a1d2/32.png) [@zerothi](https://fortran-lang.discourse.group/u/zerothi)
#### Post date: [July 10, 2020, 9:39am UTC](https://fortran-lang.discourse.group/t/problem-using-c-preprocessor-with-gfortran/64/10 "2020-07-10T09:39:00Z")

</div>

Just a small note, typically the Fortran preprocessors are not exactly the same as the C-equivalent. There are problems in Fortran codes that needs to be circumvented which means that they are generally sub-sets/or different implementations of the system.

I would highly recommend you to move to fypp for preprocessing fortran in a standardized way! 🙂

---

<div class="post-metadata">

### Author: ![hsnyder](https://yyz2.discourse-cdn.com/free1/user_avatar/fortran-lang.discourse.group/hsnyder/32/747_2.png) [@hsnyder](https://fortran-lang.discourse.group/u/hsnyder)
#### Post date: [July 12, 2020, 5:30am UTC](https://fortran-lang.discourse.group/t/problem-using-c-preprocessor-with-gfortran/64/11 "2020-07-12T05:30:07Z")

</div>

I’m not sure if this directly addresses your question, but I’d recommend having a look at the accepted answer for this stack overflow question:

> <https://stackoverflow.com/questions/31649691/stringify-macro-with-gnu-gfortran>

It explains why the C preprocessor behaves differently in gfortran than in gcc, and what you can do to work around it.

As others have said, fypp is a better preprocessor and CMake can identify the OS, but I don’t think there’s anything _wrong_ with using the c preprocessor for some things - I certainly do it.
