diff --git a/Makefile b/Makefile index 7d92bad21c..1eb4b8b55a 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,22 @@ -TOOLCHAIN := $(DEVKITARM) -COMPARE ?= 0 +# GBA rom header +TITLE := POKEMON EMER +GAME_CODE := BPEE +MAKER_CODE := 01 +REVISION := 0 +MODERN ?= 0 +# `File name`.gba ('_modern' will be appended to the modern builds) +FILE_NAME := pokeemerald +BUILD_DIR := build + +# Builds the ROM using a modern compiler +MODERN ?= 0 +# Compares the ROM to a checksum of the original - only makes sense using when non-modern +COMPARE ?= 0 + +ifeq (modern,$(MAKECMDGOALS)) + MODERN := 1 +endif ifeq (compare,$(MAKECMDGOALS)) COMPARE := 1 endif @@ -8,45 +24,29 @@ endif # Default make rule all: rom +# Toolchain selection +TOOLCHAIN := $(DEVKITARM) # don't use dkP's base_tools anymore # because the redefinition of $(CC) conflicts # with when we want to use $(CC) to preprocess files # thus, manually create the variables for the bin # files, or use arm-none-eabi binaries on the system # if dkP is not installed on this system - ifneq (,$(TOOLCHAIN)) -ifneq ($(wildcard $(TOOLCHAIN)/bin),) -export PATH := $(TOOLCHAIN)/bin:$(PATH) -endif + ifneq ($(wildcard $(TOOLCHAIN)/bin),) + export PATH := $(TOOLCHAIN)/bin:$(PATH) + endif endif PREFIX := arm-none-eabi- OBJCOPY := $(PREFIX)objcopy OBJDUMP := $(PREFIX)objdump AS := $(PREFIX)as - LD := $(PREFIX)ld -# note: the makefile must be set up so MODERNCC is never called -# if MODERN=0 -MODERNCC := $(PREFIX)gcc -PATH_MODERNCC := PATH="$(PATH)" $(MODERNCC) - -ifeq ($(OS),Windows_NT) -EXE := .exe -else EXE := -endif - -TITLE := POKEMON EMER -GAME_CODE := BPEE -MAKER_CODE := 01 -REVISION := 0 -MODERN ?= 0 - -ifeq (modern,$(MAKECMDGOALS)) - MODERN := 1 +ifeq ($(OS),Windows_NT) + EXE := .exe endif # use arm-none-eabi-cpp for macOS @@ -66,22 +66,29 @@ else CPP := $(PREFIX)cpp endif -ROM_NAME := pokeemerald.gba +ROM_NAME := $(FILE_NAME).gba +OBJ_DIR_NAME := $(BUILD_DIR)/emerald +MODERN_ROM_NAME := $(FILE_NAME)_modern.gba +MODERN_OBJ_DIR_NAME := $(BUILD_DIR)/modern + ELF_NAME := $(ROM_NAME:.gba=.elf) MAP_NAME := $(ROM_NAME:.gba=.map) -OBJ_DIR_NAME := build/emerald - -MODERN_ROM_NAME := pokeemerald_modern.gba MODERN_ELF_NAME := $(MODERN_ROM_NAME:.gba=.elf) MODERN_MAP_NAME := $(MODERN_ROM_NAME:.gba=.map) -MODERN_OBJ_DIR_NAME := build/modern -SHELL := /bin/bash -o pipefail - -ELF = $(ROM:.gba=.elf) -MAP = $(ROM:.gba=.map) -SYM = $(ROM:.gba=.sym) +# Pick our active variables +ifeq ($(MODERN),0) + ROM := $(ROM_NAME) + OBJ_DIR := $(OBJ_DIR_NAME) +else + ROM := $(MODERN_ROM_NAME) + OBJ_DIR := $(MODERN_OBJ_DIR_NAME) +endif +ELF := $(ROM:.gba=.elf) +MAP := $(ROM:.gba=.map) +SYM := $(ROM:.gba=.sym) +# Commonly used directories C_SUBDIR = src GFLIB_SUBDIR = gflib ASM_SUBDIR = asm @@ -99,34 +106,43 @@ DATA_ASM_BUILDDIR = $(OBJ_DIR)/$(DATA_ASM_SUBDIR) SONG_BUILDDIR = $(OBJ_DIR)/$(SONG_SUBDIR) MID_BUILDDIR = $(OBJ_DIR)/$(MID_SUBDIR) +SHELL := /bin/bash -o pipefail + +# Set flags for tools ASFLAGS := -mcpu=arm7tdmi --defsym MODERN=$(MODERN) -ifeq ($(MODERN),0) -CC1 := tools/agbcc/bin/agbcc$(EXE) -override CFLAGS += -mthumb-interwork -Wimplicit -Wparentheses -Werror -O2 -fhex-asm -g -ROM := $(ROM_NAME) -OBJ_DIR := $(OBJ_DIR_NAME) -LIBPATH := -L ../../tools/agbcc/lib -LIB := $(LIBPATH) -lgcc -lc -L../../libagbsyscall -lagbsyscall -else -CC1 = $(shell $(PATH_MODERNCC) --print-prog-name=cc1) -quiet -override CFLAGS += -mthumb -mthumb-interwork -O2 -mabi=apcs-gnu -mtune=arm7tdmi -march=armv4t -fno-toplevel-reorder -Wno-pointer-to-int-cast -ROM := $(MODERN_ROM_NAME) -OBJ_DIR := $(MODERN_OBJ_DIR_NAME) -LIBPATH := -L "$(dir $(shell $(PATH_MODERNCC) -mthumb -print-file-name=libgcc.a))" -L "$(dir $(shell $(PATH_MODERNCC) -mthumb -print-file-name=libnosys.a))" -L "$(dir $(shell $(PATH_MODERNCC) -mthumb -print-file-name=libc.a))" -LIB := $(LIBPATH) -lc -lnosys -lgcc -L../../libagbsyscall -lagbsyscall -endif +INCLUDE_DIRS := include +INCLUDE_CPP_ARGS := $(INCLUDE_DIRS:%=-iquote %) +INCLUDE_SCANINC_ARGS := $(INCLUDE_DIRS:%=-I %) -CPPFLAGS := -iquote include -iquote $(GFLIB_SUBDIR) -Wno-trigraphs -DMODERN=$(MODERN) -ifneq ($(MODERN),1) -CPPFLAGS += -I tools/agbcc/include -I tools/agbcc -nostdinc -undef +O_LEVEL ?= 2 +CPPFLAGS := $(INCLUDE_CPP_ARGS) -iquote $(GFLIB_SUBDIR) -Wno-trigraphs -DMODERN=$(MODERN) +ifeq ($(MODERN),0) + CPPFLAGS += -I tools/agbcc/include -I tools/agbcc -nostdinc -undef + CC1 := tools/agbcc/bin/agbcc$(EXE) + override CFLAGS += -mthumb-interwork -Wimplicit -Wparentheses -Werror -O$(O_LEVEL) -fhex-asm -g + LIBPATH := -L ../../tools/agbcc/lib + LIB := $(LIBPATH) -lgcc -lc -L../../libagbsyscall -lagbsyscall +else + # Note: The makefile must be set up to not call these if modern == 0 + MODERNCC := $(PREFIX)gcc + PATH_MODERNCC := PATH="$(PATH)" $(MODERNCC) + CC1 := $(shell $(PATH_MODERNCC) --print-prog-name=cc1) -quiet + override CFLAGS += -mthumb -mthumb-interwork -O$(O_LEVEL) -mabi=apcs-gnu -mtune=arm7tdmi -march=armv4t -fno-toplevel-reorder -Wno-pointer-to-int-cast + LIBPATH := -L "$(dir $(shell $(PATH_MODERNCC) -mthumb -print-file-name=libgcc.a))" -L "$(dir $(shell $(PATH_MODERNCC) -mthumb -print-file-name=libnosys.a))" -L "$(dir $(shell $(PATH_MODERNCC) -mthumb -print-file-name=libc.a))" + LIB := $(LIBPATH) -lc -lnosys -lgcc -L../../libagbsyscall -lagbsyscall +endif +# Enable debug info if set +ifeq ($(DINFO),1) + override CFLAGS += -g endif LDFLAGS = -Map ../../$(MAP) +# Variable filled out in other make files AUTO_GEN_TARGETS := include make_tools.mk -SHA1 := $(shell { command -v sha1sum || command -v shasum; } 2>/dev/null) -c +# Tool executables GFX := $(TOOLS_DIR)/gbagfx/gbagfx$(EXE) AIF := $(TOOLS_DIR)/aif2pcm/aif2pcm$(EXE) MID := $(TOOLS_DIR)/mid2agb/mid2agb$(EXE) @@ -138,6 +154,7 @@ MAPJSON := $(TOOLS_DIR)/mapjson/mapjson$(EXE) JSONPROC := $(TOOLS_DIR)/jsonproc/jsonproc$(EXE) PERL := perl +SHA1 := $(shell { command -v sha1sum || command -v shasum; } 2>/dev/null) -c MAKEFLAGS += --no-print-directory @@ -147,39 +164,36 @@ MAKEFLAGS += --no-print-directory .SECONDARY: # Delete files that weren't built properly .DELETE_ON_ERROR: - # Secondary expansion is required for dependency variables in object rules. .SECONDEXPANSION: -.PHONY: all rom clean compare tidy mostlyclean libagbsyscall modern tidymodern tidynonmodern +RULES_NO_SCAN += libagbsyscall clean clean-assets tidy tidymodern tidynonmodern generated clean-generated +.PHONY: all rom modern compare +.PHONY: $(RULES_NO_SCAN) infoshell = $(foreach line, $(shell $1 | sed "s/ /__SPACE__/g"), $(info $(subst __SPACE__, ,$(line)))) -# Build tools when building the rom -# Disable dependency scanning for clean/tidy/tools -# Use a separate minimal makefile for speed -# Since we don't need to reload most of this makefile -ifeq (,$(filter-out all rom compare modern libagbsyscall syms,$(MAKECMDGOALS))) -$(call infoshell, $(MAKE) -f make_tools.mk) -$(call infoshell, $(MAKE) generated) -else -NODEP ?= 1 -endif - -# check if we need to scan dependencies based on the rule -ifeq (,$(MAKECMDGOALS)) - SCAN_DEPS ?= 1 -else - # clean, tidy, tools, mostlyclean, clean-tools, $(TOOLDIRS), tidymodern, tidynonmodern don't even build the ROM - # libagbsyscall does its own thing - ifeq (,$(filter-out clean tidy tools mostlyclean clean-tools $(TOOLDIRS) tidymodern tidynonmodern libagbsyscall,$(MAKECMDGOALS))) - SCAN_DEPS ?= 0 - else - SCAN_DEPS ?= 1 +# Check if we need to scan dependencies based on the chosen rule OR user preference +NODEP ?= 0 +# Check if we need to pre-build tools and generate assets based on the chosen rule. +SETUP_PREREQS ?= 1 +# Disable dependency scanning for rules that don't need it. +ifneq (,$(MAKECMDGOALS)) + ifeq (,$(filter-out $(RULES_NO_SCAN),$(MAKECMDGOALS))) + NODEP := 1 + SETUP_PREREQS := 0 endif endif -ifeq ($(SCAN_DEPS),1) +ifeq ($(SETUP_PREREQS),1) + # If set on: Default target or a rule requiring a scan + # Forcibly execute `make tools` since we need them for what we are doing. + $(call infoshell, $(MAKE) -f make_tools.mk) + # Oh and also generate mapjson sources before we use `SCANINC`. + $(call infoshell, $(MAKE) generated) +endif + +# Collect sources C_SRCS_IN := $(wildcard $(C_SUBDIR)/*.c $(C_SUBDIR)/*/*.c $(C_SUBDIR)/*/*/*.c) C_SRCS := $(foreach src,$(C_SRCS_IN),$(if $(findstring .inc.c,$(src)),,$(src))) C_OBJS := $(patsubst $(C_SUBDIR)/%.c,$(C_BUILDDIR)/%.o,$(C_SRCS)) @@ -187,7 +201,7 @@ C_OBJS := $(patsubst $(C_SUBDIR)/%.c,$(C_BUILDDIR)/%.o,$(C_SRCS)) GFLIB_SRCS := $(wildcard $(GFLIB_SUBDIR)/*.c) GFLIB_OBJS := $(patsubst $(GFLIB_SUBDIR)/%.c,$(GFLIB_BUILDDIR)/%.o,$(GFLIB_SRCS)) -C_ASM_SRCS += $(wildcard $(C_SUBDIR)/*.s $(C_SUBDIR)/*/*.s $(C_SUBDIR)/*/*/*.s) +C_ASM_SRCS := $(wildcard $(C_SUBDIR)/*.s $(C_SUBDIR)/*/*.s $(C_SUBDIR)/*/*/*.s) C_ASM_OBJS := $(patsubst $(C_SUBDIR)/%.s,$(C_BUILDDIR)/%.o,$(C_ASM_SRCS)) ASM_SRCS := $(wildcard $(ASM_SUBDIR)/*.s) @@ -210,29 +224,29 @@ OBJS_REL := $(patsubst $(OBJ_DIR)/%,%,$(OBJS)) SUBDIRS := $(sort $(dir $(OBJS))) $(shell mkdir -p $(SUBDIRS)) -endif -syms: $(SYM) +# Pretend rules that are actually flags defer to `make all` +modern: all +compare: all +# Other rules rom: $(ROM) ifeq ($(COMPARE),1) @$(SHA1) rom.sha1 endif -# For contributors to make sure a change didn't affect the contents of the ROM. -compare: all +syms: $(SYM) -clean: mostlyclean clean-tools +clean: tidy clean-tools clean-generated clean-assets + @$(MAKE) clean -C libagbsyscall -mostlyclean: tidynonmodern tidymodern - find sound -iname '*.bin' -exec rm {} + +clean-assets: rm -f $(MID_SUBDIR)/*.s - find . \( -iname '*.1bpp' -o -iname '*.4bpp' -o -iname '*.8bpp' -o -iname '*.gbapal' -o -iname '*.lz' -o -iname '*.rl' -o -iname '*.latfont' -o -iname '*.hwjpnfont' -o -iname '*.fwjpnfont' \) -exec rm {} + rm -f $(DATA_ASM_SUBDIR)/layouts/layouts.inc $(DATA_ASM_SUBDIR)/layouts/layouts_table.inc rm -f $(DATA_ASM_SUBDIR)/maps/connections.inc $(DATA_ASM_SUBDIR)/maps/events.inc $(DATA_ASM_SUBDIR)/maps/groups.inc $(DATA_ASM_SUBDIR)/maps/headers.inc + find sound -iname '*.bin' -exec rm {} + + find . \( -iname '*.1bpp' -o -iname '*.4bpp' -o -iname '*.8bpp' -o -iname '*.gbapal' -o -iname '*.lz' -o -iname '*.rl' -o -iname '*.latfont' -o -iname '*.hwjpnfont' -o -iname '*.fwjpnfont' \) -exec rm {} + find $(DATA_ASM_SUBDIR)/maps \( -iname 'connections.inc' -o -iname 'events.inc' -o -iname 'header.inc' \) -exec rm {} + - rm -f $(AUTO_GEN_TARGETS) - @$(MAKE) clean -C libagbsyscall tidy: tidynonmodern tidymodern @@ -244,18 +258,13 @@ tidymodern: rm -f $(MODERN_ROM_NAME) $(MODERN_ELF_NAME) $(MODERN_MAP_NAME) rm -rf $(MODERN_OBJ_DIR_NAME) -ifneq ($(MODERN),0) -$(C_BUILDDIR)/berry_crush.o: override CFLAGS += -Wno-address-of-packed-member -endif - +# Other rules include graphics_file_rules.mk include map_data_rules.mk include spritesheet_rules.mk include json_data_rules.mk include songs.mk -generated: $(AUTO_GEN_TARGETS) - %.s: ; %.png: ; %.pal: ; @@ -271,119 +280,101 @@ generated: $(AUTO_GEN_TARGETS) $(CRY_SUBDIR)/%.bin: $(CRY_SUBDIR)/%.aif ; $(AIF) $< $@ --compress sound/%.bin: sound/%.aif ; $(AIF) $< $@ +# NOTE: Tools must have been built prior (FIXME) +generated: tools $(AUTO_GEN_TARGETS) +clean-generated: + -rm -f $(AUTO_GEN_TARGETS) ifeq ($(MODERN),0) -$(C_BUILDDIR)/libc.o: CC1 := $(TOOLS_DIR)/agbcc/bin/old_agbcc$(EXE) +$(C_BUILDDIR)/libc.o: CC1 := tools/agbcc/bin/old_agbcc$(EXE) $(C_BUILDDIR)/libc.o: CFLAGS := -O2 - $(C_BUILDDIR)/siirtc.o: CFLAGS := -mthumb-interwork - $(C_BUILDDIR)/agb_flash.o: CFLAGS := -O -mthumb-interwork $(C_BUILDDIR)/agb_flash_1m.o: CFLAGS := -O -mthumb-interwork $(C_BUILDDIR)/agb_flash_mx.o: CFLAGS := -O -mthumb-interwork - -$(C_BUILDDIR)/m4a.o: CC1 := $(TOOLS_DIR)/agbcc/bin/old_agbcc$(EXE) - +$(C_BUILDDIR)/m4a.o: CC1 := tools/agbcc/bin/old_agbcc$(EXE) $(C_BUILDDIR)/record_mixing.o: CFLAGS += -ffreestanding -$(C_BUILDDIR)/librfu_intr.o: CC1 := $(TOOLS_DIR)/agbcc/bin/agbcc_arm$(EXE) +$(C_BUILDDIR)/librfu_intr.o: CC1 := tools/agbcc/bin/agbcc_arm$(EXE) $(C_BUILDDIR)/librfu_intr.o: CFLAGS := -O2 -mthumb-interwork -quiet else $(C_BUILDDIR)/librfu_intr.o: CFLAGS := -mthumb-interwork -O2 -mabi=apcs-gnu -mtune=arm7tdmi -march=armv4t -fno-toplevel-reorder -Wno-pointer-to-int-cast +$(C_BUILDDIR)/berry_crush.o: override CFLAGS += -Wno-address-of-packed-member endif -ifeq ($(DINFO),1) -override CFLAGS += -g -endif +# Dependency rules (for the *.c & *.s sources to .o files) +# Have to be explicit or else missing files won't be reported. -# The dep rules have to be explicit or else missing files won't be reported. # As a side effect, they're evaluated immediately instead of when the rule is invoked. -# It doesn't look like $(shell) can be deferred so there might not be a better way. +# It doesn't look like $(shell) can be deferred so there might not be a better way (Icedude_907: there is soon). -ifeq ($(SCAN_DEPS),1) -ifeq ($(NODEP),1) -$(C_BUILDDIR)/%.o: $(C_SUBDIR)/%.c -ifeq (,$(KEEP_TEMPS)) - @echo "$(CC1) -o $@ $<" - @$(CPP) $(CPPFLAGS) $< | $(PREPROC) $< charmap.txt -i | $(CC1) $(CFLAGS) -o - - | cat - <(echo -e ".text\n\t.align\t2, 0") | $(AS) $(ASFLAGS) -o $@ - -else - @$(CPP) $(CPPFLAGS) $< -o $(C_BUILDDIR)/$*.i - @$(PREPROC) $(C_BUILDDIR)/$*.i charmap.txt | $(CC1) $(CFLAGS) -o $(C_BUILDDIR)/$*.s - @echo -e ".text\n\t.align\t2, 0\n" >> $(C_BUILDDIR)/$*.s - $(AS) $(ASFLAGS) -o $@ $(C_BUILDDIR)/$*.s -endif -else +# For C dependencies. +# Args: $1 = Output file without extension (build/assets/src/data), $2 = Input file (src/data.c) define C_DEP -$1: $2 $$(shell $(SCANINC) -I include -I $(TOOLS_DIR)/agbcc/include -I gflib $2) -ifeq (,$$(KEEP_TEMPS)) - @echo "$$(CC1) -o $$@ $$<" - @$$(CPP) $$(CPPFLAGS) $$< | $$(PREPROC) $$< charmap.txt -i | $$(CC1) $$(CFLAGS) -o - - | cat - <(echo -e ".text\n\t.align\t2, 0") | $$(AS) $$(ASFLAGS) -o $$@ - -else - @$$(CPP) $$(CPPFLAGS) $$< -o $$(C_BUILDDIR)/$3.i - @$$(PREPROC) $$(C_BUILDDIR)/$3.i charmap.txt | $$(CC1) $$(CFLAGS) -o $$(C_BUILDDIR)/$3.s - @echo -e ".text\n\t.align\t2, 0\n" >> $$(C_BUILDDIR)/$3.s - $$(AS) $$(ASFLAGS) -o $$@ $$(C_BUILDDIR)/$3.s -endif +$(call C_DEP_IMPL,$1,$2,$1) endef -$(foreach src, $(C_SRCS), $(eval $(call C_DEP,$(patsubst $(C_SUBDIR)/%.c,$(C_BUILDDIR)/%.o,$(src)),$(src),$(patsubst $(C_SUBDIR)/%.c,%,$(src))))) -endif - -ifeq ($(NODEP),1) -$(GFLIB_BUILDDIR)/%.o: $(GFLIB_SUBDIR)/%.c $$(c_dep) +# Internal implementation details. +# $1: Output file without extension, $2 input file, $3 temp path (if keeping) +define C_DEP_IMPL +$1.o: $2 ifeq (,$(KEEP_TEMPS)) - @echo "$(CC1) -o $@ $<" - @$(CPP) $(CPPFLAGS) $< | $(PREPROC) $< charmap.txt -i | $(CC1) $(CFLAGS) -o - - | cat - <(echo -e ".text\n\t.align\t2, 0") | $(AS) $(ASFLAGS) -o $@ - -else - @$(CPP) $(CPPFLAGS) $< -o $(GFLIB_BUILDDIR)/$*.i - @$(PREPROC) $(GFLIB_BUILDDIR)/$*.i charmap.txt | $(CC1) $(CFLAGS) -o $(GFLIB_BUILDDIR)/$*.s - @echo -e ".text\n\t.align\t2, 0\n" >> $(GFLIB_BUILDDIR)/$*.s - $(AS) $(ASFLAGS) -o $@ $(GFLIB_BUILDDIR)/$*.s -endif -else -define GFLIB_DEP -$1: $2 $$(shell $(SCANINC) -I include -I $(TOOLS_DIR)/agbcc/include -I gflib $2) -ifeq (,$$(KEEP_TEMPS)) @echo "$$(CC1) -o $$@ $$<" @$$(CPP) $$(CPPFLAGS) $$< | $$(PREPROC) $$< charmap.txt -i | $$(CC1) $$(CFLAGS) -o - - | cat - <(echo -e ".text\n\t.align\t2, 0") | $$(AS) $$(ASFLAGS) -o $$@ - else - @$$(CPP) $$(CPPFLAGS) $$< -o $$(GFLIB_BUILDDIR)/$3.i - @$$(PREPROC) $$(GFLIB_BUILDDIR)/$3.i charmap.txt | $$(CC1) $$(CFLAGS) -o $$(GFLIB_BUILDDIR)/$3.s - @echo -e ".text\n\t.align\t2, 0\n" >> $$(GFLIB_BUILDDIR)/$3.s - $$(AS) $$(ASFLAGS) -o $$@ $$(GFLIB_BUILDDIR)/$3.s + @$$(CPP) $$(CPPFLAGS) $$< -o $3.i + @$$(PREPROC) $3.i charmap.txt | $$(CC1) $$(CFLAGS) -o $3.s + @echo -e ".text\n\t.align\t2, 0\n" >> $3.s + $$(AS) $$(ASFLAGS) -o $$@ $3.s +endif +$(call C_SCANINC,$1,$2) +endef +# Calls SCANINC to find dependencies +define C_SCANINC +ifneq ($(NODEP),1) +$1.o: $2 $$(shell $(SCANINC) $(INCLUDE_SCANINC_ARGS) -I tools/agbcc/include -I gflib $2) endif endef -$(foreach src, $(GFLIB_SRCS), $(eval $(call GFLIB_DEP,$(patsubst $(GFLIB_SUBDIR)/%.c,$(GFLIB_BUILDDIR)/%.o, $(src)),$(src),$(patsubst $(GFLIB_SUBDIR)/%.c,%, $(src))))) + +# Create generic rules if no dependency scanning, else create the real rules +ifeq ($(NODEP),1) +$(eval $(call C_DEP,$(C_BUILDDIR)/%,$(C_SUBDIR)/%.c)) +$(eval $(call C_DEP,$(GFLIB_BUILDDIR)/%,$(GFLIB_SUBDIR)/%.c)) +else +$(foreach src,$(C_SRCS),$(eval $(call C_DEP,$(OBJ_DIR)/$(basename $(src)),$(src)))) +$(foreach src,$(GFLIB_SRCS),$(eval $(call C_DEP,$(OBJ_DIR)/$(basename $(src)),$(src)))) endif -ifeq ($(NODEP),1) -$(C_BUILDDIR)/%.o: $(C_SUBDIR)/%.s - $(PREPROC) $< charmap.txt | $(CPP) -I include - | $(AS) $(ASFLAGS) -o $@ -else -define SRC_ASM_DATA_DEP -$1: $2 $$(shell $(SCANINC) -I include -I "" $2) - $$(PREPROC) $$< charmap.txt | $$(CPP) -I include - | $$(AS) $$(ASFLAGS) -o $$@ -endef -$(foreach src, $(C_ASM_SRCS), $(eval $(call SRC_ASM_DATA_DEP,$(patsubst $(C_SUBDIR)/%.s,$(C_BUILDDIR)/%.o, $(src)),$(src)))) -endif - -ifeq ($(NODEP),1) -$(ASM_BUILDDIR)/%.o: $(ASM_SUBDIR)/%.s - $(AS) $(ASFLAGS) -o $@ $< -else +# Similar methodology for Assembly files +# $1: Output path without extension, $2: Input file (`*.s`) define ASM_DEP -$1: $2 $$(shell $(SCANINC) -I include -I "" $2) +$1.o: $2 $$(AS) $$(ASFLAGS) -o $$@ $$< +$(call ASM_SCANINC,$1,$2) +endef +# As above but first doing a preprocessor pass +define ASM_DEP_PREPROC +$1.o: $2 + $$(PREPROC) $$< charmap.txt | $$(CPP) $(INCLUDE_SCANINC_ARGS) - | $$(AS) $$(ASFLAGS) -o $$@ +$(call ASM_SCANINC,$1,$2) endef -$(foreach src, $(ASM_SRCS), $(eval $(call ASM_DEP,$(patsubst $(ASM_SUBDIR)/%.s,$(ASM_BUILDDIR)/%.o, $(src)),$(src)))) -endif +define ASM_SCANINC +ifneq ($(NODEP),1) +$1.o: $2 $$(shell $(SCANINC) $(INCLUDE_SCANINC_ARGS) -I "" $2) +endif +endef + +# Dummy rules or real rules ifeq ($(NODEP),1) -$(DATA_ASM_BUILDDIR)/%.o: $(DATA_ASM_SUBDIR)/%.s - $(PREPROC) $< charmap.txt | $(CPP) -I include - | $(AS) $(ASFLAGS) -o $@ +$(eval $(call ASM_DEP,$(ASM_BUILDDIR)/%,$(ASM_SUBDIR)/%.s)) +$(eval $(call ASM_DEP_PREPROC,$(C_BUILDDIR)/%,$(C_SUBDIR)/%.s)) +$(eval $(call ASM_DEP_PREPROC,$(DATA_ASM_BUILDDIR)/%,$(DATA_ASM_SUBDIR)/%.s)) else -$(foreach src, $(REGULAR_DATA_ASM_SRCS), $(eval $(call SRC_ASM_DATA_DEP,$(patsubst $(DATA_ASM_SUBDIR)/%.s,$(DATA_ASM_BUILDDIR)/%.o, $(src)),$(src)))) -endif +$(foreach src, $(ASM_SRCS), $(eval $(call ASM_DEP,$(src:%.s=$(OBJ_DIR)/%),$(src)))) +$(foreach src, $(C_ASM_SRCS), $(eval $(call ASM_DEP_PREPROC,$(src:%.s=$(OBJ_DIR)/%),$(src)))) +$(foreach src, $(REGULAR_DATA_ASM_SRCS), $(eval $(call ASM_DEP_PREPROC,$(src:%.s=$(OBJ_DIR)/%),$(src)))) endif +# Additional rules $(SONG_BUILDDIR)/%.o: $(SONG_SUBDIR)/%.s $(AS) $(ASFLAGS) -I sound -o $@ $< @@ -396,6 +387,7 @@ $(OBJ_DIR)/sym_common.ld: sym_common.txt $(C_OBJS) $(wildcard common_syms/*.txt) $(OBJ_DIR)/sym_ewram.ld: sym_ewram.txt $(RAMSCRGEN) ewram_data $< ENGLISH > $@ +# Linker script ifeq ($(MODERN),0) LD_SCRIPT := ld_script.txt LD_SCRIPT_DEPS := $(OBJ_DIR)/sym_bss.ld $(OBJ_DIR)/sym_common.ld $(OBJ_DIR)/sym_ewram.ld @@ -405,25 +397,24 @@ LD_SCRIPT_DEPS := endif $(OBJ_DIR)/ld_script.ld: $(LD_SCRIPT) $(LD_SCRIPT_DEPS) - cd $(OBJ_DIR) && sed "s#tools/#../../tools/#g" ../../$(LD_SCRIPT) > ld_script.ld + sed "s#tools/#tools/#g" $(LD_SCRIPT) > $(OBJ_DIR)/ld_script.ld +# Final rules + +libagbsyscall: + @$(MAKE) -C libagbsyscall TOOLCHAIN=$(TOOLCHAIN) MODERN=$(MODERN) + +# Elf from object files $(ELF): $(OBJ_DIR)/ld_script.ld $(OBJS) libagbsyscall @echo "cd $(OBJ_DIR) && $(LD) $(LDFLAGS) -T ld_script.ld -o ../../$@ " @cd $(OBJ_DIR) && $(LD) $(LDFLAGS) -T ld_script.ld -o ../../$@ $(OBJS_REL) $(LIB) $(FIX) $@ -t"$(TITLE)" -c$(GAME_CODE) -m$(MAKER_CODE) -r$(REVISION) --silent +# Builds the rom from the elf file $(ROM): $(ELF) $(OBJCOPY) -O binary $< $@ $(FIX) $@ -p --silent -modern: all - -libagbsyscall: - @$(MAKE) -C libagbsyscall TOOLCHAIN=$(TOOLCHAIN) MODERN=$(MODERN) - -################### -### Symbol file ### -################### - +# Symbol file (`make syms`) $(SYM): $(ELF) $(OBJDUMP) -t $< | sort -u | grep -E "^0[2389]" | $(PERL) -p -e 's/^(\w{8}) (\w).{6} \S+\t(\w{8}) (\S+)$$/\1 \2 \3 \4/g' > $@ diff --git a/make_tools.mk b/make_tools.mk index 00824adda6..78ff1beeb0 100644 --- a/make_tools.mk +++ b/make_tools.mk @@ -9,7 +9,9 @@ TOOL_NAMES := aif2pcm bin2c gbafix gbagfx jsonproc mapjson mid2agb preproc ramsc TOOLDIRS := $(TOOL_NAMES:%=$(TOOLS_DIR)/%) -.PHONY: tools check-tools clean-tools $(TOOLDIRS) $(CHECKTOOLDIRS) +# Tool making doesnt require a pokeemerald dependency scan. +RULES_NO_SCAN += tools check-tools clean-tools $(TOOLDIRS) $(CHECKTOOLDIRS) +.PHONY: $(RULES_NO_SCAN) tools: $(TOOLDIRS) check-tools: $(CHECKTOOLDIRS)