You are not logged in.
In the past few days I've been playing with, what's supposed to be, my first useful had written Makefile. The only thing I'm not absolutely sure I'm doing right is dependencies on header files. Basically, what I'm trying to ask is how to make sure that make will notice a change in header file, compile the appropriate object file and relink anything that needs relinking.
I'll post a simplified Makefile that reflects my use case, but if anyone asks for the actual Makefile from my project I can post that too.
Top level directory structure:
bstaletic@localhost makefiletest % ls
libopencm3 test1 test2 generated.STM32F407VG.ld linker.ld.d main.bin main.c main.d main.elf main.map main.o make_def.mk Makefile
Directories test1 and test2:
test1:
Makefile test.c test.d test.h test.o
test2:
Makefile test.c test.d test.h test.o
Top level Makefile:
PROJDIR := ${HOME}/Temp/makefiletest/
BOARD := STM32F407VG
OBJ := main.o test1/test.o test2/test.o
main.bin: main.elf
arm-none-eabi-objcopy -Obinary $< $@
main.elf : generated.$(BOARD).ld $(OBJ)
$(CC) --static -nostartfiles -Tgenerated.$(BOARD).ld $(MFLAGS) -Wl,-Map=main.map -Wl,--gc-sections $(LINK_PATH) $(OBJ) $(LINK_LIB) $(LINK_GROUP) -o $@
generated.$(BOARD).ld :
$(CC) -E $(CFLAGS) -P -E ${PROJDIR}/libopencm3/ld/linker.ld.S > $@
flash: main.bin
st-link write $< 0x8000000
dodoc:
doxygen $(DOXYFILE)
include $(PROJDIR)/make_def.mk
.PHONY: dodoc flash
The sourced make_def.mk:
AR := arm-none-eabi-ar
CC := arm-none-eabi-gcc
CFLAGS := -Os -g -Wall -Wextra -pedantic -x c -std=c99 -mfloat-abi=hard -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -DSTM32F4 -DSTM32F407VG -DSTM32F4CCM -D_ROM_OFF=0x08000000 -D_ROM=1024K -D_RAM=128K -D_CCM=64K -D_CCM_OFF=0x10000000 -D_RAM_OFF=0x20000000 -fno-common -fdata-sections -MD -I${PROJDIR}/libopencm3/include
PROJDIR := ${HOME}/Temp/makefiletest
LINK_GROUP := -Wl,--start-group -lc -lgcc -lnosys -Wl,--end-group
LINK_PATH := -L${PROJDIR}/libopencm3/lib
LINK_LIB := -lopencm3_stm32f4
DOXYFILE := $(PROJDIR)/Doxyfile
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -rf *.o
rm -rf *.elf
rm -rf *.bin
rm -rf generated.*.ld
rm -rf *.map
rm -rf lib*.a
rm -rf *.d
-include *.d
.PHONY: clean
Every other Makefile in a subdirectory:
include $(PROJDIR)/make_def.mk
So I am passing '-MD' to gcc and it does create appropriate .d files with all the dependencies defined correctly. Are my Makefiles dealing with dependencies appropriately?
Another question I have: How do I make a rule that will clean every subdirectory, not just the one "make clean" has been run in? I could hack up something using something like "find", but I can't believe there's no elegant way of doing it.
Any other suggestions are welcome too.
Note: This is embedded project and only bare-metal programming is possible, that's why I did not bother with making anything a library. Maybe it's just me, but I don't see an advantage of making a bunch of static libraries over just using the produced object files.
Last edited by bstaletic (2016-11-03 22:10:11)
Offline
I've found the issue. The Makefile, as it is written in the post above, has dependancy resolution, but is only halfway working. That is because the "-include *.d" line in make_def.mk made make only see the *.d files in the directory the modified file resides. What is actually needed is to have all *.d file from the whole project included at once. After doing that, the dependancy resolution woked as expected. Now to just figure out a non-hackish way to include everything I should.
So the modified files look like this:
make_def.mk:
CC := arm-none-eabi-gcc
CFLAGS := -Os -g -Wall -Wextra -pedantic -x c -std=c99 -mfloat-abi=hard -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -DSTM32F4 -DSTM32F407VG -DSTM32F4CCM -D_ROM_OFF=0x08000000 -D_ROM=1024K -D_RAM=128K -D_CCM=64K -D_CCM_OFF=0x10000000 -D_RAM_OFF=0x20000000 -fno-common -fdata-sections -MD -MP -I${PROJDIR}/libopencm3/include -I${PROJDIR}
PROJDIR := ${HOME}/Temp/makefiletest
LINK_GROUP := -Wl,--start-group -lc -lgcc -lnosys -Wl,--end-group
LINK_PATH := -L${PROJDIR}/libopencm3/lib
LINK_LIB := -lopencm3_stm32f4
DOXYFILE := $(PROJDIR)/Doxyfile
DEPS := main.d test1/test.d test2/test.d
-include $(DEPS)
%.o: %.c
$(CC) $(CFLAGS) -c $< -o $@
clean:
rm -rf *.o
rm -rf *.elf
rm -rf *.bin
rm -rf generated.*.ld
rm -rf *.map
rm -rf lib*.a
rm -rf *.d
.PHONY: clean
Top level Makefile:
PROJDIR := ${HOME}/Temp/makefiletest/
DESTDIR := ${PROJDIR}/build/
BOARD := STM32F407VG
OBJ := main.o test1/test.o test2/test.o
${DESTDIR}main.bin: main.elf
arm-none-eabi-objcopy -Obinary $< $@
main.elf : generated.$(BOARD).ld $(OBJ)
$(CC) --static -nostartfiles -Tgenerated.$(BOARD).ld $(MFLAGS) -Wl,-Map=main.map -Wl,--gc-sections $(LINK_PATH) $(OBJ) $(LINK_LIB) $(LINK_GROUP) -o $@
generated.$(BOARD).ld :
$(CC) -E $(CFLAGS) -P -E ${PROJDIR}/libopencm3/ld/linker.ld.S > $@
flash: main.bin
st-link write $< 0x8000000
dodoc:
doxygen $(DOXYFILE)
include $(PROJDIR)/make_def.mk
.PHONY: dodoc flash
Rest of the Makefiles:
PROJDIR := ${HOME}/Temp/makefiletest
include $(PROJDIR)/make_def.mk
Offline
DEPS := $(OBJ:.o=.d)
might be slightly more reusable (for future-proofing updates)
And the "clean" target could also take advantage of reusing the variable(s) specifically meant to keep track of generated files. Which once again properly handles the issue of dealing with subdirectories.
Managing AUR repos The Right Way -- aurpublish (now a standalone tool)
Offline
That sounds like a good idea. And the clean target idea does seem neat. I'll see what I can do. Thanks for the suggestions.
Offline