0

I had a bad(good?) idea of further modifying C preprocessed code (call it a thought experiment.)

On my quest to achieve this I got the below sequence of shell commands. Note that I have not added any modifications to the preprocessed code, but left the ability to do so:

#!/bin/bash
gcc -E debug/*.h debug/*.c src/* > build/main.i
#Command to modify build/main.i in future
gcc -Wpointer-arith -Wall ./build/main.i -o ./bin/main.exe 

However, when running the last command to compile the code, a bunch of redefinition errors are generated. An example is below. Even C-standard functions are doing the same thing.

In file included from src/String.c:3:
src/String.h:32:3: error: conflicting types for 'String'
   32 | } String;
      |   ^~~~~~
In file included from debug/StringDebug.c:5:
debug/../src/String.h:32:3: note: previous declaration of 'String' was here
   32 | } String;
      |   ^~~~~~
...many many more...
<path>\mingw\include\stdlib.h:916:61: error: redefinition of 'setenv'
  916 | __cdecl __MINGW_NOTHROW  int setenv( const char *__n, const char *__v, int __f )
      |                                                             ^~~~~~
In file included from debug/../src/Object.h:4,
                 from debug/BasicTypeDebug.c:2:
<path>\mingw\include\stdlib.h:916:61: note: previous definition of 'setenv' was here
  916 | __cdecl __MINGW_NOTHROW  int setenv( const char *__n, const char *__v, int __f )
      |                                                             ^~~~~~

Looking at build/main.i confirms that the same file is being included multiple times. I have header guards and don't declare any variables in my header files. I know nothing is wrong because running a normal compile command (below) works.

gcc -Wpointer-arith -Wall -o ./bin/main.exe debug/*.h debug/*.c src/*

Looking at this question, my guess as to what is happening is that the preprocessor, when called by itself, is putting the output of every single translation unit into one file, hence creating the duplicates. However, because a normal compilation command works, my guess is that the preprocessor is called once per translation unit when the compiler is invoked instead of just the preprocessor by itself.

So my question is twofold:

  1. Is my guess correct, or if it's not correct what is actually happening?
  2. If my guess is correct how do you tell gcc to output one preprocessed file per translation unit?

I understand what I'm trying to do isn't necessarily "correct", its more just to see what can be done and what can't.

EDIT

See kaylum's answers in the comments below for the answer. Not sure how I missed that looking back but hindsight is 20/20.

  • 1
    `gcc -E` is already outputting each preprocessed file seperately. It's just that you are redirecting it to a single file. Compared to the normal case which does preprocess file 1, compile file 1, preprocess file 2, compile file 2. You do preprocess * to X, compile X. – kaylum Aug 18 '21 at 21:25
  • @kaylum When I run ```gcc -E``` it just prints to the console as output. How would I redirect the output to multiple files? – JackCarmichael Aug 18 '21 at 21:25
  • 1
    Need to modify the script to do that. Use the shell globbing to loop over the files. That is, use a `for` loop and invoke `gcc` commands on a single file within the loop body. – kaylum Aug 18 '21 at 21:27
  • Ah, I see. I will give that a go. Thank you! – JackCarmichael Aug 18 '21 at 21:30
  • I am not sure why you need to modify the output of `gcc -E`. – jxh Aug 18 '21 at 22:12
  • If you want to have some real fun make a [Unity Build](https://en.wikipedia.org/wiki/Unity_build) and look at the preprocessed output from that. – Retired Ninja Aug 18 '21 at 22:19
  • @RetiredNinja Definitely will check out Unity Build. – JackCarmichael Aug 18 '21 at 22:27
  • 1
    You don't normally compile `.h` files directly (list them on the C compiler command line); you shouldn't do so when preprocessing them either. – Jonathan Leffler Aug 18 '21 at 23:12
  • @JonathanLeffler Thanks for the advise. I changed what you said and (unsurprisingly) compiling is faster now. – JackCarmichael Aug 19 '21 at 15:21

0 Answers0