Search code examples
makefilegnu-makeavr

Some implicit makefile?


I am trying to understand makefile. I took atmega168 bootloader's makefile and simplified it to this:

CC         = avr-gcc

override CFLAGS        = -g -Wall -Os -mmcu=atmega328p -DF_CPU=16000000L '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' -DBAUD_RATE=57600

atmega328: ATmegaBOOT_168_atmega328.hex

%.elf: ATmegaBOOT_168.o
    avr-gcc -g -Wall -Os -mmcu=atmega328p -DF_CPU=16000000L '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' -DBAUD_RATE=57600 -Wl,--section-start=.text=0x7800 -o $@ $< 

clean:
    rm -rf *.o *.elf *.lst *.map *.sym *.lss *.eep *.srec *.bin *.hex

%.hex: %.elf
    avr-objcopy -j .text -j .data -O ihex $< $@

When I ran $ make atmega328 I get:

avr-gcc -g -Wall -Os -mmcu=atmega328p -DF_CPU=16000000L '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' -DBAUD_RATE=57600   -c -o ATmegaBOOT_168.o ATmegaBOOT_168.c
avr-gcc -g -Wall -Os -mmcu=atmega328p -DF_CPU=16000000L '-DMAX_TIME_COUNT=F_CPU>>4' '-DNUM_LED_FLASHES=1' -DBAUD_RATE=57600 -Wl,--section-start=.text=0x7800 -o ATmegaBOOT_168_atmega328.elf ATmegaBOOT_168.o 
avr-objcopy -j .text -j .data -O ihex ATmegaBOOT_168_atmega328.elf ATmegaBOOT_168_atmega328.hex
rm ATmegaBOOT_168_atmega328.elf ATmegaBOOT_168.o

Why cannot I remove CC or CFLAGS?

I understand some basics of makefile. I read a lot on the internet, plus went through gnu manual, but I cannot understand the very first output with ATmegaBOOT_168.c. What/How has generated first command? Was there used some second makefile? If yes, how to find its location?

UPDATE: If I rename ATmegaBOOT_168.c to ATmegaBOOT_1681.c. Running $ make atmega328 gives:

make: *** No rule to make target 'ATmegaBOOT_168_atmega328.hex', needed by 'atmega328'.  Stop.

but the rule is present.


Solution

  • CC and CFLAGS are variables used in the built in implicit rules of GNU make. When you run make, it reads your makefile a bit like:

    1. No target given, so we'll make the first: atmega328. This requires a .hex file.
    2. The .hex file can be generated from a .elf file per the last rule.
    3. .elf files can be generated by the %.elf rule (which here looks like you've broken the pattern, as there's no % in the dependencies).
    4. There's no rule for .o in this file, so the default recipe $(CC) $(CPPFLAGS) $(CFLAGS) -c is used. Since a .c file is found, this rule is applicable and generates the first command. The rule could have been written (as shown in suffix rules):

      .c.o:
         $(CC) -c $(CFLAGS) $(CPPFLAGS) -o $@ $<
      
    5. Backtrack up this list, now that the source has been found, and run the commands.

    If the implicit rule variables are left unset, you will typically get programs built for your host system using cc.