I have a makefile that used http://make.mad-scientist.net as a resource. The build process works but everything is being rebuild each time. If I run make --debug it says that the d dependency file was not found so it is regenerated.
When I look in my output folder, there is only one .d file which no filename, just .d. It looks like this file is appended during the build as the file size increases during a build.
This us using GNU Arm Embedded Toolchain 10 2021.10.
Here is the makefile, stripped down to minimal operation. The "project" has 6 or so c files and 4 or 5 header files across several folders to mimic a real project. The build artifacts are placed in a build folder and the object files + dependency files are in a obj folder under build.
###################### PATH SETUP ###############################################
## Setup common paths before importing project specific makefile
PLATFORM := $(PLATFORM_NAME)
FAMILY := PG22
TARGET := EFM32PG22C200F512IM40
################################ PROJECT DEFINES ########################################################
# Let's setup the initial C_DEF variable with any build time defines
# Let the port specific makefile append anything specific
C_DEF := -DPLATFORM_$(PLATFORM) -DUSE_RTT_FOR_DEBUGGING=1 -D$(TARGET) -DFAMILY_$(FAMILY) -DNO_HFXO -D__STARTUP_CLEAR_BSS -DSL_TRUSTZONE_NONSECURE
BUILD_DIR := build
OBJ_DIR := $(BUILD_DIR)/$(PLATFORM)/obj
BIN_DIR := $(BUILD_DIR)/$(PLATFORM)
SCRIPTS_DIR := .scripts
MODULES_DIR := modules
PROJ_HAL_DIR := Ports/$(PLATFORM)/HAL
# For organizational purposes, lets capture all of the submodule paths
MODULE_DIRS := $(MODULES_DIR)/submod-hal_generic
EFM32PG22_CONFIG_DIR = Ports/$(PLATFORM)/config
$(PLATFORM)_LINKER := $(EFM32PG22_CONFIG_DIR)/linker.ld
################################ SOURCE PATHS ########################################################
# We need to explicably list source directory paths
SOURCE_DIRS := application/src $(MODULE_DIRS) Ports/$(PLATFORM)/config
################################ INCLUDE PATHS ########################################################
# We need to explicably list source directory paths.
# Just include the general generic paths here and let the port specific makefile add its own paths as needed
# We already captured the paths above so just use a loop to build the include variable
MODULES_INCLUDES := $(foreach dir,$(MODULE_DIRS),-I$(dir))
INCLUDE_DIRS := -Iapplication/src \
-IPorts/$(PLATFORM) \
-IPorts/$(PLATFORM)/config \
-I$(PROJ_HAL_DIR) \
$(MODULES_INCLUDES)
################################ C FILE LIST GENERATION #######################################################
# Time for more automagical operations. Instead of listing all the filenames manually, let's just use
# make features to generate the list.
# There is no mechanism to ignore files.
CFILES := $(foreach dir,$(SOURCE_DIRS),$(notdir $(wildcard $(dir)/*.c)))
############################### SOURCE EXCLUSIONS ###############################################################
# C FILE LIST GENERATION will collect all source files in provide paths which won't work for some submodules
# who have test files not meant for normal compilation for the MCU project.
EXCLUSIONS := checksums_unit_tests.c cyclic_fifo_queue_test.c
CFILES := $(filter-out $(EXCLUSIONS), $(CFILES))
CC_$(PLATFORM) := arm-none-eabi-gcc.exe \
-std=c99 \
-Og \
-Wall \
-Wextra \
-pedantic \
-ffunction-sections \
-fdata-sections \
-finline-functions \
-mcpu=cortex-m33 \
-mthumb \
-g3 \
-gdwarf-2 \
-Wno-format \
-fno-common \
-ffreestanding \
-fno-builtin \
-nostartfiles \
-fstack-usage \
-MD
CC := $(CC_$(PLATFORM))
# This code has multiple intention fall-throughs in switch statements that generate warnings b/c of -Wall option. Let's just supress fallthrough warnings in general.
CC += -Wno-implicit-fallthrough
# These warnings are just plain annoying and serve no purpose.
CC += -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-function -Wno-unused-parameter
################################ OBJECT FILE GENERATION########################################################
# Time for more automagical operations. Instead of relisting all the filenames as objects, let's just use
# make features to generate the list. Insert $(OBJ_DIR) to each output file name so the output files are generated in the rigth
# location.
ALL_OBJECT_FILES := $(patsubst %.c,$(OBJ_DIR)/%.o,$(CFILES))
################################ SECRET SAUCE #################################################################
# Use vpath to tell make to look in these directories for dependencies.
vpath %.c $(SOURCE_DIRS)
################################ TARGETS #####################################################################
LINKER := $($(PLATFORM)_LINKER)
LDFLAGS := -Wl,--gc-sections -T"$(LINKER)" -Wl,-L$(OBJ_DIR) -Wl,--start-group $(ALL_OBJECT_FILES) -Wl,--end-group -Wl,-Map,$(BIN_DIR)/$(FILENAME).map -Wl,--print-memory-usage
all: $(BIN_DIR)/$(FILENAME).srec $(BIN_DIR)/$(FILENAME).bin
createdirs:
$(info "Creating Directories")
mkdir -p $(BUILD_DIR)
mkdir -p $(BIN_DIR)
mkdir -p $(OBJ_DIR)
$(BIN_DIR)/$(FILENAME).srec: createdirs $(BIN_DIR)/$(FILENAME).elf
arm-none-eabi-objcopy -O srec $(BIN_DIR)/$(FILENAME).elf $(BIN_DIR)/$(FILENAME).srec
$(BIN_DIR)/$(FILENAME).bin: $(BIN_DIR)/$(FILENAME).elf
arm-none-eabi-objcopy -O binary $(BIN_DIR)/$(FILENAME).elf $(BIN_DIR)/$(FILENAME).bin
$(BIN_DIR)/$(FILENAME).elf: $(ALL_OBJECT_FILES)
$(CC) $(LDFLAGS) \
--specs=nano.specs \
--specs=nosys.specs \
-o $(BIN_DIR)/$(FILENAME).elf
arm-none-eabi-objdump -S $(BIN_DIR)/$(FILENAME).elf > $(BIN_DIR)/$(FILENAME).lst
.PHONY: clean all
clean:
rm -rf $(BUILD_DIR)
rm -f *.o
rm -f *.su
################################ RECIPES #####################################################################
# Auto-Dependency Generation
# Sources:
# http://make.mad-scientist.net/papers/advanced-auto-dependency-generation
# http://www.math.utah.edu/docs/info/make_4.html
# https://stackoverflow.com/questions/4036191/sources-from-subdirectories-in-makefile
# The basic idea is that this magical incantation coerces GCC to output a .d
# dependency file for each .c file (therefore this method only works with GCC).
# Those dependency files are then included back into this makefile and magically
# used in the right magical places using magical nonsense line noise syntax.
# Where we want to put the .d dependency files.
DEPDIR := $(OBJ_DIR)
# Linux nerd nonsense that coerces GCC into generating .d dependency files.
#
# -MT $@ sets the name of the target in the generated dependency file.
# -MMD generates dependency information as a side-effect of compilation,
# not instead of compilation, whatever the heck that means. This version
# omits system headers from the generated dependencies: if you prefer to
# preserve system headers as prerequisites, use -MD.
# -MP adds a target for each prerequisite in the list, to avoid errors when deleting files.
# -MF $(DEPDIR)/$*.d writes the generated dependency file $(DEPDIR)/$*.d.
DEPFLAGS := -MT $@ -MMD -MP -MF $(DEPDIR)/$*.d
# This is the main invocation of GCC. Why this is all stored in a variable that
# looks like the name of a .c file, I have no idea.
COMPILE.c := $(CC) $(C_DEF) $(DEPFLAGS) $(INCLUDE_DIRS) -c
# Create the generic recipe. Note there are two recipes. The first one is blank and deletes anything that is there by default.
#
# $(DEPDIR)/%.d declares the generated dependency file as a prerequisite of the
# target, so that if it’s missing the target will be rebuilt.
# | $(DEPDIR) declares the dependency directory as an order-only prerequisite of
# the target (whatever the heck that nonsense means), so that it
# will be created when needed. Basically, I have no clue what this does.
$(OBJ_DIR)/%.o: %.c
$(OBJ_DIR)/%.o: %.c $(DEPDIR)/%.d | $(DEPDIR)
$(COMPILE.c) $< -o $@
$(DEPDIR): ; @mkdir -p $@
# Some absolute nonsense line noise syntax to generate a list of all the
# dependency files that could exist.
DEPFILES := $(CFILES:%.c=$(DEPDIR)/%.d)
# Mention each dependency file as a target, so that make won’t fail if the file doesn’t exist.
$(DEPFILES):
# Include all dependency files which exist, to include the relevant targets.
# See https://www.gnu.org/software/make/manual/html_node/Wildcard-Function.html for wildcard function documentation
include $(wildcard $(DEPFILES))
Here is a snapshot of the build output using -debug. The command line command for make is: make.exe -j16 --debug --makefile=makefile FILENAME=test PLATFORM_NAME=EFM32PG22
C:\Users\xyz\Desktop\TEST>make.exe -j16 --debug --makefile=makefile FILENAME=test PLATFORM_NAME=EFM32PG22
GNU Make 3.82.90
Built for i686-pc-mingw32
Copyright (C) 1988-2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Reading makefiles...
Updating goal targets....
File 'all' does not exist.
File 'createdirs' does not exist.
Must remake target 'createdirs'.
"Creating Directories"
mkdir -p build
File 'build/EFM32PG22/obj/file1.d' does not exist.
Must remake target 'build/EFM32PG22/obj/file1.d'.
Successfully remade target file 'build/EFM32PG22/obj/file1.d'.
Prerequisite 'build/EFM32PG22/obj/file1.d' of target 'build/EFM32PG22/obj/file1.o' does not exist.
Must remake target 'build/EFM32PG22/obj/file1.o'.
arm-none-eabi-gcc.exe -std=c99 -Og -Wall -Wextra -pedantic -ffunction-sections -fdata-sections -finline-functions -mcpu=cortex-m33 -mthumb -g3 -gdwarf-2 -Wno-format -fno-common -ffreestanding -fno-builtin -nostartfiles -fstack-usage -MD -Wno-implicit-fallthrough -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-function -Wno-unused-parameter -DPLATFORM_EFM32PG22 -DUSE_RTT_FOR_DEBUGGING=1 -DEFM32PG22C200F512IM40 -DFAMILY_PG22 -DNO_HFXO -D__STARTUP_CLEAR_BSS -DSL_TRUSTZONE_NONSECURE -MT -MMD -MP -MF build/EFM32PG22/obj/.d -Iapplication/src -IPorts/EFM32PG22 -IPorts/EFM32PG22/config -IPorts/EFM32PG22/HAL -Imodules/submod-hal_generic -c application/src/file1.c -o build/EFM32PG22/obj/file1.o
File 'build/EFM32PG22/obj/main.d' does not exist.
Must remake target 'build/EFM32PG22/obj/main.d'.
Successfully remade target file 'build/EFM32PG22/obj/main.d'.
Prerequisite 'build/EFM32PG22/obj/main.d' of target 'build/EFM32PG22/obj/main.o' does not exist.
Must remake target 'build/EFM32PG22/obj/main.o'.
mkdir -p build/EFM32PG22
arm-none-eabi-gcc.exe -std=c99 -Og -Wall -Wextra -pedantic -ffunction-sections -fdata-sections -finline-functions -mcpu=cortex-m33 -mthumb -g3 -gdwarf-2 -Wno-format -fno-common -ffreestanding -fno-builtin -nostartfiles -fstack-usage -MD -Wno-implicit-fallthrough -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-function -Wno-unused-parameter -DPLATFORM_EFM32PG22 -DUSE_RTT_FOR_DEBUGGING=1 -DEFM32PG22C200F512IM40 -DFAMILY_PG22 -DNO_HFXO -D__STARTUP_CLEAR_BSS -DSL_TRUSTZONE_NONSECURE -MT -MMD -MP -MF build/EFM32PG22/obj/.d -Iapplication/src -IPorts/EFM32PG22 -IPorts/EFM32PG22/config -IPorts/EFM32PG22/HAL -Imodules/submod-hal_generic -c application/src/main.c -o build/EFM32PG22/obj/main.o
File 'build/EFM32PG22/obj/file2.d' does not exist.
Must remake target 'build/EFM32PG22/obj/file2.d'.
Successfully remade target file 'build/EFM32PG22/obj/file2.d'.
Prerequisite 'build/EFM32PG22/obj/file2.d' of target 'build/EFM32PG22/obj/file2.o' does not exist.
Must remake target 'build/EFM32PG22/obj/file2.o'.
mkdir -p build/EFM32PG22/obj
arm-none-eabi-gcc.exe -std=c99 -Og -Wall -Wextra -pedantic -ffunction-sections -fdata-sections -finline-functions -mcpu=cortex-m33 -mthumb -g3 -gdwarf-2 -Wno-format -fno-common -ffreestanding -fno-builtin -nostartfiles -fstack-usage -MD -Wno-implicit-fallthrough -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-function -Wno-unused-parameter -DPLATFORM_EFM32PG22 -DUSE_RTT_FOR_DEBUGGING=1 -DEFM32PG22C200F512IM40 -DFAMILY_PG22 -DNO_HFXO -D__STARTUP_CLEAR_BSS -DSL_TRUSTZONE_NONSECURE -MT -MMD -MP -MF build/EFM32PG22/obj/.d -Iapplication/src -IPorts/EFM32PG22 -IPorts/EFM32PG22/config -IPorts/EFM32PG22/HAL -Imodules/submod-hal_generic -c application/src/file2.c -o build/EFM32PG22/obj/file2.o
File 'build/EFM32PG22/obj/file4.d' does not exist.
Must remake target 'build/EFM32PG22/obj/file4.d'.
Successfully remade target file 'build/EFM32PG22/obj/file4.d'.
Prerequisite 'build/EFM32PG22/obj/file4.d' of target 'build/EFM32PG22/obj/file4.o' does not exist.
Must remake target 'build/EFM32PG22/obj/file4.o'.
arm-none-eabi-gcc.exe -std=c99 -Og -Wall -Wextra -pedantic -ffunction-sections -fdata-sections -finline-functions -mcpu=cortex-m33 -mthumb -g3 -gdwarf-2 -Wno-format -fno-common -ffreestanding -fno-builtin -nostartfiles -fstack-usage -MD -Wno-implicit-fallthrough -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-function -Wno-unused-parameter -DPLATFORM_EFM32PG22 -DUSE_RTT_FOR_DEBUGGING=1 -DEFM32PG22C200F512IM40 -DFAMILY_PG22 -DNO_HFXO -D__STARTUP_CLEAR_BSS -DSL_TRUSTZONE_NONSECURE -MT -MMD -MP -MF build/EFM32PG22/obj/.d -Iapplication/src -IPorts/EFM32PG22 -IPorts/EFM32PG22/config -IPorts/EFM32PG22/HAL -Imodules/submod-hal_generic -c modules/submod-hal_generic/file4.c -o build/EFM32PG22/obj/file4.o
File 'build/EFM32PG22/obj/startup_efm32pg22.d' does not exist.
Must remake target 'build/EFM32PG22/obj/startup_efm32pg22.d'.
Successfully remade target file 'build/EFM32PG22/obj/startup_efm32pg22.d'.
Prerequisite 'build/EFM32PG22/obj/startup_efm32pg22.d' of target 'build/EFM32PG22/obj/startup_efm32pg22.o' does not exist.
Must remake target 'build/EFM32PG22/obj/startup_efm32pg22.o'.
arm-none-eabi-gcc.exe -std=c99 -Og -Wall -Wextra -pedantic -ffunction-sections -fdata-sections -finline-functions -mcpu=cortex-m33 -mthumb -g3 -gdwarf-2 -Wno-format -fno-common -ffreestanding -fno-builtin -nostartfiles -fstack-usage -MD -Wno-implicit-fallthrough -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-function -Wno-unused-parameter -DPLATFORM_EFM32PG22 -DUSE_RTT_FOR_DEBUGGING=1 -DEFM32PG22C200F512IM40 -DFAMILY_PG22 -DNO_HFXO -D__STARTUP_CLEAR_BSS -DSL_TRUSTZONE_NONSECURE -MT -MMD -MP -MF build/EFM32PG22/obj/.d -Iapplication/src -IPorts/EFM32PG22 -IPorts/EFM32PG22/config -IPorts/EFM32PG22/HAL -Imodules/submod-hal_generic -c Ports/EFM32PG22/config/startup_efm32pg22.c -o build/EFM32PG22/obj/startup_efm32pg22.o
File 'build/EFM32PG22/obj/file3.d' does not exist.
Must remake target 'build/EFM32PG22/obj/file3.d'.
Successfully remade target file 'build/EFM32PG22/obj/file3.d'.
Prerequisite 'build/EFM32PG22/obj/file3.d' of target 'build/EFM32PG22/obj/file3.o' does not exist.
Must remake target 'build/EFM32PG22/obj/file3.o'.
arm-none-eabi-gcc.exe -std=c99 -Og -Wall -Wextra -pedantic -ffunction-sections -fdata-sections -finline-functions -mcpu=cortex-m33 -mthumb -g3 -gdwarf-2 -Wno-format -fno-common -ffreestanding -fno-builtin -nostartfiles -fstack-usage -MD -Wno-implicit-fallthrough -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-function -Wno-unused-parameter -DPLATFORM_EFM32PG22 -DUSE_RTT_FOR_DEBUGGING=1 -DEFM32PG22C200F512IM40 -DFAMILY_PG22 -DNO_HFXO -D__STARTUP_CLEAR_BSS -DSL_TRUSTZONE_NONSECURE -MT -MMD -MP -MF build/EFM32PG22/obj/.d -Iapplication/src -IPorts/EFM32PG22 -IPorts/EFM32PG22/config -IPorts/EFM32PG22/HAL -Imodules/submod-hal_generic -c Ports/EFM32PG22/config/file3.c -o build/EFM32PG22/obj/file3.o
File 'all' does not exist.
File 'all' does not exist.
File 'all' does not exist.
File 'all' does not exist.
Prerequisite 'build/EFM32PG22/obj/file1.o' is newer than target 'build/EFM32PG22/test.elf'.
Prerequisite 'build/EFM32PG22/obj/main.o' is newer than target 'build/EFM32PG22/test.elf'.
Prerequisite 'build/EFM32PG22/obj/file2.o' is newer than target 'build/EFM32PG22/test.elf'.
Prerequisite 'build/EFM32PG22/obj/file4.o' is newer than target 'build/EFM32PG22/test.elf'.
Prerequisite 'build/EFM32PG22/obj/startup_efm32pg22.o' is newer than target 'build/EFM32PG22/test.elf'.
Prerequisite 'build/EFM32PG22/obj/file3.o' is newer than target 'build/EFM32PG22/test.elf'.
Must remake target 'build/EFM32PG22/test.elf'.
arm-none-eabi-gcc.exe -std=c99 -Og -Wall -Wextra -pedantic -ffunction-sections -fdata-sections -finline-functions -mcpu=cortex-m33 -mthumb -g3 -gdwarf-2 -Wno-format -fno-common -ffreestanding -fno-builtin -nostartfiles -fstack-usage -MD -Wno-implicit-fallthrough -Wno-unused-variable -Wno-unused-but-set-variable -Wno-unused-function -Wno-unused-parameter -Wl,--gc-sections -T"Ports/EFM32PG22/config/linker.ld" -Wl,-Lbuild/EFM32PG22/obj -Wl,--start-group build/EFM32PG22/obj/file1.o build/EFM32PG22/obj/main.o build/EFM32PG22/obj/file2.o build/EFM32PG22/obj/file4.o build/EFM32PG22/obj/startup_efm32pg22.o build/EFM32PG22/obj/file3.o -Wl,--end-group -Wl,-Map,build/EFM32PG22/test.map -Wl,--print-memory-usage \
--specs=nano.specs \
--specs=nosys.specs \
-o build/EFM32PG22/test.elf
Memory region Used Size Region Size %age Used
FLASH: 96 B 112 KB 0.08%
NV_STORAGE: 0 GB 16 KB 0.00%
RAM: 32 KB 32 KB 100.00%
arm-none-eabi-objdump -S build/EFM32PG22/test.elf > build/EFM32PG22/test.lst
File 'all' does not exist.
Prerequisite 'createdirs' of target 'build/EFM32PG22/test.srec' does not exist.
Prerequisite 'build/EFM32PG22/test.elf' is newer than target 'build/EFM32PG22/test.srec'.
Must remake target 'build/EFM32PG22/test.srec'.
arm-none-eabi-objcopy -O srec build/EFM32PG22/test.elf build/EFM32PG22/test.srec
Prerequisite 'build/EFM32PG22/test.elf' is newer than target 'build/EFM32PG22/test.bin'.
Must remake target 'build/EFM32PG22/test.bin'.
arm-none-eabi-objcopy -O binary build/EFM32PG22/test.elf build/EFM32PG22/test.bin
File 'all' does not exist.
File 'all' does not exist.
Must remake target 'all'.
Successfully remade target file 'all'.
Output object folder