diff --git a/Makefile b/Makefile index 8248a48..2a9b77f 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,14 @@ .SUFFIXES: -.DEFAULTTARGET: all +.DEFAULT_GOAL := all -include Makefile.conf +################################################ +# # +# CONSTANT DEFINITIONS # +# # +################################################ # Directory constants SRCDIR = src @@ -12,49 +16,64 @@ BINDIR = bin OBJDIR = obj DEPSDIR = deps -ROMFILE = $(BINDIR)/$(ROMName).$(ROMExt) - # Program constants RGBASM = rgbasm RGBLINK = rgblink RGBFIX = rgbfix MKDIR = $(shell which mkdir) +ROMFile = $(BINDIR)/$(ROMName).$(ROMExt) + +# Project-specific configuration +include Makefile.conf + + # Argument constants ASFLAGS += -E -h -i $(SRCDIR)/ -i $(SRCDIR)/constants/ -i $(SRCDIR)/macros/ -p $(FillValue) -LDFLAGS += -p $(FillValue) -FXFLAGS += -jv -i $(GameID) -k $(NewLicensee) -l $(OldLicensee) -m $(MBCType) -n $(ROMVersion) -p $(FillValue) -r $(SRAMSize) -t $(GameTitle) +LDFLAGS += -d -p $(FillValue) +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 ASMFILES := $(wildcard $(SRCDIR)/*.asm) -# `all` (Default target): build the ROM -.PHONY: all -all: $(ROMFILE) - -# `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 - +################################################ +# # +# RESOURCE FILES # +# # +################################################ # Define how to compress files (same recipe for any file) %.pb16: % 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 +# This must be done before we include `$(DEPSDIR)/all` otherwise `dummy` has no prereqs 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 # It's made an actual file to avoid an infinite compilation loop # 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" > $@ # `.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. -$(DEPSDIR)/%.d: $(SRCDIR)/%.asm dummy - @echo Building deps file $@ +# Compiling also generates dependency files! +# 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 $(OBJDIR) set -e; \ - $(RGBASM) -M $@.tmp $(ASFLAGS) -o $(patsubst $(SRCDIR)/%.asm,$(OBJDIR)/%.o,$<) $<; \ - sed 's,\($*\)\.o[ :]*,\1.o $@: ,g' < $@.tmp > $@; \ - rm $@.tmp + TMP_DEPFILE=$$(mktemp); \ + $(RGBASM) -M $$TMP_DEPFILE $(ASFLAGS) -o $@ $<; \ + 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 $(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 -$(ROMFILE): $(patsubst $(SRCDIR)/%.asm,$(OBJDIR)/%.o,$(ASMFILES)) +$(ROMFile): $(patsubst $(SRCDIR)/%.asm,$(OBJDIR)/%.o,$(ASMFILES)) @$(MKDIR) -p $(BINDIR) $(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 - $(RGBFIX) $(FXFLAGS) $(BINDIR)/tmp.gb - - mv $(BINDIR)/tmp.gb $@ - -# 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 $@ $< - + set -e; \ + TMP_ROM=$$(mktemp); \ + $(RGBLINK) $(LDFLAGS) -o $$TMP_ROM -m $(@:.gb=.map) -n $(@:.gb=.sym) $^ $(OBJDIR)/build_date.o; \ + $(RGBFIX) $(FXFLAGS) $$TMP_ROM; \ + mv $$TMP_ROM $(ROMFile)