Some engineers love to do coding in macros. The rest of us would like to break their fingers. This command will run the file through the pre-processor, expanding all macros, but retaining all comments. Stick a comment like "LOOK HERE" and search for that so you reduce the amount of time you spend looking for the offending code.

Some engineers love to do coding in macros. The rest of us would like to break their fingers. This command will run the file through the pre-processor, expanding all macros, but retaining all comments. Stick a comment like "LOOK HERE" and search for that so you reduce the amount of time you spend looking for the offending code.

+

+

=== Pre-Process, Retain Defines/Macros ===

+

+

<pre>

+

gcc -dD -E <file-name.c> -o file

+

</pre>

+

+

Just like the previous example, but perhaps you're trying to trace the macro define mess.

What's Here, Why You Should Care

A collection of tips useful to those doing embedded development. Accumulated over several years of doing project work, helping other engineers, untangling projects for customers and feedback from several CELF presentations related to this topic.

Tips

View Compilation Plan

gcc -### <the rest of your command line goes here>

The GCC you run is a driver program for a bunch of other programs. With this parameter, gcc will produce (but not actually execute) the commands it would have used to accomplish the task you asked it to do. This way, you can see the gory details of what's going on behind the scenes. What library is being used? What is -mcpu set to? It's all there.

You can pipe this output to a file and execute that to compile a program, making it easy to experiment with tweaks to the linker or assembler.

Pre-Process, Retain Comments

gcc -C -E <file-name.c> -o file

Some engineers love to do coding in macros. The rest of us would like to break their fingers. This command will run the file through the pre-processor, expanding all macros, but retaining all comments. Stick a comment like "LOOK HERE" and search for that so you reduce the amount of time you spend looking for the offending code.

Pre-Process, Retain Defines/Macros

gcc -dD -E <file-name.c> -o file

Just like the previous example, but perhaps you're trying to trace the macro define mess.

See what Files the Linker is Using

gcc -Wl,-t <parameters>

Displays what files the linker opens in what order. When looking in archive files, the archive file is displayed in para theses, followed by the file in the archive. Very handy when working through a legacy project that depends on files linking in a certain order that suddenly breaks because of a small (probably viewed as not noteworthy) change in a makefile somewhere.

Print Pre-defined Macros

gcc -E -dM - < /dev/null | cut -c 9- | sort

Very handy when porting code. Lets you know if your target processor has some missing defines or if something is different (line __INT_MAX__) that can have interesting effects on your project. Diff the output from the old to the new compiler so you can easily see the differences, makes it easy to spot problems before getting started.

Mixed Assembler and Source Output

gcc -g somefile.c -o somefile
objdump -S somefile

Prints out each line in the program and the corresponding assembly code. Very handy when you're trying to see that the processor is generating the correct code, with the instructions you're expecting. You can also see the effects of optimization, but would recommend doing this for a small amount of code because when the optimization level is high, there's a much lower relationship between line of code and generated assembler.

Specify Language

gcc -x c a-c-source-file.with-a-non-standard-extension -o test.out

Great for legacy projects where where the file extensions don't match with GCC's expectations, while less of a problem since many projects got their start with GCC, this still is an issue with long-running projects that years back, used some other compiler. This stays in effect for the following file on the command line.

List Include File Dependencies

There's a whole family of things around -M. These produce a rule that could be used in a make file, with the included files as dependencies.

gcc -M <file name>

This shows you all includes, even those on the system path. Useful if you're doing porting work or validating if your compiler is working as expected and getting the files from the right place. You'll see something like this for a basic hello world program

Like -M, but no system files. Great to see if your project is configured and working as expected.

gcc -M -MG <file name>

The prior -M and -MM commands will stop if header files can be located. The parameter -MG will just produce the dependency list with the missing file. Engineers that have projects that generate header files as part of the build find -MM very handy.

gcc -M -MT '<target>' <file name>

By default, the target will be the <file name>.o This command will make the default the value of <target>.

If the command was

gcc -M -MT '$(target)' hello.c

You would see

$(target): hello.c

Symbol Trace

gcc -Wl,-y,printf hello.c

This is very handy when you want to understand the linker is finding a definition of a symbol. Some projects have name collisions or link order dependencies. This lets you see precisely what the linker is doing.

The reference is in a temporary file created during the compilation process. If you were linking several object files together explicitly, you would see the name of the object file where printf was referenced.

Saving temporary files

gcc -save-temps hello.c

The compilers temporary files are saved. This is often invaluable dealing with complicated makefiles to peek at the preprocessed output without having to figure out how to do a -E option by hand.