Fix "duplicate rules" error & polish Makefile

This commit is contained in:
ISSOtm
2019-04-28 19:36:07 +02:00
parent 492d8fd473
commit ecb895c97a

112
Makefile
View File

@@ -1,10 +1,14 @@
.SUFFIXES: .SUFFIXES:
.DEFAULTTARGET: all .DEFAULT_GOAL := all
include Makefile.conf
################################################
# #
# CONSTANT DEFINITIONS #
# #
################################################
# Directory constants # Directory constants
SRCDIR = src SRCDIR = src
@@ -12,49 +16,64 @@ BINDIR = bin
OBJDIR = obj OBJDIR = obj
DEPSDIR = deps DEPSDIR = deps
ROMFILE = $(BINDIR)/$(ROMName).$(ROMExt)
# Program constants # Program constants
RGBASM = rgbasm RGBASM = rgbasm
RGBLINK = rgblink RGBLINK = rgblink
RGBFIX = rgbfix RGBFIX = rgbfix
MKDIR = $(shell which mkdir) MKDIR = $(shell which mkdir)
ROMFile = $(BINDIR)/$(ROMName).$(ROMExt)
# Project-specific configuration
include Makefile.conf
# Argument constants # Argument constants
ASFLAGS += -E -h -i $(SRCDIR)/ -i $(SRCDIR)/constants/ -i $(SRCDIR)/macros/ -p $(FillValue) ASFLAGS += -E -h -i $(SRCDIR)/ -i $(SRCDIR)/constants/ -i $(SRCDIR)/macros/ -p $(FillValue)
LDFLAGS += -p $(FillValue) LDFLAGS += -d -p $(FillValue)
FXFLAGS += -jv -i $(GameID) -k $(NewLicensee) -l $(OldLicensee) -m $(MBCType) -n $(ROMVersion) -p $(FillValue) -r $(SRAMSize) -t $(GameTitle) FXFLAGS += -j -f lh -i $(GameID) -k $(NewLicensee) -l $(OldLicensee) -m $(MBCType) -n $(ROMVersion) -p $(FillValue) -r $(SRAMSize) -t $(GameTitle)
# The list of "root" ASM files that RGBASM will be invoked on # The list of "root" ASM files that RGBASM will be invoked on
ASMFILES := $(wildcard $(SRCDIR)/*.asm) ASMFILES := $(wildcard $(SRCDIR)/*.asm)
# `all` (Default target): build the ROM ################################################
.PHONY: all # #
all: $(ROMFILE) # RESOURCE FILES #
# #
# `clean`: Clean temp and bin files ################################################
.PHONY: clean
CLEANTARGETS := $(BINDIR) $(DEPSDIR) $(OBJDIR) $(SRCDIR)/res/build.date dummy # The list of things that must be cleared; expanded by the resource Makefiles
clean:
-rm -rf $(CLEANTARGETS)
# `rebuild`: Build everything from scratch
.PHONY: rebuild
rebuild:
$(MAKE) clean
$(MAKE) all
# Define how to compress files (same recipe for any file) # Define how to compress files (same recipe for any file)
%.pb16: % %.pb16: %
src/tools/pb16.py $< $@ src/tools/pb16.py $< $@
CLEANTARGETS := $(BINDIR) $(DEPSDIR) $(OBJDIR) dummy # The list of things that must be cleared; expanded by the resource Makefiles
INITTARGETS :=
# Include all resource Makefiles # Include all resource Makefiles
# This must be done before we include `$(DEPSDIR)/all` otherwise `dummy` has no prereqs
include $(wildcard $(SRCDIR)/res/*/Makefile) include $(wildcard $(SRCDIR)/res/*/Makefile)
# `all` (Default target): build the ROM
all: $(ROMFile)
.PHONY: all
# `clean`: Clean temp and bin files
clean:
-rm -rf $(CLEANTARGETS)
.PHONY: clean
# `rebuild`: Build everything from scratch
# It's important to do these two in order if we're using more than one job
rebuild:
$(MAKE) clean
$(MAKE) all
.PHONY: rebuild
# `dummy` is a dummy target to build the resource files necessary for RGBASM to not fail on compilation # `dummy` is a dummy target to build the resource files necessary for RGBASM to not fail on compilation
# It's made an actual file to avoid an infinite compilation loop # It's made an actual file to avoid an infinite compilation loop
# INITTARGETS is defined by the resource Makefiles # INITTARGETS is defined by the resource Makefiles
@@ -62,35 +81,46 @@ dummy: $(INITTARGETS)
@echo "THIS FILE ENSURES THAT COMPILATION GOES RIGHT THE FIRST TIME, DO NOT DELETE" > $@ @echo "THIS FILE ENSURES THAT COMPILATION GOES RIGHT THE FIRST TIME, DO NOT DELETE" > $@
# `.d` files are generated as dependency lists of the "root" ASM files, to save a lot of hassle. # `.d` files are generated as dependency lists of the "root" ASM files, to save a lot of hassle.
# > Deps files also depend on `dummy` to ensure all the binary files are present, so RGBASM doesn't choke on them not being present; # > Obj files also depend on `dummy` to ensure all the binary files are present, so RGBASM doesn't choke on them not being present;
# > This would cause the first compilation to never finish, thus Make never knows to build the binary files, thus deadlocking everything. # > This would cause the first compilation to never finish, thus Make never knows to build the binary files, thus deadlocking everything.
$(DEPSDIR)/%.d: $(SRCDIR)/%.asm dummy # Compiling also generates dependency files!
@echo Building deps file $@ # Also add all obj dependencies to the deps file too, so Make knows to remake it
# RGBDS is stupid, so dependency files cannot be generated if obj files aren't,
# so if a dep file is missing but an obj is there, we need to delete the object and start over
$(DEPSDIR)/%.d: $(OBJDIR)/%.o ;
$(OBJDIR)/%.o: DEPFILE = $(DEPSDIR)/$*.d
$(OBJDIR)/%.o: $(SRCDIR)/%.asm dummy
@$(MKDIR) -p $(DEPSDIR) @$(MKDIR) -p $(DEPSDIR)
@$(MKDIR) -p $(OBJDIR) @$(MKDIR) -p $(OBJDIR)
set -e; \ set -e; \
$(RGBASM) -M $@.tmp $(ASFLAGS) -o $(patsubst $(SRCDIR)/%.asm,$(OBJDIR)/%.o,$<) $<; \ TMP_DEPFILE=$$(mktemp); \
sed 's,\($*\)\.o[ :]*,\1.o $@: ,g' < $@.tmp > $@; \ $(RGBASM) -M $$TMP_DEPFILE $(ASFLAGS) -o $@ $<; \
rm $@.tmp sed 's,\($*\)\.o[ :]*,\1.o $(DEPFILE): ,g' < $$TMP_DEPFILE > $(DEPFILE); \
for line in $$(cut -d ":" -f 2 $$TMP_DEPFILE); do if [ "$$line" != "$<" ]; then echo "$$line: ;" >> $(DEPFILE); fi; done; \
rm $$TMP_DEPFILE
# Include (and potentially remake) all dependency files # Include (and potentially remake) all dependency files
include $(patsubst $(SRCDIR)/%.asm,$(DEPSDIR)/%.d,$(ASMFILES)) # Remove duplicated recipes (`sort | uniq`), hence using yet another file grouping everything
# Also filter out lines already defined in the resource Makefiles because defining two rules for the same file causes Bad Things(tm) (`grep`)
SPACE :=
SPACE +=
# Yes this "space" hack is NEEDED. I don't like where I'm going anymore, either
$(DEPSDIR)/all: $(patsubst $(SRCDIR)/%.asm,$(DEPSDIR)/%.d,$(ASMFILES))
cat $^ | sort | uniq | grep -vE "^($(subst .,\\.,$(subst $(SPACE),|,$(strip $(INITTARGETS))))): ;" > $@
ifneq ($(MAKECMDGOALS),clean)
include $(DEPSDIR)/all
endif
# How to make the ROM # How to make the ROM
$(ROMFILE): $(patsubst $(SRCDIR)/%.asm,$(OBJDIR)/%.o,$(ASMFILES)) $(ROMFile): $(patsubst $(SRCDIR)/%.asm,$(OBJDIR)/%.o,$(ASMFILES))
@$(MKDIR) -p $(BINDIR) @$(MKDIR) -p $(BINDIR)
$(RGBASM) $(ASFLAGS) -o $(OBJDIR)/build_date.o $(SRCDIR)/res/build_date.asm $(RGBASM) $(ASFLAGS) -o $(OBJDIR)/build_date.o $(SRCDIR)/res/build_date.asm
$(RGBLINK) $(LDFLAGS) -o $(BINDIR)/tmp.gb -m $(@:.$(ROMExt)=.map) -n $(@:.$(ROMExt)=.sym) $^ $(OBJDIR)/build_date.o set -e; \
$(RGBFIX) $(FXFLAGS) $(BINDIR)/tmp.gb TMP_ROM=$$(mktemp); \
$(RGBLINK) $(LDFLAGS) -o $$TMP_ROM -m $(@:.gb=.map) -n $(@:.gb=.sym) $^ $(OBJDIR)/build_date.o; \
mv $(BINDIR)/tmp.gb $@ $(RGBFIX) $(FXFLAGS) $$TMP_ROM; \
mv $$TMP_ROM $(ROMFile)
# How to make the objects files
# (Just in case; since generating the deps files also generates the OBJ files, this should not be run ever, unless the OBJ files are destroyed but the deps files aren't.)
$(OBJDIR)/%.o: $(SRCDIR)/%.asm
@$(MKDIR) -p $(OBJDIR)
$(RGBASM) $(ASFLAGS) -o $@ $<