Implement proper build system

This commit is contained in:
2024-08-26 17:28:42 +02:00
parent 3dc1f54ebc
commit 35adae7c1f

123
Makefile
View File

@@ -4,34 +4,125 @@
# Makefile
# Written by Leon Krieg <info@madcow.dev>
# ==============================================================================
# GENERAL SETTINGS
# ==============================================================================
SRCDIR := src
BINDIR := bin
TMPDIR := $(BINDIR)/build
TARGET := $(BINDIR)/core.hex
ELFFILE := $(BINDIR)/core.elf
LOGFILE := $(BINDIR)/core.log
VERBOSE := false
ARCH := m32
FREQ := 8000000UL
MCU := atmega32a
ASP := usbasp
GCC := avr-gcc
CC := avr-gcc
LD := $(CC)
OBJCOPY := avr-objcopy
AVD := avrdude
RMF := rm -f
BINDIR := bin
ELFILE := $(BINDIR)/out.elf
TARGET := $(BINDIR)/core.hex
CFLAGS := -Os -std=c99 -Wall -Wextra -Werror
MKDIR := mkdir -p
RMR := rm -rf
CPPFLAGS := -DF_CPU=$(FREQ)
CFLAGS := -mmcu=$(MCU) -Os -std=c99 -Wall -Wextra -Werror
OCFLAGS := -j .text -j .data -O ihex
LDFLAGS := -mmcu=$(MCU)
LDLIBS :=
# ==============================================================================
# TARGET FILE LISTS (DERIVED FROM SOURCE TREE)
# ==============================================================================
PATHS := $(shell find "$(SRCDIR)" -type d -printf '%P ' 2>/dev/null)
FILES := $(shell find "$(SRCDIR)" -type f -name "*.c" -printf '%P ' 2>/dev/null)
TMPDIRS := $(BINDIR) $(TMPDIR) $(PATHS:%=$(TMPDIR)/%)
OBJECTS := $(FILES:%.c=$(TMPDIR)/%.o)
DEPENDS := $(FILES:%.c=$(TMPDIR)/%.d)
# ==============================================================================
# AUXILIARY TARGETS (AND FUSE SETTINGS)
# ==============================================================================
.PHONY: all
all: flash
.PHONY: flash
flash: $(TARGET)
$(AVD) -c $(ASP) -p $(ARCH) \
-U lfuse:w:0xff:m \
-U hfuse:w:0x99:m \
$(E) "[AVD] Flashing..."
$(Q) $(AVD) -l $(LOGFILE) \
-c $(ASP) -p $(ARCH) \
-U lfuse:w:0xff:m \
-U hfuse:w:0x99:m \
-U flash:w:$(TARGET)
$(TARGET): src/main.c
$(GCC) -o $(ELFILE) $(CFLAGS) $(CPPFLAGS) $^ -mmcu=$(MCU)
avr-objcopy -j .text -j .data -O ihex $(ELFILE) $@
avr-size --format=avr --mcu=$(MCU) $@
.PHONY: clean
clean:
$(RMF) $(TARGET)
$(RMF) $(ELFILE)
$(E) "[REM] $(TARGET)"
$(Q) $(RMR) $(TARGET)
$(E) "[REM] $(ELFFILE)"
$(Q) $(RMR) $(ELFFILE)
$(E) "[REM] $(LOGFILE)"
$(Q) $(RMR) $(LOGFILE)
$(E) "[REM] $(TMPDIR)"
$(Q) $(RMR) $(TMPDIR)
.PHONY: distclean
distclean: clean
$(E) "[REM] $(BINDIR)"
$(Q) $(RMR) $(BINDIR)
$(TMPDIRS):
$(E) "[DIR] $@"
$(Q) $(MKDIR) $@
# ==============================================================================
# PRIMARY BUILD TARGET AND PATTERN RULES
# ==============================================================================
# We must expand the prerequisite lists a second time to resolve path variable
# $(@D). This means folders can be set as explicit dependencies and created in
# the $TMPDIRS rule. This is better than relying on Make to honor the order of
# prerequisites for the primary target and we will not have to call mkdir for
# each build step preemptively.
.SECONDEXPANSION:
$(TARGET): $(ELFFILE) | $$(@D)
$(E) "[HEX] $@"
$(Q) $(OBJCOPY) $(OCFLAGS) $< $@
$(ELFFILE): $(OBJECTS) $(DEPENDS) | $$(@D)
$(E) "[ELF] $@"
$(Q) $(LD) -o $@ $(LDFLAGS) $(OBJECTS) $(LDLIBS)
$(TMPDIR)/%.o: $(SRCDIR)/%.c | $$(@D)
$(E) "[OBJ] $@"
$(Q) $(CC) -c -o $@ $(CFLAGS) $(CPPFLAGS) $<
$(TMPDIR)/%.d: $(SRCDIR)/%.c | $$(@D)
$(E) "[DEP] $@"
$(Q) $(CC) -c -o $@ $(CFLAGS) $(CPPFLAGS) -MM -MT $(@:.d=.o) $<
# ==============================================================================
# MAKE PREPROCESSOR INCLUDES AND CONDITIONALS
# ==============================================================================
# Load header dependency rules
include $(wildcard $(DEPENDS))
# Sanity check
ifeq ($(strip $(OBJECTS)),)
$(error No sources found in '$(SRCDIR)/')
endif
# Handle verbosity setting
ifneq ($(VERBOSE), false)
E = @true
else
E = @echo
Q = @
endif