I took a makefile from a previous project that compiles programs for an avr microcontroller. I ran into some problems with what IO ports/data directional addresses I was setting which was causing the microcontroller to fault and reset. Because of this I wanted to add a step in my makefile to have it generate the pre-proccessed files and then compile from these preprocessed files. I'm not too familiar with how rules/dependencies work in makefiles so I've made, what I believe is, a simple mistake in my understanding of how makefiles work. My rules to make the preprocessed files/object files and eventually the .elf file must be wrong. Up until I added the steps which attempted to create the preprocessed files creating the .elf file work fine. What is my simple mistake/understanding in how rules/dependencies work in make?
How I view this working is when I ask to make all
it sees that it has a dependency of led.elf. To create this it has the dependency of the preprocessed files based on the line of $(OUTPUT).elf: $(PROCESS_FILES)
so it starts with this line. When I try to make all
however I get the error make: *** No rule to make target 'main.c', needed by 'main.e'. Stop.
and I don't understand why. Can anyone help my understanding in make files?
SRC_FILES=\
main.c led.c comm.c
#Object files
PROCESS_FILES=$(SRC_FILES:.c=.e)
OBJ_FILES=$(PROCESS_FILES:.e=.o)
#Directories where to look for include files
INC_DIRS=\
-I. \
#Output file name
OUTPUT=led
#Programmer and port
PROG=dragon_isp
PORT=usb
#Debugging host and port
DHOST=localhost
DPORT=6423
#Compiler related params
MCU=atmega2560
CC=avr-gcc
OBJCOPY=avr-objcopy
CFLAGS= -mcall-prologues -std=gnu99 -funsigned-char -funsigned bitfields \
-fpack-struct -fshort-enums -mmcu=$(MCU) -Wall -Wstrict-prototypes \
$(INC_DIRS)
#Optimization level
CFLAGS+=-Os
#Debug info
CFLAGS+=-gdwarf-2
#Generate hex file ready to upload
all: $(OUTPUT).elf
$(OBJCOPY) -R .eeprom -O ihex $(OUTPUT).elf $(OUTPUT).hex
#Link output files
$(OUTPUT).elf: $(PROCESS_FILES)
$(CC) $(CFLAGS) $(OBJ_FILES) -o $(OUTPUT).elf -Wl,-Map,$(OUTPUT).map
#Create object files
$(PROCESS_FILES): %.e : %.c
$(CC) -E $(CFLAGS) $< -o $@
$(OBJ_FILES): %.o : %.e
$(CC) -x $(CFLAGS) $< -o $@
#Create assembler file of a C source
%.s: %.c
$(CC) -S $(CFLAGS) $< -o $@
#Cleans all generated files
clean:
rm -f $(OBJ_FILES)
rm -f $(OUTPUT).elf
rm -f $(OUTPUT).hex
rm -f $(OUTPUT).map
Edit: I'm away from my computer now so I can't check this but thinking about my issue I'm starting to think I don't have a file named main.c in that directory. Even if I did I still think the makefile would not work correctly because I don't fully understand rules in makefiles.
My error was coming from the fact that I did not have a main.c
file in my directory. Make sure you backup files when you're messing with the OBJ_FILES or similar variable and have a line that will delete whatever is in that variable upon a make clean
.
As for the rules, I had to make one small fix to achieve what I wanted. I changed
$(OUTPUT).elf: $(PROCESS_FILES)
$(CC) $(CFLAGS) $(OBJ_FILES) -o $(OUTPUT).elf -Wl,-Map,$(OUTPUT).map
to
$(OUTPUT).elf: $(OBJ_FILES)
$(CC) $(CFLAGS) $(OBJ_FILES) -o $(OUTPUT).elf -Wl,-Map,$(OUTPUT).map
This then sees it needs the object files which in turn needs the preprocessed files.
Edit: I also changed OBJ_FILES=$(PROCESS_FILES:.e=.o)
to OBJ_FILES=$(SRC_FILES:.c=.o)
. I also added $(PROCESS_FILES)
to $(OUTPUT).elf: $(OBJ_FILES)
so the rule would generate both the preprocessed files and object files independently. I had to change $(OBJ_FILES): %.o : %.e
to $(OBJ_FILES): %.o : %.c
to make this work.