diff --git a/.gitignore b/.gitignore index cadaacd..e607722 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,5 @@ /build/ -/release/ \ No newline at end of file +/release/ +*.mk +*.user +*.d diff --git a/Makefile b/Makefile index 5f60792..0ab6c30 100644 --- a/Makefile +++ b/Makefile @@ -17,6 +17,54 @@ # - Windows # # ----------------------------------------------------- # +# Variables +# --------- +# ASAN +# Builds with address sanitizer, includes DEBUG. +# DEBUG +# Builds a debug build, forces -O0 and adds debug symbols. +# MINGW_CHOST +# If you use mingw this can specify architecture. +# Available values: +# x86_64-w64-mingw32 -> indicates x86_64 +# i686-w64-mingw32 -> indicates i386 +# QUIET +# If defined, "===> CC ..." lines are silenced. +# SOURCE_DATE_EPOCH +# For reproduceable builds, look here for details: +# https://reproducible-builds.org/specs/source-date-epoch/ +# If set, adds a BUILD_DATE define to CFLAGS. +# UBSAN +# Builds with undefined behavior sanitizer.includes DEBUG. +# VERBOSE +# Prints full compile, linker and misc commands. +# WERR +# Treat compiler warnings as errors. +# If defined, -Werror is added to compiler flags. +# ---------- + +# User configurable options +# ------------------------- + +# CONFIG_FILE +# This is an optional configuration file, it'll be used in +# case of presence. +CONFIG_FILE:=config.mk + +# ---------- + +# In case of a configuration file being present, we'll just use it +ifeq ($(wildcard $(CONFIG_FILE)), $(CONFIG_FILE)) +include $(CONFIG_FILE) +endif + +# Normalize QUIET value to either "x" or "" +ifdef QUIET + override QUIET := "x" +else + override QUIET := "" +endif + # Detect the OS ifdef SystemRoot YQ2_OSTYPE ?= Windows @@ -71,24 +119,58 @@ else COMPILER := unknown endif +# ASAN includes DEBUG +ifdef ASAN +DEBUG=1 +endif + +# UBSAN includes DEBUG +ifdef UBSAN +DEBUG=1 +endif + +# ---------- + +# Set up build and bin output directories + +# Root dir names +override BINROOT := +override BUILDROOT := build + +override BINDIR := $(BINROOT)release +override BUILDDIR := $(BUILDROOT) + # ---------- # Base CFLAGS. These may be overridden by the environment. # Highest supported optimizations are -O2, higher levels # will likely break this crappy code. ifdef DEBUG -CFLAGS ?= -O0 -g -Wall -pipe +CFLAGS ?= -O0 -g -Wall -pipe -DDEBUG +ifdef ASAN +override CFLAGS += -fsanitize=address -DUSE_SANITIZER +endif +ifdef UBSAN +override CFLAGS += -fsanitize=undefined -DUSE_SANITIZER +endif else CFLAGS ?= -O2 -Wall -pipe -fomit-frame-pointer endif +# Optionally treat warnings as errors +ifdef WERR +override CFLAGS += -Werror +endif + # Always needed are: # -fno-strict-aliasing since the source doesn't comply # with strict aliasing rules and it's next to impossible # to get it there... # -fwrapv for defined integer wrapping. MSVC6 did this # and the game code requires it. -override CFLAGS += -fno-strict-aliasing -fwrapv +# -fvisibility=hidden to keep symbols hidden. This is +# mostly best practice and not really necessary. +override CFLAGS += -fno-strict-aliasing -fwrapv -fvisibility=hidden # -MMD to generate header dependencies. Unsupported by # the Clang shipped with OS X. @@ -124,8 +206,6 @@ override CFLAGS += -DYQ2OSTYPE=\"$(YQ2_OSTYPE)\" -DYQ2ARCH=\"$(YQ2_ARCH)\" # ---------- -# For reproduceable builds, look here for details: -# https://reproducible-builds.org/specs/source-date-epoch/ ifdef SOURCE_DATE_EPOCH CFLAGS += -DBUILD_DATE=\"$(shell date --utc --date="@${SOURCE_DATE_EPOCH}" +"%b %_d %Y" | sed -e 's/ /\\ /g')\" endif @@ -154,7 +234,17 @@ LDFLAGS ?= # It's a shared library. override LDFLAGS += -shared -# Required libaries +# Link address sanitizer if requested. +ifdef ASAN +override LDFLAGS += -fsanitize=address +endif + +# Link undefined behavior sanitizer if requested. +ifdef UBSAN +override LDFLAGS += -fsanitize=undefined +endif + +# Required libraries ifeq ($(YQ2_OSTYPE), Darwin) override LDFLAGS += -arch $(YQ2_ARCH) else ifeq ($(YQ2_OSTYPE), Windows) @@ -163,6 +253,19 @@ else override LDFLAGS += -lm endif +# ASAN and UBSAN must not be linked +# with --no-undefined. OSX and OpenBSD +# don't support it at all. +ifndef ASAN +ifndef UBSAN +ifneq ($(YQ2_OSTYPE), Darwin) +ifneq ($(YQ2_OSTYPE), OpenBSD) +override LDFLAGS += -Wl,--no-undefined +endif +endif +endif +endif + # ---------- # Builds everything @@ -197,24 +300,26 @@ clean: ifeq ($(YQ2_OSTYPE), Windows) xatrix: @echo "===> Building game.dll" - ${Q}mkdir -p release - ${MAKE} release/game.dll + ${Q}mkdir -p $(BINDIR) + ${MAKE} $(BINDIR)/game.dll else ifeq ($(YQ2_OSTYPE), Darwin) xatrix: @echo "===> Building game.dylib" - ${Q}mkdir -p release - $(MAKE) release/game.dylib + ${Q}mkdir -p $(BINDIR) + $(MAKE) $(BINDIR)/game.dylib else xatrix: @echo "===> Building game.so" - ${Q}mkdir -p release - $(MAKE) release/game.so + ${Q}mkdir -p $(BINDIR) + $(MAKE) $(BINDIR)/game.so -release/game.so : CFLAGS += -fPIC +$(BINDIR)/game.so : CFLAGS += -fPIC endif -build/%.o: %.c - @echo "===> CC $<" +$(BUILDDIR)/%.o: %.c + @if [ -z $(QUIET) ]; then\ + echo "===> CC $<";\ + fi ${Q}mkdir -p $(@D) ${Q}$(CC) -c $(CFLAGS) -o $@ $< @@ -277,7 +382,7 @@ XATRIX_OBJS_ = \ # ---------- # Rewrite paths to our object directory -XATRIX_OBJS = $(patsubst %,build/%,$(XATRIX_OBJS_)) +XATRIX_OBJS = $(patsubst %,$(BUILDDIR)/%,$(XATRIX_OBJS_)) # ---------- @@ -292,15 +397,15 @@ XATRIX_DEPS= $(XATRIX_OBJS:.o=.d) # ---------- ifeq ($(YQ2_OSTYPE), Windows) -release/game.dll : $(XATRIX_OBJS) +$(BINDIR)/game.dll : $(XATRIX_OBJS) @echo "===> LD $@" ${Q}$(CC) -o $@ $(XATRIX_OBJS) $(LDFLAGS) else ifeq ($(YQ2_OSTYPE), Darwin) -release/game.dylib : $(XATRIX_OBJS) +$(BINDIR)/game.dylib : $(XATRIX_OBJS) @echo "===> LD $@" ${Q}$(CC) -o $@ $(XATRIX_OBJS) $(LDFLAGS) else -release/game.so : $(XATRIX_OBJS) +$(BINDIR)/game.so : $(XATRIX_OBJS) @echo "===> LD $@" ${Q}$(CC) -o $@ $(XATRIX_OBJS) $(LDFLAGS) endif