Das Makefile habe ich in einem Unterverzeichnis foo/obj und die Quellen dann in foo, also keine komplizierte Projektstruktur. Wenn man Quellen und Objekte im gleichen Verzeichnis mischen will, wird's noch einfacher.

Code:
## Makefile targets 

# all           make hex and elf files
# clean         remove intermediate and binary files 
# reset         reset the target
# burn          upload program (firmware) to target
# burn-all      upload program (firmware) and persistent data (EEPROM) to target

# Generated files in the directory
# *.s: Assembler output of GCC (GNU AVR assembly as ASCII)
# *.o: Objects (elf32-avr)
# *.elf: final binary (elf32-avr)
# *.hex: final binary (Intel HEX)
# *.lst: Disassembly of *.elf (ASCII)
# *.map: map file (location info, ASCII)

# The project's base name to name hex- and elf-files and such
PRG				= eBook

# C sources that make up the project
SRC				= main.c vfd-put.c vfd.c ebook.c taster.c main.c timer.c

# we run on an AVR ATmega8
MCU_TARGET		= atmega8	

# You must change the Port and Progger to fit your hardware.
# siprog3 is home brew
AVRDUDE			= avrdude.exe -p $(MCU_TARGET) -P com1 -c siprog3 

OPTIMIZE		= -Os 
INCLUDES		= -I../include

DEFS			= -DF_CPU=8000000

CC				= avr-gcc -mmcu=$(MCU_TARGET)
LD             	= $(CC)
OBJCOPY        	= avr-objcopy
OBJDUMP        	= avr-objdump

# Targets dealing with C sources
.PHONY: all size lst text eeprom depend 

# clean targets
.PHONY: clean

# Targets that use avrdude
.PHONY: reset burn burn-all

CFLAGS			= -Wall $(OPTIMIZE) $(DEFS) $(INCLUDES) -Winline -fno-keep-inline-functions
LDFLAGS			= -Wl,-Map,$(PRG).map -Wl,-section-start=.eeprom=0x810001
ASMFLAGS		= -dp -save-temps -fverbose-asm

# object and assembler files. we build *.o out of *.s (not *.c)
OBJ				= $(patsubst %.c, %.o, $(SRC))
ASM				= $(patsubst %.c, %.s, $(SRC))

all: depend $(ASM) $(PRG).elf lst text eeprom

depend:
	$(CC) -MM  $(addprefix ../, $(SRC)) -mmcu=$(MCU_TARGET) $(DEFS) $(INCLUDES) |\
		sed -e 's/\.o:/.s:/' > .depend

size: 
	avr-size -x $(OBJ)
	@echo AVR $(MCU_TARGET) Memory Usage:
	@avr-size -C --mcu=$(MCU_TARGET) $(PRG).elf | grep -E '^(Data)|(Pro)'

$(PRG).elf: $(OBJ) 
	$(CC) $(LDFLAGS) -o $@ $^ $(LIBS)

-include .depend

%.s: ../%.c Makefile
	$(CC) -S $< -o $@ $(ASMFLAGS) $(CFLAGS) 

%.o: %.s
	$(CC) -x assembler $< -c -o $@ 

# Rules to clean up

clean:
	rm -f .depend $(wildcard *.o *.s *.i *.map *.lst *.elf *.hex *.map *~ ../*~)

# Rules to generate disassembly

lst: $(PRG).lst

%.lst: %.elf
	$(OBJDUMP) -h -S -j .data -j .eeprom -j .text $< > $@

# Rules for building the .text rom images

text: $(PRG).hex

%.hex: %.elf
	$(OBJCOPY) -j .text -j .data -O ihex $< $@

# Rules for building the .eeprom rom images

eeprom: $(PRG)_eeprom.hex

%_eeprom.hex: %.elf
	$(OBJCOPY) -j .eeprom --change-section-lma .eeprom=1 -O ihex $< $@

# Rules with avrdude
reset:
	$(AVRDUDE)

burn: 
	$(AVRDUDE) -V -U flash:w:"$(PRG).hex"

burn-all: 
	$(AVRDUDE) -V -U flash:w:"$(PRG).hex" -U eeprom:w:"$(PRG)_eeprom.hex"
Bei Fragen fragen. Wichtig ist, daß die Einrückungen TABs sind. Ein gscheiter Editor (zB emacs) sollte das erkennen bzw. anmeckern, falls nicht.