How to view the raw C / AVR code generated by IDE before compliation?

So I write my arduino code in the IDE, and with one click of a button, the compiled binary is whizzing down my USB cable to Arduinos flash. Simple!
However, sometimes I want to see the straight C code that sits behind my Arduino code in the libraries. The IDE must dump a .c file in some temporary location before it becomes hex and goes to my board.....how can I see this C file?

Cant you just look at the libraries your using. In their folder is a .h file and a .cpp file you can open them in a text editor or notepad2 is good. Sometimes you will need to to reconfigure them.

yes, that is one way of doing it, if you have a LOT of spare time.....also seems such a waste since the IDE generates a .c file anyway. There must be a way of getting a dump of this .c file.

I don't think it does create a .c file. I think it goes straight to intermediate code and then assembly language.

eriknyquist:
yes, that is one way of doing it, if you have a LOT of spare time

I don't understand why you think that the time taken is "a lot". The source code for the libraries you use is readily available under the Arduino directory (for the standard libraries) and under your sketches directory (for libraries that you have added).

If you want to see what your sketch looks like after the IDE has converted it from .ino to .cpp then you can turn on verbose output in the IDE options and then look for the message telling you where the IDE has placed your temporary files. I can't imagine many situations where that would be necessary, though.

For your sketch, the pre-processed C++ code will be in $TMP/sketchname.ino.cpp or $TMP/sketchname.cpp (depending on exactly which version of the IDE you are using, apparently.)
$TMP is some temporary directory with a weird name that Java picks for you; the easiest way to find it is to turn on the "verbose" compilation option in the preferences menu, do a "verify", and copy/paste.

Libraries are compile directly from their source code, which can be found in the distribution directory.

You're likely to be disappointed. There is actually very little pre-processing that goes on, and your sketch will look very much like the original. See also: Redirecting

What you will need to do, is compile your app using the IDE with a change to the preferences ( command line options, for ide 1.0.1 and above ), Or call GCC directly. There is a flag the compiler can use to output the code as a single huge file with all pre-processing expanded.

This can be useful, but remember all includes are expanded too so the file is generally enormous, however the sketch should be the last thing in the file.

I cannot remember the command line flag, but a quick google search using keywords like 'GCC compiler option' should prove useful.

peterH, the time taken is relative to the size of my arduino sketch and how many different library functions are used. In this case it would take me a couple of hours to trawl through the librarys and build a pure C file, not too long but even so I'd like to know how to do this in the future.
Yeah I tried the verbose output, since I tried it on my windows machine the temp files are in some folder that isn't there, (C:\Users\enyquist\AppData) . I'll try it with a linux distro.
pyro_65, arduino's 'preferences.txt' file is in this same elusive AppData folder, god I hate windows. Again I'll try this on my linux box, really shouldn't be that hard.....

I tried it with the IDE and it works, need \arduino\hardware\arduino\avr\platform.txt

modify
compiler.cpp.flags=-c -g -Os -w -fno-exceptions -ffunction-sections -fdata-sections -MMD

to

compiler.cpp.flags=-c -g -Os -w -fno-exceptions -ffunction-sections -fdata-sections -MMD -E

then compile, when the linker spews up, open the temporary compilation folder and open the .o files. That is your code expanded.

eriknyquist:
In this case it would take me a couple of hours to trawl through the librarys and build a pure C file

Why on Earth would you want to do that? The libraries consist of plain old C++ files and you have the source right there in front of you.

Your sketch goes through some subtle mangling to generate the final C++ file that is given to the compiler, but from a developers point of view this is basically just adding in some declarations and includes for you and doesn't change the main body of the code; it's pretty rare that you would need to see the generated C++ since it is almost identical to the .ino code you see in the IDE.

no practical reason, I'm simply interested in AVRs and I'd like to see which AVR registers are being modified. This will just make that a bit easier. I KNOW that these can be found in the .cpp and .h files but this means I won't have to sift through the whole thing, I can see only the registers that are actually being written in the compiled program

I'd like to see which AVR registers are being modified

Looking at the preprocessed output (from -E) will actually obscure this, compared to looking at the core/library. The C compiler doesn't deal with named AVR-registers at the low level; they all become rather obscure looking operations on pointers. For example, here is digitalWrite():

void digitalWrite(uint8_t pin, uint8_t val)
{
 uint8_t timer = ( (__extension__({ uint16_t __addr16 = (uint16_t)((uint16_t)(digital_pin_to_timer_PGM + (pin))); uint8_t __result; __asm__ ( "lpm %0, Z" "\n\t" : "=r" (__result) : "z" (__addr16) ); __result; })) );
 uint8_t bit = ( (__extension__({ uint16_t __addr16 = (uint16_t)((uint16_t)(digital_pin_to_bit_mask_PGM + (pin))); uint8_t __result; __asm__ ( "lpm %0, Z" "\n\t" : "=r" (__result) : "z" (__addr16) ); __result; })) );
 uint8_t port = ( (__extension__({ uint16_t __addr16 = (uint16_t)((uint16_t)(digital_pin_to_port_PGM + (pin))); uint8_t __result; __asm__ ( "lpm %0, Z" "\n\t" : "=r" (__result) : "z" (__addr16) ); __result; })) );
 volatile uint8_t *out;

 if (port == 0) return;
 if (timer != 0) turnOffPWM(timer);
 out = ( (volatile uint8_t *)( (__extension__({ uint16_t __addr16 = (uint16_t)((uint16_t)(port_to_output_PGM + (port))); uint16_t __result; __asm__ ( "lpm %A0, Z+" "\n\t" "lpm %B0, Z" "\n\t" : "=r" (__result), "=z" (__addr16) : "1" (__addr16) ); __result; }))) );

 uint8_t oldSREG = (*(volatile uint8_t *)((0x3F) + 0x20));
 __asm__ __volatile__ ("cli" ::);

 if (val == 0x0) {
  *out &= ~bit;
 } else {
  *out |= bit;
 }

 (*(volatile uint8_t *)((0x3F) + 0x20)) = oldSREG;
}

Are you sure you don't want to look at the assembly language produced? That's much more "concentrated", more stripped of extraneous garbage, and closer to actual AVR architecture stuff...

eriknyquist:
no practical reason, I'm simply interested in AVRs and I'd like to see which AVR registers are being modified. This will just make that a bit easier. I KNOW that these can be found in the .cpp and .h files but this means I won't have to sift through the whole thing, I can see only the registers that are actually being written in the compiled program

That's quite a bit different to viewing pre-processed code, sure the register macros are expanded to volatile pointer casts, but not quite what happens in the 'compiled program'

On windows to view the asm listing, type 'shell:sendto' into explorer, hit enter then copy the file I attached below in there.
You can then go into the IDE temp compile folder and right click on your sketch *.elf file then SendTo->AVR_ASM.bat

You will have to open the file in notepad and edit the path to the arduino directory.

But it will generate a text file containing the asm for your sketch.

AVR-ASM.bat (73 Bytes)

For example, consider a statement in your sketch like:PORTB = 0x12;
In the pre-processed C code (from -E), you would see:

  (*(volatile uint8_t *)((0x05) + 0x20)) = 0x12;

Which I claim is not very useful. The assembler output would contain:

100: 82 e1 ldi r24, 0x12 ; 18
102: 85 b9 out 0x05, r24 ; 5

The original source code is best.

Unfortunately, there is no way to get "partially pre-processed" code that might tell you something like:digitalWriteFast(13,1);turns intoPORTD |= 0x40;
Fortunately, the Arduino code doesn't have many of the sort of complex macros that would make that sort of thing more useful. digitalWrite() is a true function, and its source code is pretty understandable.

pyro_65, thanks for that batch file, I ran it on my .elf but I have a silly question...

where is the .asm file dumped? I can't find it anywhere...

my bad, it dumps it in the same Temp folder. Thanks again pyro_65