# AQ2 JMod game library Makefile
#
# Common targets:
#   make              Build native Linux shared library: gamex86_64.so
#   make debug        Build native Linux debug library
#   make win64        Cross-compile Windows x64 DLL: gamex86_64.dll
#   make clean        Remove objects for the current target/build
#   make distclean    Remove all generated build output
#   make install      Copy the native Linux .so to INSTALL_DIR
#
# Useful overrides:
#   make -j BUILD=debug
#   make win64 MINGW_PREFIX=x86_64-w64-mingw32
#   make install INSTALL_DIR=/home/jordan/quake2/action TARGET_NAME=gamex86_64.jump.so
#   make AQTION_EXTENSION=1    Enable AQTION extension API, if your engine expects it

TARGET_OS ?= linux
BUILD ?= release
AQTION_EXTENSION ?= 0

# GNU make has a built-in CC=cc. Replace that default with a target-appropriate compiler,
# but still allow command-line overrides such as `make CC=clang`.
ifeq ($(origin CC),default)
  ifeq ($(TARGET_OS),win64)
    MINGW_PREFIX ?= x86_64-w64-mingw32
    CC := $(MINGW_PREFIX)-gcc
  else
    CC := gcc
  endif
endif

ifeq ($(TARGET_OS),win64)
  ARCH ?= x86_64
  TARGET_EXT := dll
  TARGET_NAME ?= game$(ARCH).$(TARGET_EXT)
  OBJDIR := build/$(TARGET_OS)-$(BUILD)
  PLATFORM_CPPFLAGS := -Dstricmp=_stricmp
  PLATFORM_CFLAGS :=
  PLATFORM_LDFLAGS := -shared -Wl,--enable-stdcall-fixup -Wl,--out-implib,$(OBJDIR)/libgame.a game.def
  PLATFORM_LIBS := -lm
else ifeq ($(TARGET_OS),linux)
  ARCH ?= $(shell uname -m | sed 's/^i.86/i386/' | sed 's/^aarch64/arm64/')
  TARGET_EXT := so
  TARGET_NAME ?= game$(ARCH).$(TARGET_EXT)
  OBJDIR := build/$(TARGET_OS)-$(ARCH)-$(BUILD)
  PLATFORM_CPPFLAGS := -Dstricmp=strcasecmp
  PLATFORM_CFLAGS := -fPIC
  PLATFORM_LDFLAGS := -shared
  PLATFORM_LIBS := -ldl -lm
else
  $(error Unsupported TARGET_OS '$(TARGET_OS)'. Use linux or win64.)
endif

ifeq ($(BUILD),debug)
  BUILD_CFLAGS := -O0 -g3 -fno-omit-frame-pointer -fcommon -DDEBUG
else ifeq ($(BUILD),release)
  BUILD_CFLAGS := -O2 -g -fno-omit-frame-pointer -fcommon
else ifeq ($(BUILD),sanitize)
  ifneq ($(TARGET_OS),linux)
    $(error BUILD=sanitize is only supported for TARGET_OS=linux.)
  endif
  BUILD_CFLAGS := -O1 -g3 -fno-omit-frame-pointer -fcommon -fsanitize=address,undefined
  BUILD_LDFLAGS := -fsanitize=address,undefined
else
  $(error Unsupported BUILD '$(BUILD)'. Use release, debug, or sanitize.)
endif

COMMON_WARNINGS := -Wall -Wextra -Wformat=2 -Wformat-security -Wno-unused-parameter -Wno-missing-field-initializers
COMMON_CPPFLAGS := $(PLATFORM_CPPFLAGS)

ifeq ($(AQTION_EXTENSION),1)
  COMMON_CPPFLAGS += -DAQTION_EXTENSION
endif

CPPFLAGS += $(COMMON_CPPFLAGS)
CFLAGS += $(BUILD_CFLAGS) $(COMMON_WARNINGS) $(PLATFORM_CFLAGS)
LDFLAGS += $(BUILD_LDFLAGS) $(PLATFORM_LDFLAGS)
LDLIBS += $(PLATFORM_LIBS)

SOURCES := \
  g_ai.c g_cmds.c g_combat.c g_func.c g_items.c g_main.c g_misc.c \
  g_monster.c g_phys.c g_save.c g_spawn.c g_svcmds.c \
  g_target.c g_trigger.c g_turret.c g_utils.c g_weapon.c g_chase.c \
  p_client.c p_hud.c p_trail.c p_view.c p_weapon.c q_shared.c \
  m_move.c a_team.c a_game.c a_items.c a_cmds.c a_radio.c a_menu.c \
  cgf_sfx_glass.c a_doorkick.c \
  g_puppet.c g_lasertrail.c g_mapvote.c g_marker.c g_puppetdemo.c

OBJECTS := $(patsubst %.c,$(OBJDIR)/%.o,$(SOURCES))
DEPS := $(OBJECTS:.o=.d)
TARGET := $(TARGET_NAME)
INSTALL_DIR ?= ../quake2/action

.PHONY: all linux win64 release debug sanitize clean distclean install help print-config

all: $(TARGET)

linux:
	$(MAKE) TARGET_OS=linux BUILD=$(BUILD) all

win64:
	$(MAKE) TARGET_OS=win64 BUILD=$(BUILD) all

release:
	$(MAKE) TARGET_OS=$(TARGET_OS) BUILD=release all

debug:
	$(MAKE) TARGET_OS=$(TARGET_OS) BUILD=debug all

sanitize:
	$(MAKE) TARGET_OS=linux BUILD=sanitize all

$(TARGET): $(OBJECTS)
	$(CC) $(OBJECTS) $(LDFLAGS) -o $@ $(LDLIBS)

$(OBJDIR)/%.o: %.c | $(OBJDIR)
	$(CC) $(CPPFLAGS) $(CFLAGS) -MMD -MP -c $< -o $@

$(OBJDIR):
	mkdir -p $@

install: all
	install -d "$(INSTALL_DIR)"
	cp -f "$(TARGET)" "$(INSTALL_DIR)/$(TARGET_NAME)"

clean:
	rm -rf "$(OBJDIR)"
	rm -f "$(TARGET)"

distclean:
	rm -rf build
	rm -f game*.so game*.dll game*.dylib *.a

print-config:
	@echo "TARGET_OS=$(TARGET_OS)"
	@echo "BUILD=$(BUILD)"
	@echo "ARCH=$(ARCH)"
	@echo "CC=$(CC)"
	@echo "TARGET=$(TARGET)"
	@echo "OBJDIR=$(OBJDIR)"
	@echo "CPPFLAGS=$(CPPFLAGS)"
	@echo "CFLAGS=$(CFLAGS)"
	@echo "LDFLAGS=$(LDFLAGS)"
	@echo "LDLIBS=$(LDLIBS)"
	@echo "AQTION_EXTENSION=$(AQTION_EXTENSION)"

help:
	@sed -n '1,23p' Makefile

-include $(DEPS)
