# # TyrQuake Makefile (tested under Linux and MinGW/Msys) # # By default, all executables will be built and placed in the ./bin # subdirectory. If you want to build just one, type e.g. "make bin/tyr-quake". # TYR_VERSION_MAJOR = 0 TYR_VERSION_MINOR = 62 TYR_VERSION_BUILD = TYR_VERSION = $(TYR_VERSION_MAJOR).$(TYR_VERSION_MINOR)$(TYR_VERSION_BUILD) # ============================================================================ # User configurable options here: # ============================================================================ BUILD_DIR ?= build BIN_DIR ?= bin DEBUG ?= N# Compile with debug info OPTIMIZED_CFLAGS ?= Y# Enable compiler optimisations (if DEBUG != Y) USE_X86_ASM ?= $(I386_GUESS) USE_SDL ?= N# New (experimental) SDL video implementation for Win32 LOCALBASE ?= /usr/local QBASEDIR ?= .# Default basedir for quake data files (Linux/BSD only) TARGET_OS ?= $(HOST_OS) TARGET_UNIX ?= $(if $(filter UNIX,$(TARGET_OS)),$(HOST_UNIX),) # ============================================================================ .PHONY: default clean # ============================================================================ # --------------------------------------- # Attempt detection of the build host OS # --------------------------------------- SYSNAME := $(shell uname -s) TOPDIR := $(shell pwd) ifneq (,$(findstring MINGW32,$(SYSNAME))) HOST_OS = WIN32 else ifneq (,$(findstring $(SYSNAME),FreeBSD NetBSD)) HOST_OS = UNIX HOST_UNIX = bsd else ifneq (,$(findstring $(SYSNAME),OpenBSD)) HOST_OS = UNIX HOST_UNIX = openbsd else ifneq (,$(findstring $(SYSNAME),Darwin)) HOST_OS = UNIX HOST_UNIX = darwin else ifneq (,$(findstring $(SYSNAME),Linux)) HOST_OS = UNIX HOST_UNIX = linux else $(error OS type not detected.) endif endif endif endif endif # -------------------------------------------------------------------- # Setup driver options, choosing sensible defaults based on target OS # -------------------------------------------------------------------- ifeq ($(TARGET_OS),UNIX) EXT = VID_TARGET ?= x11 IN_TARGET ?= x11 ifeq ($(TARGET_UNIX),darwin) CD_TARGET ?= null SND_TARGET ?= null USE_XF86DGA ?= N endif ifeq ($(TARGET_UNIX),bsd) CD_TARGET ?= bsd SND_TARGET ?= linux USE_XF86DGA ?= Y endif ifeq ($(TARGET_UNIX),openbsd) CD_TARGET ?= bsd SND_TARGET ?= sndio USE_XF86DGA ?= Y endif ifeq ($(TARGET_UNIX),linux) CD_TARGET ?= linux SND_TARGET ?= linux USE_XF86DGA ?= Y endif endif ifeq ($(TARGET_OS),WIN32) EXT = .exe CD_TARGET ?= win SND_TARGET ?= win ifeq ($(USE_SDL),Y) VID_TARGET ?= sdl IN_TARGET ?= sdl else VID_TARGET ?= win IN_TARGET ?= win endif endif # -------------------------------------------------------------- # Executable file extension and possible cross-compiler options # -------------------------------------------------------------- ifeq ($(TARGET_OS),WIN32) EXT = .exe ifneq ($(HOST_OS),WIN32) TARGET ?= $(MINGW_CROSS_GUESS) CC = $(TARGET)-gcc STRIP = $(TARGET)-strip WINDRES = $(TARGET)-windres endif else EXT = endif # ============================================================================ # Helper functions # ============================================================================ # --------------------------------------------------- # Remove duplicates from a list, preserving ordering # --------------------------------------------------- # (I wonder if Make optimises the tail recursion here?) filter-dups = $(if $(1),$(firstword $(1)) $(call filter-dups,$(filter-out $(firstword $(1)),$(1))),) # ---------------------------------------------- # Try to guess the location of X11 includes/libs # ---------------------------------------------- # $(1) - header file to search for # $(2) - library name to search for # $(3) - list of directories to search in IGNORE_DIRS = /usr $(LOCALBASE) find-localbase = $(shell \ for DIR in $(IGNORE_DIRS); do \ if [ -e $$DIR/include/$(1) ] && \ [ -e $$DIR/lib/lib$(2).a ] || \ [ -e $$DIR/lib/lib$(2).la ] || \ [ -e $$DIR/lib/lib$(2).dylib ]; then exit 0; fi; \ done; \ for DIR in $(3); do \ if [ -e $$DIR/include/$(1) ] && \ [ -e $$DIR/lib/lib$(2).a ] || \ [ -e $$DIR/lib/lib$(2).la ] || \ [ -e $$DIR/lib/lib$(2).dylib ]; then echo $$DIR; exit 0; fi; \ done ) X11DIRS = /usr/X11R7 /usr/local/X11R7 /usr/X11R6 /usr/local/X11R6 /opt/X11 /opt/local X11BASE_GUESS := $(call find-localbase,X11/Xlib.h,X11,$(X11DIRS)) X11BASE ?= $(X11BASE_GUESS) SDLDIRS = /opt/local SDLBASE_GUESS := $(call find-localbase,SDL/SDL.h,SDL,$(SDLDIRS)) SDLBASE ?= $(SDLBASE_GUESS) # ------------------------------------------------------------------------ # Try to guess the MinGW cross compiler executables # - I've seen i386-mingw32msvc, i586-mingw32msvc (Debian) and now # i486-mingw32 (Arch). # ------------------------------------------------------------------------ MINGW_CROSS_GUESS := $(shell \ if which i486-mingw32-gcc > /dev/null 2>&1; then \ echo i486-mingw32; \ elif which i586-mingw32msvc-gcc > /dev/null 2>&1; then \ echo i586-mingw32msvc; \ else \ echo i386-mingw32msvc; \ fi) # -------------------------------- # GCC version and option checking # -------------------------------- cc-version = $(shell sh $(TOPDIR)/scripts/gcc-version \ $(if $(1), $(1), $(CC))) cc-option = $(shell if $(CC) $(CFLAGS) -Werror $(1) -S -o /dev/null -xc /dev/null \ > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi ;) cc-i386 = $(if $(subst __i386,,$(shell echo __i386 | $(CC) -E -xc - | tail -n 1)),Y,N) GCC_VERSION := $(call cc-version,) I386_GUESS := $(call cc-i386) # ------------------------- # Special include/lib dirs # ------------------------- DX_INC = $(TOPDIR)/dxsdk/sdk/inc ST_INC = $(TOPDIR)/scitech/include ST_LIBDIR = scitech/lib/win32/vc # --------------------------------------- # Define some build variables # --------------------------------------- STRIP ?= strip WINDRES ?= windres CFLAGS ?= CFLAGS := $(CFLAGS) -Wall -Wno-trigraphs ifeq ($(DEBUG),Y) CFLAGS += -g else ifeq ($(OPTIMIZED_CFLAGS),Y) CFLAGS += -O2 # -funit-at-a-time is buggy for MinGW GCC > 3.2 # I'm assuming it's fixed for MinGW GCC >= 4.0 when that comes about CFLAGS += $(shell if [ $(GCC_VERSION) -lt 0400 ] ;\ then echo $(call cc-option,-fno-unit-at-a-time,); fi ;) CFLAGS += $(call cc-option,-fweb,) CFLAGS += $(call cc-option,-frename-registers,) CFLAGS += $(call cc-option,-ffast-math,) endif endif # -------------------------------------------------------------------------- # Each binary needs to build it's own object files in separate directories # due to the {NQ,QW}_HACK ifdefs still present in the common files. # -------------------------------------------------------------------------- # (sw = software renderer, gl = OpenGL renderer, sv = server) NQSWDIR = $(BUILD_DIR)/nqsw NQGLDIR = $(BUILD_DIR)/nqgl QWSWDIR = $(BUILD_DIR)/qwsw QWGLDIR = $(BUILD_DIR)/qwgl QWSVDIR = $(BUILD_DIR)/qwsv APPS = tyr-quake$(EXT) tyr-glquake$(EXT) \ tyr-qwcl$(EXT) tyr-glqwcl$(EXT) \ tyr-qwsv$(EXT) default: all all: $(patsubst %,$(BIN_DIR)/%,$(APPS)) # To make warnings more obvious, be less verbose as default # Use 'make V=1' to see the full commands ifdef V quiet = else quiet = quiet_ endif quiet_cmd_mkdir = ' MKDIR $(@D)' cmd_mkdir = mkdir -p $(@D) define do_mkdir @if [ ! -d $(@D) ]; then \ echo $($(quiet)cmd_mkdir); \ $(cmd_mkdir); \ fi endef # cmd_fixdep => Turn all pre-requisites into targets with no commands, to # prevent errors when moving files around between builds (e.g. from NQ or QW # dirs to the common dir.) cmd_fixdep = \ cp $(@D)/.$(@F).d $(@D)/.$(@F).d.tmp ; \ sed -e 's/\#.*//' -e 's/^[^:]*: *//' -e 's/ *\\$$//' -e '/^$$/ d' \ -e 's/$$/ :/' < $(@D)/.$(@F).d.tmp >> $(@D)/.$(@F).d ; \ rm -f $(@D)/.$(@F).d.tmp cmd_cc_dep_c = \ $(CC) -MM -MT $@ $(CPPFLAGS) -o $(@D)/.$(@F).d $< ; \ $(cmd_fixdep) quiet_cmd_cc_o_c = ' CC $@' cmd_cc_o_c = $(CC) -c $(CPPFLAGS) $(CFLAGS) -o $@ $< define do_cc_o_c @$(do_mkdir); @$(cmd_cc_dep_c); @echo $($(quiet)cmd_cc_o_c); @$(cmd_cc_o_c); endef cmd_cc_dep_rc = \ $(CC) -x c-header -MM -MT $@ $(CPPFLAGS) -o $(@D)/.$(@F).d $< ; \ $(cmd_fixdep) quiet_cmd_windres_res_rc = ' WINDRES $@' cmd_windres_res_rc = $(WINDRES) -I $(