August 21, 2004

The gcc preprocessor

I've been dropped back into the world of writing and porting C/C++ code the last couple weeks.

It's been a big hairy bag o' fun. First, I wrote the new code in C++ assuming the group using the library would be using newer compilers. Silly me. Turned out they were still stuck with GCC 2.95.x which wasn't going to work. Moving the code to C wasn't really difficult, even if I lost a bit on the way. The single biggest loss? Defining variables as needed... oh no, still gotta create a pack of variables at the top of the function. Serious yuck. Raw string handling? Oh lord, spare me.

I also had to spend a good deal of time dealing with make (and its progeny, the Makefile) again. I take back all the nasty things I've said about ant. Yeah, ant still sucks but make is ant on quaaludes after a frontal lobotomy. Me thinks I'll find someone else to deal with Makefile issues in the future.

I'm also dinking around with some RADIUS stuff and need a simple, one at a time NAS test. Since no one has a RADIUS test application for OsX, I finally got around to porting our old and creaky NAS test app to Darwin. Oh joy. Problems galore and rather than stick #error preprocessor statements here and there, I just needed to see what the output of gcc preprocessor looked like. I poked around seeking to answer the question: "How do I capture the gcc preprocessor output?" That was pointless (although I an found interesting paper on the negative affects of the C preprocessor on productivity).

I'd failed to find the right mojo earlier while digging around in the gcc man page, so I tried again. Adding an -E flag (which seems the obvious solution) didn't seem to do anything. Finally, I realized that -E and -o (and perhaps -c under some circumstances) are mutually exclusive. Pick one (or the other) and it works.

Assuming a compiler line for a particular file foo.c:

gcc -O -g -DNDEBUG -Wall -DDarwin -c foo.c -o foo.o

Substitute this:

gcc -O -g -DNDEBUG -Wall -DDarwin -c foo.c -E

The output data is useful, but not as useful as it could be; preprocessor level (e.g. macros, defines, etc.) substitution has already happened, but the file tagging is pretty weak and there isn't any whitespace collapsing, so you're on your own.

What surprised me most about this whole excursion was my difficulty finding an appropriate discussion. I just don't get it. I've always found getting the output of the preprocessor an essential part of porting. Either getting the preprocessor data is obvious to everyone (possible), or no one does it (which seems unthinkable).

Posted by Dave at August 21, 2004 10:50 PM
Comments

I doubt you still have this problem but...
gcc -E foo.c > [foo.i]

Posted by: Dylan on July 11, 2005 10:29 AM commLink

That's certainly the basic idea (and you'll note that I initially thought that would be the end of it). In practice, when dealing with complex code with a boatload of compilation flags, you'll need to do basically everything except spit out an object.

In general, you'll need to tweak the make files to perform -E instead of -o 'something'.

Posted by: Dave Ely on July 12, 2005 02:51 AM commLink