Reputation: 4459
I have two files: assign1.c and ports.h.
FYI: I am using avr-gcc.
I built the following makefile, which I also use for another project (and other TARGET) where it works fine.
TARGET = assign2
LIB=
INCLUDE=ports.h
CFLAGS =-mmcu=atmega32 -Wall
CC = avr-gcc
SRC= $(TARGET).c
OBJ= $(SRC:.c=.o)
OBJCOPY = avr-objcopy
FORMAT = ihex
MSG_COMPILING = Compiling:
MSG_LINKING = Linking:
MSG_FLASH = Creating load file for flash:
all:elf hex
elf: $(TARGET).elf
hex: $(TARGET).hex
%.hex: %.elf
@echo $(MSG_FLASH) $@
@echo
$(OBJCOPY) -O $(FORMAT) -R .eeprom $< $@
$(RM) *.elf $(TARGET)
@echo
%.elf: $(OBJ) $(LIB)
@echo $(MSG_LINKING) $@
@echo
$(CC) $(CFLAGS) $^ -o $@
@echo
%.o: $(SRC) $(INCLUDE)
@echo $(MSG_COMPILING) $<
@echo
$(CC) $(CFLAGS) -c $<
@echo
.PHONY : clean
clean:
$(RM) *.o *.hex *.elf $(TARGET)
The terminal prints the following output.
C:\Project>make
Compiling: assign2.c
avr-gcc -mmcu=atmega32 -Wall -c assign2.c
In file included from assign2.c:8:
c:/winavr-20100110/lib/gcc/../../avr/include/util/delay.h:90:3: warning: #warnin
g "Compiler optimizations disabled; functions from <util/delay.h> won't work as
designed"
Linking: assign2.elf
avr-gcc -mmcu=atmega32 -Wall assign2.o -o assign2.elf
Compiling: assign2.c
avr-gcc -mmcu=atmega32 -Wall -c assign2.c
In file included from assign.c:8:
c:/winavr-20100110/lib/gcc/../../avr/include/util/delay.h:90:3: warning: #warnin
g "Compiler optimizations disabled; functions from <util/delay.h> won't work as
designed"
avr-gcc elf.o assign2.elf -o elf
avr-gcc: elf.o: No such file or directory
make: *** [elf] Error 1
rm assign2.o
C:\Project>
For some reason it seems to compile the first file, a second time and doing so crashes.
Can anyone correct me on my errors?
Upvotes: 0
Views: 920
Reputation: 101081
The problem is your pattern rules. You are writing pattern rules like this (after make expands the variables):
%.o: assign2.c ports.h
What this rule tells make is that ANY target it wants to build that matches the %.o
pattern, can be built by compiling assign2.c
. That's obviously not true: this rule build exactly one target: assign2.o
.
So make reads your makefile and wants to build a file named elf
. It sees that elf
depends on $(TARGET).elf
, so it builds that (that's the first compile and link, that works). Then make wants to build elf
itself. You haven't declared it to be .PHONY, so make assumes it might be a real target.
Make looks through its built-in rules to find one that will let it build elf
, and it finds a built-in rule: % : %.o
which it can use to compile a program from a .o
file with the same prefix. So now for target elf
make wants to try to build a file elf.o
. Oho! It sees there's a pattern rule that lets it build any .o
file based on the assign2.c
source file, so it runs that rule (that's the second compile) expecting it to build elf.o
... which it doesn't, obviously.
Then make runs the built-in link recipe, using elf.o
which doesn't exist, and fails.
The solution to your problem is two things:
First, you should always declare all your makefile targets that you don't actually want to build as .PHONY so make won't try to build them:
.PHONY: all elf hex
Second, you should never use pattern rules where the prerequisite is not also a pattern (this can be useful in certain very specific situations, but not in general). You should either change those pattern rules to explicit rules:
assign2.elf: $(OBJ) $(LIB)
...
$(OBJ): $(SRC) $(INCLUDE)
...
Or make them into full pattern rules by using the pattern in the prerequisites list as well:
%.elf : %.obj $(LIB)
...
%.o: %.c $(INCLUDE)
...
Upvotes: 3