# OS package maintainers: Please try invoking make with PACKAGE_REPOSITORY=1 to see if that meets your needs before patching out our optimizations entirely.
PACKAGE_REPOSITORY ?= 0

# Use colored output. Disable for build system debugging.
PRETTY_OUTPUT ?= 1

# Tools
CROSS=
ifneq ($(CROSS),)
    undefine CC
    undefine CXX
    undefine AR
    undefine RC
    undefine RANLIB
    undefine STRIP
endif

CC=$(CROSS)gcc
CXX=$(CROSS)g++
AR=$(CROSS)ar
RC=$(CROSS)windres
RANLIB=$(CROSS)ranlib
STRIP=$(CROSS)strip
AS=nasm
PKG_CONFIG=pkg-config

DONT_PRINT = > /dev/null 2>&1
DONT_FAIL = ; exit 0

# Override defaults that absolutely will not work.
ifeq ($(CC),cc)
    override CC=gcc
endif
ifeq ($(AS),as)
    override AS=nasm
endif

COBJC=$(CC)
L_CC=$(CC)
L_CXX=$(CXX)

CCFULLPATH=$(CC)

ifeq ($(PLATFORM),WII)
    ifeq ($(strip $(DEVKITPPC)),)
        $(error "Please set DEVKITPPC in your environment. export DEVKITPPC=<path to>devkitPPC")
    endif

    include $(DEVKITPPC)/wii_rules

    CCFULLPATH=$(DEVKITPPC)/bin/$(CC)

    CROSS=powerpc-eabi-
    RANLIB=powerpc-eabi-ranlib
    STRIP=powerpc-eabi-strip
    ELF2DOL=elf2dol
    DOLSUFFIX=.dol
endif

CLANG?=0

CLANG_POTENTIAL_VERSION := $(shell $(CCFULLPATH) --version)

ifeq ($(findstring clang,$(CC)),clang)
    override CLANG=1
endif
# detect clang symlinked as gcc, as in OS X
ifeq ($(findstring clang,$(CLANG_POTENTIAL_VERSION)),clang)
    override CLANG=1
endif

ifneq (0,$(CLANG))
    override CC=clang -x c
    override CXX=clang -x c++
    override COBJC=clang -x objective-c
    override L_CC=clang
    override L_CXX=clang
endif

# GCC version, for conditional selection of flags.
ifndef GCC_MAJOR
    GCC_MAJOR    := $(shell $(CCFULLPATH) -dumpversion 2>&1 | cut -d'.' -f1)
endif
ifeq ($(GCC_MAJOR),)
    GCC_MAJOR    := 4
endif
ifndef GCC_MINOR
    GCC_MINOR    := $(shell $(CCFULLPATH) -dumpversion 2>&1 | cut -d'.' -f2)
endif
ifeq ($(GCC_MINOR),)
    GCC_MINOR    := 8
endif

# Detect machine architecture
ifndef SYSARCH
    SYSARCH:=$(strip $(shell uname -m))
endif
SYSBITS=32

# Detect the platform if it wasn't explicitly given to us from
# the outside world. This allows cross-compilation by overriding
# CC and giving us PLATFORM specifically.
#
ifndef HOSTPLATFORM
    uname:=$(strip $(shell uname -s))
    HOSTPLATFORM=UNKNOWN
    ifeq ($(findstring Linux,$(uname)),Linux)
        HOSTPLATFORM=LINUX
    endif
    ifeq ($(findstring BSD,$(uname)),BSD)
        HOSTPLATFORM=BSD
    endif
    ifeq ($(findstring MINGW,$(uname)),MINGW)
        HOSTPLATFORM=WINDOWS
    endif
    ifeq ($(findstring Darwin,$(uname)),Darwin)
        HOSTPLATFORM=DARWIN
    endif
    ifeq ($(findstring BeOS,$(uname)),BeOS)
        HOSTPLATFORM=BEOS
    endif
    ifeq ($(findstring skyos,$(uname)),skyos)
        HOSTPLATFORM=SKYOS
    endif
    ifeq ($(findstring QNX,$(uname)),QNX)
        HOSTPLATFORM=QNX
    endif
    ifeq ($(findstring SunOS,$(uname)),SunOS)
        HOSTPLATFORM=SUNOS
    endif
    ifeq ($(findstring syllable,$(uname)),syllable)
        HOSTPLATFORM=SYLLABLE
    endif
endif
ifndef PLATFORM
    PLATFORM=$(HOSTPLATFORM)
endif

ifndef SUBPLATFORM
    SUBPLATFORM=
    ifeq ($(PLATFORM),LINUX)
        SUBPLATFORM=LINUX
    endif
    ifeq ($(PLATFORM),DINGOO)
        SUBPLATFORM=LINUX
        CROSS=mipsel-linux-
    endif
    ifeq ($(PLATFORM),GCW)
        SUBPLATFORM=LINUX
        CROSS=mipsel-linux-
    endif
    ifeq ($(PLATFORM),CAANOO)
        SUBPLATFORM=LINUX
    endif
endif

# Binary suffix override:
EXESUFFIX_OVERRIDE ?=

# Are we running from synthesis?
SYNTHESIS ?= 0

# Mac OS X Frameworks location
# Like above, use absolute paths.
APPLE_FRAMEWORKS ?=/Library/Frameworks
# Without the resource files packaged in the .app bundle, the startupwindow produces errors, so give it an off switch.
OSX_STARTUPWINDOW ?= 1

# Engine options
#  USE_OPENGL     - enables basic OpenGL Polymost renderer
#  POLYMER        - enables fancy Polymer renderer
#  NOASM          - disables the use of inline assembly pragmas
#  LINKED_GTK     - enables compile-time linkage to GTK
#
POLYMER = 1
USE_OPENGL = 1
NOASM = 0
LINKED_GTK = 0
BUILD32_ON_64 ?= 0
USE_LIBPNG ?= 1
USE_LIBVPX ?= 1
HAVE_VORBIS ?= 1
HAVE_FLAC ?= 1
NETCODE ?= 1

LUNATIC ?= 0
USE_LUAJIT_2_1 ?= 0

# EXPERIMENTAL, unfinished x86_64 assembly routines. DO NOT ENABLE.
USE_ASM64 ?= 0

ifeq (0,$(USE_OPENGL))
    POLYMER = 0
    USE_LIBVPX = 0
endif

# Debugging/Build options
#  CPLUSPLUS - 1 = enable C++ building
#  RELEASE - 1 = no debugging
#  DEBUGANYWAY:
#    1 = Include debug symbols even when generating release code.
#    2 = Also enable sanitizers with Clang. On the C side, make 'sprite' etc. be real arrays.
#  DISABLEINLINING - 1 = compile inline functions as extern __fastcall instead of static inline
#  KRANDDEBUG - 1 = include logging of krand() calls for debugging the demo system
#  MEMMAP - 1 = produce .memmap file when linking
#  EFENCE  - 1 = compile with Electric Fence for malloc() debugging
#  OPTLEVEL - 0..3 = GCC optimization strategy
#  LTO - 1 = enable link-time optimization, for GCC 4.5 and up
#
CPLUSPLUS?=1
RELEASE?=1
DEBUGANYWAY?=0
KRANDDEBUG?=0
MEMMAP?=0
DISABLEINLINING?=0
EFENCE?=0
DMALLOC?=0
PROFILER?=0
MUDFLAP?=0

# Make allocache() a wrapper around malloc()? Useful for debugging
# allocache()-allocated memory accesses with e.g. Valgrind.
# For debugging with Valgrind + GDB, see
# http://valgrind.org/docs/manual/manual-core-adv.html#manual-core-adv.gdbserver
ALLOCACHE_AS_MALLOC?=0

# Select the default optimization level for release and debug builds.
ifeq ($(RELEASE),0)
    OPTLEVEL?=0
else
    OPTLEVEL?=2
endif

ifeq ($(RELEASE),0)
    override STRIP=
endif
ifneq ($(DEBUGANYWAY),0)
    override STRIP=
endif

ifneq ($(LUNATIC),0)
    # FIXME: Lunatic builds with LTO don't start up properly as the required
    # symbol names are apparently not exported.
    override LTO=0

    ifneq ($(CPLUSPLUS),0)
        $(error "Lunatic C++ build not supported")
    endif
endif

ifndef LTO
    LTO=1
    ifneq (0,$(CLANG))
        ifeq ($(PLATFORM), WINDOWS)
            LTO=0
        endif
    endif
endif

COMMONFLAGS=$(ARCH)
COMPILERFLAGS=

ifeq ($(PACKAGE_REPOSITORY),0)
    COMMONFLAGS += $(OPTIMIZATIONS)
endif

OPTIMIZATIONS=-O$(OPTLEVEL) $(OPTOPT)

DEBUGFLAG=-g
ifeq (0,$(CLANG))
    ifneq ($(PLATFORM),WII)
        DEBUGFLAG=-ggdb -fno-omit-frame-pointer
    endif
endif
ifneq ($(RELEASE)$(DEBUGANYWAY),10)
    # debug build or DEBUGANYWAY=1 --> -g flag
    OPTIMIZATIONS += $(DEBUGFLAG)
endif

CONLYFLAGS=-std=gnu99 -Wimplicit -Werror-implicit-function-declaration
CPPONLYFLAGS= -fno-exceptions -fno-rtti -Wno-write-strings
ASFORMAT=elf$(SYSBITS)
ASFLAGS=-s -f $(ASFORMAT) #-g
LINKERFLAGS=
LIBS=-lm
LIBDIRS=

ifeq (1,$(strip $(shell expr $(GCC_MAJOR) \>= 4)))
    F_NO_STACK_PROTECTOR := -fno-stack-protector
    # there are some link-time issues with stack protectors, so make it possible to override
    F_STACK_PROTECTOR_ALL ?= -fstack-protector-all
    ifeq (0,$(CLANG))
        F_JUMP_TABLES := -fjump-tables
    endif
    M_TUNE_GENERIC := -mtune=generic
    M_STACKREALIGN := -mstackrealign
    W_STRICT_OVERFLOW := -Wno-strict-overflow
endif

ifeq ($(HOSTPLATFORM),WINDOWS)
# MSYS2 lets you create files named NUL but has a /dev/null. Go figure.
    ifeq (,$(wildcard /dev/null))
        DONT_PRINT = > NUL 2>&1
    endif
endif

ifeq ($(PLATFORM),WINDOWS)
    ifndef COMPILERTARGET
        COMPILERTARGET:=$(strip $(shell $(CC) -dumpmachine))
    endif

    ifeq ($(findstring x86_64,$(COMPILERTARGET)),x86_64)
        SYSARCH:=x86_64
        SYSBITS=64
    endif

    WINLIB?=/$(SYSBITS)
else
ifneq (1,$(BUILD32_ON_64))
    ifeq ($(findstring x86_64,$(ARCH)),x86_64)
        SYSBITS=64
    endif
    ifeq ($(ARCH),)
        ifeq ($(findstring x86_64,$(SYSARCH)),x86_64)
            SYSBITS=64
        endif
    endif
endif
endif

ifeq ($(PLATFORM),DARWIN)
    ifndef DARWINVERSION
        DARWINVERSION:=$(strip $(shell uname -r | cut -d . -f 1))
    endif

    DARWIN9 ?= 0
    DARWIN10 ?= 0
    ifeq (1,$(strip $(shell expr $(DARWINVERSION) \< 10)))
        override DARWIN9 := 1
    endif
    ifeq (1,$(strip $(shell expr $(DARWINVERSION) \< 11)))
        override DARWIN10 := 1
    endif

#    COMMONFLAGS    += -fno-leading-underscore

    ifeq (1,$(DARWIN9))
        F_JUMP_TABLES :=
        W_STRICT_OVERFLOW :=
    endif

    ifeq (1,$(BUILD32_ON_64))
        COMMONFLAGS += $(F_NO_STACK_PROTECTOR)
    else
        ifeq ($(findstring ppc,$(ARCH)),ppc)
            COMMONFLAGS += $(F_NO_STACK_PROTECTOR)
        endif
    endif
    ifneq (0,$(OSX_STARTUPWINDOW))
        COMPILERFLAGS+= -DOSX_STARTUPWINDOW
    endif
endif


ifneq (0,$(RELEASE))
    # Debugging disabled
    COMMONFLAGS += $(F_NO_STACK_PROTECTOR)
else
    # Debugging enabled
    ifneq (0,$(KRANDDEBUG))
        COMMONFLAGS += -fno-inline -fno-inline-functions -fno-inline-functions-called-once
    endif
    ifeq (1,$(SDL_TARGET))
        COMPILERFLAGS += -DNOSDLPARACHUTE
    endif
endif

ifndef OPTOPT
    ifeq ($(PLATFORM), WII)
        OPTOPT=
    else
        OPTOPTARCH=$(ARCH)
        ifeq (,$(OPTOPTARCH))
            OPTOPTARCH=$(SYSARCH)
        endif

        ifeq (i686,$(findstring i686, $(OPTOPTARCH)))
            OPTOPT=-march=pentium3 $(M_TUNE_GENERIC) -mmmx
            # -msse2 -mfpmath=sse,387 -malign-double $(M_STACKREALIGN)
        else
            OPTOPT=
        endif
    endif
endif

ifneq (0,$(KRANDDEBUG))
    RELEASE=0
endif
ifneq (0,$(PROFILER))
    # XXX: Why?
    DEBUGANYWAY=1
endif




ifeq (1,$(strip $(shell expr $(GCC_MAJOR) \>= 4)))
    ifeq (1,$(strip $(shell expr $(GCC_MINOR) \>= 1)))
        COMPILERFLAGS+= -Wno-attributes
    endif
endif

ifeq ($(PLATFORM),WII)
    override USE_LIBVPX = 0
    override NETCODE = 0
    override HAVE_FLAC = 0
endif
ifeq ($(PLATFORM),GCW)
    override USE_LIBVPX = 0
endif
ifeq ($(PLATFORM),DINGOO)
    override USE_LIBVPX = 0
endif

ifneq (0,$(USE_LIBVPX))
    # On Windows, we link statically to libvpx
    LIBS+= -lvpx
endif


ifneq ($(ALLOCACHE_AS_MALLOC),0)
    COMPILERFLAGS += -DDEBUG_ALLOCACHE_AS_MALLOC
endif

# See http://clang.llvm.org/docs/UsersManual.html#controlling-code-generation
# for a list of possible UBSan options.
# Clang 3.2 does only supports -fsanitize=address for the AddressSanitizer
CLANG_DEBUG_FLAGS := -fsanitize=address -fsanitize=bounds,enum,float-cast-overflow,object-size
#CLANG_DEBUG_FLAGS := $(CLANG_DEBUG_FLAGS),signed-integer-overflow
#CLANG_DEBUG_FLAGS := $(CLANG_DEBUG_FLAGS),unsigned-integer-overflow
#CLANG_DEBUG_FLAGS := $(CLANG_DEBUG_FLAGS) -fsanitize-undefined-trap-on-error

ifneq (0,$(RELEASE))
    ## Debugging disabled

    ifeq (0,$(CLANG))
        COMMONFLAGS += -funswitch-loops
        ifeq (1,$(strip $(shell expr $(GCC_MAJOR) \< 4)))
            override LTO=0
        endif
        ifeq (1,$(strip $(shell expr $(GCC_MAJOR) = 4)))
            ifeq ($(PLATFORM),WII)
                ifeq (1,$(strip $(shell expr $(GCC_MINOR) \< 8)))
                    override LTO=0
                endif
            else
                ifeq (1,$(strip $(shell expr $(GCC_MINOR) \< 6)))
                    override LTO=0
                endif
            endif
        endif
    endif

    ifeq (0,$(DEBUGANYWAY))
        COMMONFLAGS += -fomit-frame-pointer
        COMPILERFLAGS += -DNDEBUG
    else
        # Our $(DEBUGANYWAY) -> DEBUGGINGAIDS #define
        COMPILERFLAGS += -DDEBUGGINGAIDS=$(DEBUGANYWAY)
        ifneq (0,$(CLANG))
            ifeq (2,$(DEBUGANYWAY))
                COMMONFLAGS += $(CLANG_DEBUG_FLAGS)
            endif
        endif
    endif

    ifneq (0,$(LTO))
        COMPILERFLAGS += -DUSING_LTO
        COMMONFLAGS += -flto
    endif
else
    ## Debugging enabled

    # Our $(DEBUGANYWAY) -> DEBUGGINGAIDS #define
    COMPILERFLAGS += -DDEBUGGINGAIDS=$(DEBUGANYWAY)
    ifneq (0,$(CLANG))
        ifeq (2,$(DEBUGANYWAY))
            COMMONFLAGS += $(CLANG_DEBUG_FLAGS)
        endif
    endif

    ifeq ($(SUBPLATFORM),LINUX)
        LIBS+=-rdynamic
    endif

    ifneq (0,$(MUDFLAP))
        LIBS+= -lmudflapth
        COMMONFLAGS += -fmudflapth
    endif
    ifneq (0,$(PROFILER))
        ifneq ($(PLATFORM),DARWIN)
            LIBS+= -lprofiler
        endif
        COMMONFLAGS += -pg
    endif
    ifneq (0,$(KRANDDEBUG))
        COMPILERFLAGS += -DKRANDDEBUG=1
    endif
endif

W_NO_UNUSED_RESULT :=
ifeq (0,$(CLANG))
#    W_NO_UNUSED_RESULT := $(shell echo '' | $(CC) -E -Wno-unused-result - 2>/dev/null && echo -Wno-unused-result)
#    W_NO_UNUSED_RESULT := $(findstring -Wno-unused-result,$(W_NO_UNUSED_RESULT))
    ifeq (1,$(strip $(shell expr $(GCC_MAJOR) \>= 4)))
        ifeq (1,$(strip $(shell expr $(GCC_MINOR) \>= 4)))
            W_NO_UNUSED_RESULT := -Wno-unused-result
        endif
    endif
endif

CWARNS := -W -Wall \
    -Wpointer-arith \
    -Wextra \
    -Wno-char-subscripts \
    #-Wstrict-prototypes \
    #-Waggregate-return \
    #-Wwrite-strings \
    #-Wcast-qual -Wcast-align \
    #-Waddress -Wlogical-op

ifneq (0,$(CLANG))
    CWARNS+= -Wno-unused-value -Wno-parentheses -Wno-missing-braces
endif

COMMONFLAGS+= -funsigned-char -fno-strict-aliasing $(F_JUMP_TABLES)

COMPILERFLAGS+= $(CWARNS) $(W_NO_UNUSED_RESULT) -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0

ifeq (0,$(NETCODE))
    COMPILERFLAGS+= -DNETCODE_DISABLE
endif


#### Lunatic development
# LuaJIT standalone interpreter executable:
LUAJIT:=luajit
# Options to "luajit -b" for synthesis. Since it runs on Linux, we need to tell
# the native LuaJIT to emit PE object files.
ifeq ($(PLATFORM),WINDOWS)
    LUAJIT_BCOPTS := -o windows
    ifeq (32,$(SYSBITS))
        LUAJIT_BCOPTS += -a x86
    endif
    ifeq (64,$(SYSBITS))
        LUAJIT_BCOPTS += -a x64
    endif
endif

ifneq ($(LUNATIC),0)
    # FIXME: Lunatic doesn't build with inlining because of wacky include
    # chains!
    override DISABLEINLINING=1

    ifneq ($(CPLUSPLUS),0)
        # FIXME: Lunatic C++ doesn't build because otherwise it doesn't find
        # INT32_MIN and the like.
        COMPILERFLAGS+= -D__STDC_LIMIT_MACROS
    endif

    COMPILERFLAGS+= -Isource/lunatic -DLUNATIC
    ifneq ($(USE_LUAJIT_2_1),0)
        COMPILERFLAGS+= -DUSE_LUAJIT_2_1
    endif

    # Determine size of defs.ilua bytecode once.
    ifndef DEFS_BC_SIZE
        DEFS_BC_SIZE := $(shell $(LUAJIT) -bg -t h source/lunatic/defs.ilua -)
        DEFS_BC_SIZE := $(word 3, $(DEFS_BC_SIZE))
        # Pass it to the sub-makes, too.
        export DEFS_BC_SIZE
    endif
    # Determine size of defs_m32.ilua bytecode once.
    ifndef DEFS_M32_BC_SIZE
        DEFS_M32_BC_SIZE := $(shell $(LUAJIT) -bg -t h source/lunatic/defs_m32.ilua -)
        DEFS_M32_BC_SIZE := $(word 3, $(DEFS_M32_BC_SIZE))
        export DEFS_M32_BC_SIZE
    endif
    COMPILERFLAGS+= -DLUNATIC_DEFS_BC_SIZE=$(DEFS_BC_SIZE) -DLUNATIC_DEFS_M32_BC_SIZE=$(DEFS_M32_BC_SIZE)

    ifeq ($(PLATFORM),WINDOWS)
        LIBS+= -lluajit
    else
        LIBS+= -lluajit-5.1
    endif
endif

####

ifneq (0,$(DISABLEINLINING))
    COMPILERFLAGS+= -DDISABLE_INLINING
endif

# This should come from the environment:
ifdef EDUKE32_MY_DEVELOPER_ID
    COMPILERFLAGS+= -DMY_DEVELOPER_ID=$(EDUKE32_MY_DEVELOPER_ID)
endif

ifneq (0,$(USE_LIBPNG))
    COMPILERFLAGS+= -DUSE_LIBPNG
endif
ifneq (0,$(USE_LIBVPX))
    COMPILERFLAGS+= -DUSE_LIBVPX
endif

ifneq (0,$(HAVE_VORBIS))
    COMPILERFLAGS+= -DHAVE_VORBIS
endif
ifneq (0,$(HAVE_FLAC))
    COMPILERFLAGS+= -DHAVE_FLAC
endif
ifneq (0,$(EFENCE))
    LIBS+= -lefence
    COMPILERFLAGS+= -DEFENCE
endif
ifneq (0,$(DMALLOC))
    LIBS+= -ldmalloc
    COMPILERFLAGS+= -DDMALLOC
endif

# may be overridden
EXESUFFIX=
DLLSUFFIX=.so


SDL_TARGET ?= 2
SDL_FRAMEWORK ?= 0

ifeq (1,$(strip $(shell expr $(GCC_MAJOR) \>= 4)))
    L_SSP := -lssp
endif

# NOTE: If your setup doesn't have libstdc++, you can try using libsupc++.
# Search for STDCPPLIB below and change it to -lsupc++.

SDL_INCLUDES=-I$(SDLROOT)/include -I$(SDLROOT)/include/SDL
SDL_LIB=-l$(SDLNAME)
SDL_MIXER_LIB=-l$(SDLNAME)_mixer

ifeq ($(SUBPLATFORM),LINUX)
    RENDERTYPE=SDL
    MIXERTYPE=SDL
    COMPILERFLAGS+= -DHAVE_INTTYPES
    GTKCOMPAT32=0
    SDL_FRAMEWORK=0

    # On Linux, we don't need to specify libstdc++ manually, the linker will
    # presumably take care for us.
    STDCPPLIB:=

    ifeq ($(PLATFORM),GCW)
        override USE_OPENGL=0
        override NOASM=1
    endif
    ifeq ($(PLATFORM),DINGOO)
        override USE_OPENGL=0
        override NOASM=1
    endif

    ifeq ($(findstring x86_64,$(SYSARCH)),x86_64)
        ifeq (1,$(BUILD32_ON_64))
            # On my 64bit Gentoo these are the 32bit emulation libs
            LIBS+= -m32
            LIBDIRS+= -L/emul/linux/x86/usr/lib
            COMMONFLAGS+= -m32
            # Override WITHOUT_GTK=0
            GTKCOMPAT32=1
        else
            override NOASM=1
        endif
    endif

    LIBS+= -lrt
    ifeq (0,$(CLANG))
        COMMONFLAGS += -fno-pic
    endif
endif
ifeq ($(PLATFORM),DARWIN)
    COMPILERFLAGS+= -DUNDERSCORES
    ASFORMAT=macho$(SYSBITS)
    ASFLAGS+= -DUNDERSCORES
    # ASM on OS X crashes in mmxoverlay()
    override NOASM=1

    # LIBDIRS+= -Lplatform/Apple/lib
    # COMPILERFLAGS+= -Iplatform/Apple/include

    ifneq ($(shell port --version &>/dev/null; echo $$?),127)
        LIBDIRS+= -L/opt/local/lib
        COMPILERFLAGS+= -I/opt/local/include
    endif
    ifneq ($(shell brew --version &>/dev/null; echo $$?),127)
        LIBDIRS+= -L/usr/local/lib
        COMPILERFLAGS+= -I/usr/local/include
    endif
    ifneq ($(shell fink --version &>/dev/null; echo $$?),127)
        LIBDIRS+= -L/sw/lib
        COMPILERFLAGS+= -I/sw/include
    endif

    RENDERTYPE    = SDL
    MIXERTYPE     = SDL
    STDCPPLIB:=-lstdc++
    COMPILERFLAGS    += -DHAVE_INTTYPES
    DLLSUFFIX=.dylib
    GTKCOMPAT32    = 0
    WITHOUT_GTK   ?= 1

    ifeq (1,$(SDL_FRAMEWORK))
        SDL_INCLUDES=-I$(APPLE_FRAMEWORKS)/SDL.framework/Headers -I$(APPLE_FRAMEWORKS)/SDL_mixer.framework/Headers
        SDL_LIB=-l$(SDLNAME)main -Wl,-framework,SDL -Wl,-rpath -Wl,"@loader_path/../Frameworks"
        SDL_MIXER_LIB=-Wl,-framework,SDL_mixer
    endif

    ifeq (1,$(DARWIN9))
        COMPILERFLAGS += -DDARWIN9
    endif

    ifeq (1,$(BUILD32_ON_64))
        ARCH=-arch i386
    endif

    ifneq ($(findstring x86_64,$(ARCH)),x86_64)
        ifeq (,$(ARCH))
            ifneq ($(findstring x86_64,$(SYSARCH)),x86_64)
                LINKERFLAGS += -read_only_relocs suppress
            endif
        else
            LINKERFLAGS += -read_only_relocs suppress
        endif
    endif

    ifeq (0,$(CLANG))
        COMMONFLAGS += -fno-pic
    endif
endif
ifeq ($(PLATFORM),WINDOWS)
    COMPILERFLAGS+= -DUNDERSCORES -DHAVE_INTTYPES -Iplatform/Windows/include
    LINKERFLAGS+= -static-libgcc
    ASFORMAT=win$(SYSBITS)
    ASFLAGS+= -DUNDERSCORES

    # Windows types can be SDL or WIN
    RENDERTYPE?=SDL
    MIXERTYPE?=WIN
    ifneq ($(RENDERTYPE),SDL)
        ifeq ($(MIXERTYPE),SDL)
            MIXERTYPE:=WIN
        endif
    endif

    SDL_INCLUDES=
    ifeq ($(SDL_TARGET),1)
        SDL_MIXER_LIB=platform/Windows/lib$(WINLIB)/SDL_mixer.lib
    endif

    WITHOUT_GTK?=1
    SDLCONFIG=
    SDL_FRAMEWORK=1
    EXESUFFIX=.exe
    DLLSUFFIX=.dll
    LIBDIRS+= -Lplatform/Windows/lib$(WINLIB)
    LIBS+= -Wl,--enable-auto-import -lmingwex -lgdi32 -lcomctl32 -lwinmm $(L_SSP) -lwsock32 -lws2_32 -lshlwapi
    ifeq (0,$(CLANG))
        LIBS+= -mwindows
    endif
    #-lshfolder
    STDCPPLIB:=-lstdc++
    ifeq ($(findstring x86_64,$(SYSARCH)),x86_64)
        ifneq (1,$(BUILD32_ON_64))
            override NOASM=1
        endif
    endif

    COMMONFLAGS += -fno-pic
endif
ifeq ($(PLATFORM),BSD)
    COMPILERFLAGS+= -I/usr/local/include

    RENDERTYPE=SDL
    MIXERTYPE=SDL
    COMPILERFLAGS+= -DHAVE_INTTYPES
    ifneq ($(findstring i386,$(SYSARCH)),i386)
        override NOASM=1
    endif
    STDCPPLIB:=-lstdc++
endif
ifeq ($(PLATFORM),BEOS)
    override NOASM=1

    RENDERTYPE=SDL
    MIXERTYPE=SDL
    STDCPPLIB:=-lstdc++
endif
ifeq ($(PLATFORM),SKYOS)
    RENDERTYPE=SDL
    MIXERTYPE=SDL
    EXESUFFIX=.app
    override NOASM=1
    COMPILERFLAGS+= -DUNDERSCORES -I/boot/programs/sdk/include/sdl
    SDLCONFIG=
    LIBS+= -lSDL -lnet
endif
ifeq ($(PLATFORM),WII)
    RENDERTYPE=SDL
    MIXERTYPE=SDL
    SDL_INCLUDES=
    EXESUFFIX=.elf
    override USE_OPENGL=0
    override POLYMER=0
    override NOASM=1
    override WITHOUT_GTK=1
    # -msdata=eabi
    COMMONFLAGS+= -g -mtune=750 -meabi -mhard-float
    COMPILERFLAGS+= -DGEKKO -DHAVE_INTTYPES -D__POWERPC__ -I$(LIBOGC_INC) -I$(PORTLIBS)/include -Iplatform/Wii/include
    SDLCONFIG=
    SDL_TARGET=1
    SDL_FRAMEWORK=1
    LIBDIRS += -L$(LIBOGC_LIB) -L$(PORTLIBS)/lib -Lplatform/Wii/lib
endif
ifeq ($(PLATFORM),QNX)
    RENDERTYPE=SDL
    MIXERTYPE=SDL
    override USE_OPENGL=0
    override NOASM=1
    STDCPPLIB:=-lstdc++
    LIBS+= -lsocket
endif
ifeq ($(PLATFORM),SUNOS)
    RENDERTYPE=SDL
    MIXERTYPE=SDL
    override USE_OPENGL=0
    override NOASM=1
    STDCPPLIB:=-lstdc++
    LIBS+= -lsocket -lnsl
endif
ifeq ($(PLATFORM),SYLLABLE)
    RENDERTYPE=SDL
    MIXERTYPE=SDL
    override USE_OPENGL=0
    override NOASM=1
endif
ifeq ($(PLATFORM),GCW)
    COMPILERFLAGS += -D__OPENDINGUX__
endif
ifeq ($(PLATFORM),DINGOO)
    COMPILERFLAGS += -D__OPENDINGUX__
endif

ifneq ($(EXESUFFIX_OVERRIDE),)
    EXESUFFIX=$(EXESUFFIX_OVERRIDE)
endif

ifneq (0,$(CLANG))
    ifneq (,$(STDCPPLIB))
        STDCPPLIB:=-Xlinker $(STDCPPLIB)
    endif
endif

ifeq ($(SDL_TARGET),2)
    SDLCONFIG ?= sdl2-config
    SDLNAME ?= SDL2
endif
ifeq ($(SDL_TARGET),1)
    SDLCONFIG ?= sdl-config
    SDLNAME ?= SDL
endif

ifneq ($(SDLCONFIG),)
    SDLVERSION:=$(strip $(shell $(SDLCONFIG) --version))
    ifneq ($(SDLVERSION),)
        SDLROOT:=$(strip $(shell $(SDLCONFIG) --prefix))
    endif
endif

SDL_STATIC?=1

ifeq ($(RENDERTYPE),SDL)
    COMPILERFLAGS += -DSDL_TARGET=$(SDL_TARGET)

    ifeq ($(SDL_FRAMEWORK),1)
        COMPILERFLAGS += -DSDL_FRAMEWORK
    endif

    ifneq ($(PLATFORM),WINDOWS)
        ifeq ($(SDL_FRAMEWORK),1)
            ifeq ($(PLATFORM),DARWIN)
                LIBS        += -Wl,-framework,SDL
                COMPILERFLAGS+= -I$(APPLE_FRAMEWORKS)/SDL.framework/Headers \
                                -I$(APPLE_FRAMEWORKS)/SDL_mixer.framework/Headers
            endif
        else
            ifneq ($(SDLCONFIG),)
                SDLCONFIG_COMMONFLAGS:=$(subst -Dmain=SDL_main,,$(strip $(shell $(SDLCONFIG) --cflags)))
                SDLCONFIG_LIBS:=$(strip $(shell $(SDLCONFIG) --libs))

                LIBS+= $(SDLCONFIG_LIBS)
                COMMONFLAGS+= $(SDLCONFIG_COMMONFLAGS)
            endif
        endif
    else
        COMPILERFLAGS += -D_GNU_SOURCE=1
        ifneq ($(SDL_STATIC),0)
            ifneq ($(SDL_TARGET),1) # Since SDL2 is under the zlib license, link statically if possible.
                LIBS+= -static
            endif
        endif
        LIBS+= -l$(SDLNAME)main -l$(SDLNAME) -lmingw32 -lgdi32 -limm32 -lole32 -loleaut32 -lwinmm -lversion
    endif

    ifeq (1,$(WITHOUT_GTK))
        HAVE_GTK2=0
    else
        ifneq (No,$(shell $(PKG_CONFIG) --exists gtk+-2.0 || echo No))
            HAVE_GTK2=1
            # On my 64bit Gentoo box I have Cairo enabled which means the libs list includes
            # -lpangocairo-1.0 and -lcairo, however the 32bit compatibility libraries don't
            # include cairo, so we need to filter out those -l switches in order to link
            ifneq ($(LINKED_GTK),0)
                ifeq ($(GTKCOMPAT32),1)
                    LIBS+= $(shell $(PKG_CONFIG) --libs gtk+-2.0 | sed 's/\s-l\(pango\)\{0,1\}cairo\S*\s/ /g')
                else
                    LIBS+= $(shell $(PKG_CONFIG) --libs gtk+-2.0)
                endif
            endif
            COMPILERFLAGS += -DHAVE_GTK2 $(shell $(PKG_CONFIG) --cflags gtk+-2.0)
        else
            HAVE_GTK2=0
        endif
    endif

    COMPILERFLAGS += $(SDL_INCLUDES)
    ifneq ($(MIXERTYPE),WIN)
        LIBS += $(SDL_MIXER_LIB)
    endif
    LIBS += $(SDL_LIB)
endif
ifeq ($(RENDERTYPE),WIN)
    LIBS+= -ldxguid
endif

# SDL depends on these
ifeq ($(PLATFORM),WINDOWS)
    ifeq ($(RENDERTYPE),SDL)
    SDL_LIB:=-l$(SDLNAME)main $(SDL_LIB)
        ifeq ($(MIXERTYPE),WIN)
            LIBS+= -ldxguid_sdl
        endif
    endif
endif
ifeq ($(PLATFORM),WII)
    LIBS+= -laesnd_tueidj -lpng -lfat -lwiiuse -lbte -logc -lm -lwiikeyboard
endif

COMPILERFLAGS+= -DRENDERTYPE$(RENDERTYPE)=1 -DMIXERTYPE$(MIXERTYPE)=1 $(W_STRICT_OVERFLOW)

ifneq (0,$(USE_OPENGL))
    COMPILERFLAGS+= -DUSE_OPENGL
endif
ifneq (0,$(NOASM))
    COMPILERFLAGS+= -DNOASM
endif
ifneq (0,$(USE_ASM64))
    COMPILERFLAGS+= -DUSE_ASM64
endif
ifneq (0,$(LINKED_GTK))
    COMPILERFLAGS+= -DLINKED_GTK
endif

ifneq (0,$(POLYMER))
 ifneq (0,$(USE_OPENGL))
  COMPILERFLAGS+= -DPOLYMER
 endif
endif

STATICSTDCPP?=
ifeq (1,$(STATICSTDCPP))
    STATICSTDCPP= -static
endif
ifeq (0,$(STATICSTDCPP))
    STATICSTDCPP= -shared
endif


ifneq ($(PLATFORM),WINDOWS)
    ifneq ($(PLATFORM),WII)
        ifneq ($(PLATFORM),BSD)
            LIBS+= -ldl
        endif
        ifneq ($(PLATFORM),DARWIN)
            LIBS+= -pthread
        endif
    endif
endif

ifeq ($(PLATFORM),WINDOWS)
    ifneq ($(USE_LIBPNG),0)
        LIBS+= -lpng_mini -lz_mini
    endif
else
    ifeq ($(PLATFORM),DARWIN)
        ifneq ($(USE_LIBPNG),0)
            LIBS+= -lpng # -lz
        endif
    else
        ifneq ($(USE_LIBPNG),0)
            LIBS+= -lpng -lz
        endif
    endif
endif


ifeq ($(PLATFORM),WINDOWS)
    ifneq ($(findstring x86_64,$(COMPILERTARGET)),x86_64)
        LINKERFLAGS+= -Wl,--large-address-aware
    endif
endif

ifneq (0,$(MEMMAP))
ifeq ($(PLATFORM),DARWIN)
    LINKERFLAGS+=-Wl,-map -Wl,$@.memmap
else
    LINKERFLAGS+=-Wl,-Map=$@.memmap
endif
endif

ifneq (0,$(PROFILER))
    LINKERFLAGS+=-pg
endif
ifeq ($(PLATFORM),WII)
    LINKERFLAGS+= -mrvl -meabi -mhard-float -Wl,--gc-sections
    # -msdata=eabi
endif

# Detect version control revision, if applicable
ifeq (,$(VC_REV))
    ifneq (,$(wildcard EDUKE32_REVISION))
        VC_REV    := $(shell cat EDUKE32_REVISION)
    endif
endif
ifeq (,$(VC_REV))
    VC_REV    := $(shell svn info 2>&1 | grep Revision | cut -d' ' -f2)
endif
ifeq (,$(VC_REV))
    VC_REV    := $(shell git svn info 2>&1 | grep Revision | cut -d' ' -f2)
endif
ifneq (,$(VC_REV)$(VC_REV_CUSTOM))
    REVFLAG += -DREV="\"r$(VC_REV)$(VC_REV_CUSTOM)\""
endif

COMPILER=$(CC) $(CONLYFLAGS)
COMPILER_OBJC=$(COBJC) $(CONLYFLAGS)
LINKER=$(L_CC)
ifneq ($(CPLUSPLUS),0)
    COMPILER=$(CXX) $(CPPONLYFLAGS)
    LINKER=$(L_CXX)
endif

ifneq (,$(CUSTOMOPT))
    COMMONFLAGS+= $(CUSTOMOPT)
endif
ifneq (,$(CFLAGS))
    COMMONFLAGS+= $(CFLAGS)
endif
ifneq (,$(CXXFLAGS))
    CPPONLYFLAGS+= $(CXXFLAGS)
endif
ifneq (,$(LDFLAGS))
    LINKERFLAGS+= $(LDFLAGS)
endif

ifeq ($(PRETTY_OUTPUT),1)
RECIPE_IF = if
BUILD_SETTINGS_COMPILER = \033[1;36mcompiler: \033[0;36m\"$(COMPILER) $(COMMONFLAGS) $(COMPILERFLAGS)\"
BUILD_SETTINGS_ASSEMBLER = \033[1;36massembler: \033[0;36m\"$(AS) $(ASFLAGS)\"
BUILD_SETTINGS_LINKER = \033[1;36mlinker: \033[0;36m\"$(LINKER) $(COMMONFLAGS) $(LINKERFLAGS) $(LIBDIRS) $(LIBS) $(STATICSTDCPP) $(STDCPPLIB)\"
ifeq (0,$(NOASM))
    BUILD_SETTINGS = printf "$(BUILD_SETTINGS_COMPILER)\n$(BUILD_SETTINGS_ASSEMBLER)\n$(BUILD_SETTINGS_LINKER)\033[0m\n"
else
    BUILD_SETTINGS = printf "$(BUILD_SETTINGS_COMPILER)\n$(BUILD_SETTINGS_LINKER)\033[0m\n"
endif
BUILD_STARTED = printf "\033[K\033[1;36mBuild started using:\033[0m\n"; $(BUILD_SETTINGS)
BUILD_ECHOFLAGS = printf "\033[K\033[1;36mEnded compilation in this directory using:\n$(BUILD_SETTINGS_COMPILER)\033[0m\n"
BUILD_FINISHED = printf "\033[K\033[1;36mBuild successful:\033[0m\n"
COMPILE_STATUS = printf "\033[K\033[0mBuilding object \033[1m$@\033[0m...\033[0m\r"
COMPILE_OK = printf "\033[K\033[0;32mBuilt object \033[1;32m$@\033[0;32m \033[0m\n"
COMPILE_FAILED = printf "\033[K\033[0;31mFailed building \033[1;31m$@\033[0;31m from\033[0m \033[1;31m$<\033[0;31m!\033[0m\n"; exit 1
RECIPE_RESULT_COMPILE = ; then $(COMPILE_OK); else $(COMPILE_FAILED); fi
ONESTEP_STATUS = printf "\033[K\033[0mBuilding executable \033[1m$@\033[0m...\033[0m\r"
ONESTEP_OK = printf "\033[K\033[0;32mBuilt executable \033[1;32m$@\033[0;32m \033[0m\n"
ONESTEP_FAILED = printf "\033[K\033[0;31mFailed building executable \033[1;31m$@\033[0;31m!\033[0m\n"; exit 1
RECIPE_RESULT_ONESTEP = ; then $(ONESTEP_OK); else $(ONESTEP_FAILED); fi
ARCHIVE_STATUS = printf "\033[K\033[0mCreating library archive \033[1m$@\033[0m...\033[0m\r"
ARCHIVE_OK = printf "\033[K\033[0;32mCreated library archive \033[1;32m$@\033[0;32m \033[0m\n"
ARCHIVE_FAILED = printf "\033[K\033[0;31mFailed creating library archive \033[1;31m$@\033[0;31m from\033[0m \033[1;31m$<\033[0;31m!\033[0m\n"; exit 1
RECIPE_RESULT_ARCHIVE = ; then $(ARCHIVE_OK); else $(ARCHIVE_FAILED); fi
LINK_STATUS = printf "\033[K\033[0;0mLinking executable \033[1m$@\033[0;0m...\033[0m\r"
LINK_OK = printf "\033[K\033[0;32mLinked executable \033[1;32m$@\033[0;32m \033[0m\n"
LINK_FAILED = printf "\033[K\033[0;31mFailed linking executable \033[1;31m$@\033[0;31m!\033[0m\n"; exit 1
RECIPE_RESULT_LINK = ; then $(LINK_OK); else $(LINK_FAILED); fi
else
RECIPE_IF =
BUILD_STARTED =
BUILD_ECHOFLAGS =
BUILD_FINISHED =
COMPILE_STATUS =
COMPILE_OK = true
COMPILE_FAILED = false; exit 1
RECIPE_RESULT_COMPILE =
ONESTEP_STATUS =
ONESTEP_OK = true
ONESTEP_FAILED = false; exit 1
RECIPE_RESULT_ONESTEP =
ARCHIVE_STATUS =
ARCHIVE_OK = true
ARCHIVE_FAILED = false; exit 1
RECIPE_RESULT_ARCHIVE =
LINK_STATUS =
LINK_OK = true
LINK_FAILED = false; exit 1
RECIPE_RESULT_LINK =
endif