# DOS (DJGPP) build rules: JoeyLib's library for DOS, and programRules, the # DOS rules for one program, which make/programs.mk instantiates for every # program (a project reaches both through make/project.mk). JoeyLib's own # examples are at the end. PLATFORM := dos include $(dir $(lastword $(MAKEFILE_LIST)))/common.mk $(call requireTool,$(DOS_CC),toolchain:dos) $(call requireTool,$(DOS_AS),toolchain:dos) $(call requireTool,$(DOS_CWSDSTUB),toolchain:dos) $(call requireTool,$(LIBXMP_DIR)/include/libxmp-lite/xmp.h,toolchain:dos) # -fomit-frame-pointer: flag parity with the ST/Amiga CFLAGS (both had # it; DOS never did). Frees EBP for allocation in the hot loops under # DOSBox's per-instruction-charged core (perf-hunt-2 rank 2). # so flag experiments never edit a tracked file (perf-hunt-2 rank 17). CFLAGS := $(COMMON_CFLAGS) -march=i386 -m32 -fomit-frame-pointer -I$(SRC_DIR)/dos -I$(SRC_X86) -I$(LIBXMP_DIR)/include -MMD -MP ASFLAGS := -f coff # libxmp-lite (MIT, libxmp.org) -- 4-channel-Protracker-and-friends # replayer + SMIX SFX overlay. Installed by ./install.sh # (LIBXMP_DIR, from config.mk). Built as a static archive that the DOS # audio HAL links against. LIBXMP_SRC := $(filter-out %/win32.c, $(wildcard $(LIBXMP_DIR)/src/*.c) $(wildcard $(LIBXMP_DIR)/src/loaders/*.c)) LIBXMP_OBJDIR := $(BUILD)/obj/libxmp-lite LIBXMP_OBJS := $(patsubst $(LIBXMP_DIR)/src/%.c,$(LIBXMP_OBJDIR)/%.o,$(LIBXMP_SRC)) LIBXMP_AR := $(LIBDIR)/libxmplite.a LIBXMP_CFLAGS := -DJOEY_LIBXMP_LITE -DLIBXMP_CORE_PLAYER -DHAVE_FNMATCH=0 -I$(LIBXMP_DIR)/include -I$(LIBXMP_DIR)/include/libxmp-lite -I$(LIBXMP_DIR)/src -Wno-error -w # The x86 code DOS shares with DVX (the sprite emitter, the whole-map tile # walker, the set-1 scan code table) lives in src/x86 and builds into obj/x86; # only the CPU-independent sprite dispatch stays in src/codegen. PORT_C_SRCS := $(wildcard $(SRC_DIR)/dos/*.c) PORT_S_SRCS := $(wildcard $(SRC_DIR)/dos/*.asm) X86_C_SRCS := $(wildcard $(SRC_X86)/*.c) CODEGEN_DIR := $(REPO_DIR)/src/codegen LIB_OBJS := \ $(patsubst $(SRC_CORE)/%.c,$(BUILD)/obj/core/%.o,$(CORE_C_SRCS)) \ $(patsubst $(SRC_DIR)/generic/%.c,$(BUILD)/obj/generic/%.o,$(GENERIC_C_SRCS)) \ $(patsubst $(SRC_DIR)/dos/%.c,$(BUILD)/obj/port/%.o,$(PORT_C_SRCS)) \ $(patsubst $(SRC_DIR)/dos/%.asm,$(BUILD)/obj/port/%.o,$(PORT_S_SRCS)) \ $(patsubst $(SRC_X86)/%.c,$(BUILD)/obj/x86/%.o,$(X86_C_SRCS)) \ $(BUILD)/obj/codegen/spriteCompile.o \ $(BUILD)/obj/codegen/spriteStage.o LIB := $(LIBDIR)/libjoey.a $(BUILD)/obj/core/%.o: $(SRC_CORE)/%.c @mkdir -p $(dir $@) $(DOS_CC) $(CFLAGS) -c $< -o $@ $(BUILD)/obj/generic/%.o: $(SRC_DIR)/generic/%.c @mkdir -p $(dir $@) $(DOS_CC) $(CFLAGS) -c $< -o $@ $(BUILD)/obj/port/%.o: $(SRC_DIR)/dos/%.c @mkdir -p $(dir $@) $(DOS_CC) $(CFLAGS) -I$(CODEGEN_DIR) -c $< -o $@ $(BUILD)/obj/port/%.o: $(SRC_DIR)/dos/%.asm @mkdir -p $(dir $@) $(DOS_AS) $(ASFLAGS) $< -o $@ $(BUILD)/obj/x86/%.o: $(SRC_X86)/%.c @mkdir -p $(dir $@) $(DOS_CC) $(CFLAGS) -I$(CODEGEN_DIR) -c $< -o $@ $(BUILD)/obj/codegen/%.o: $(CODEGEN_DIR)/%.c @mkdir -p $(dir $@) $(DOS_CC) $(CFLAGS) -I$(CODEGEN_DIR) -c $< -o $@ # Archived from scratch, so the members -- and every program's layout -- # follow LIB_OBJS rather than the order earlier builds added them in. $(LIB): $(LIB_OBJS) @mkdir -p $(dir $@) rm -f $@ $(DOS_AR) rcs $@ $^ $(LIBXMP_OBJDIR)/%.o: $(LIBXMP_DIR)/src/%.c @mkdir -p $(dir $@) $(DOS_CC) $(CFLAGS) $(LIBXMP_CFLAGS) -c $< -o $@ $(LIBXMP_AR): $(LIBXMP_OBJS) @mkdir -p $(dir $@) rm -f $@ $(DOS_AR) rcs $@ $^ # Pull in per-object header-dependency files generated by gcc -MMD/-MP. # Without this, editing a header (e.g. surfaceInternal.h) doesn't rebuild # the .c files that include it, leaving a frankenstein binary where # different TUs see different struct layouts. -include $(LIB_OBJS:.o=.d) # ---- programs ----------------------------------------------------------------- # A program is NAME.EXE, in bin/ or in its own bin/NAME/ with its DATA beside # it (JoeyLib's install convention), where DOSBox's C: (bin/ or the folder) # finds both. PROGRAM_EXT := .EXE PROGRAM_FOLDERS := yes # One program, $(1) its id: compiled and linked in one step with the library # and libxmp-lite, then given the CWSDPMI DPMI server, so the .EXE needs no # CWSDPMI.EXE beside it. gcc's -MMD leaves NAME.d beside it, for header edits. define programRules $(call programBin,$(1)): $(call programVar,$(1),SRCS) $(LIB) $(LIBXMP_AR) @mkdir -p $$(dir $$@) $(DOS_CC) $(CFLAGS) $(call programVar,$(1),CFLAGS) $(call programVar,$(1),SRCS) $(LIB) $(LIBXMP_AR) -o $$@ $(call programVar,$(1),LDFLAGS) $(DOS_EMBED_DPMI) $$@ -include $(basename $(call programBin,$(1))).d endef # ---- JoeyLib's own build: its examples ------------------------------------------ ifndef JOEY_PROJECT include $(REPO_DIR)/make/examples.mk include $(REPO_DIR)/make/programs.mk .DEFAULT_GOAL := all .PHONY: all dos clean-dos clean all dos: $(LIB) $(LIBXMP_AR) programs clean-dos: rm -rf $(BUILD) # `clean` as an alias for `clean-dos`. Without it a bare # `make -f make/dos.mk clean` FAILS -- and with stderr discarded that # looks like success while leaving stale objects the next build links. clean: clean-dos endif