csgo-2018-source/devtools/makefile_base_posix.mak
2021-07-24 21:11:47 -07:00

870 lines
32 KiB
Makefile

#
# Base makefile for Linux and OSX
#
# !!!!! Note to future editors !!!!!
#
# before you make changes, make sure you grok:
# 1. the difference between =, :=, +=, and ?=
# 2. how and when this base makefile gets included in the generated makefile(s)
# ( see http://www.gnu.org/software/make/manual/make.html#Flavors )
#
# Command line prefixes:
# - errors are ignored
# @ command is not printed to stdout before being executed
# + command is executed even if Make is invoked in "do not exec" mode
OS := $(shell uname)
HOSTNAME := $(shell hostname)
IDENTIFY_CURRENT_MAKEFILE_RELATIVE_FUNCTION = $(word $(words $(MAKEFILE_LIST)),$(MAKEFILE_LIST))
MAKEFILE_BASE_POSIX_MAK := $(call IDENTIFY_CURRENT_MAKEFILE_RELATIVE_FUNCTION)
CROSS_COMPILE_DIR := $(realpath $(dir $(MAKEFILE_BASE_POSIX_MAK))../../cross_compile)
ifeq ($(MAKE_VERBOSE),1)
QUIET_PREFIX =
QUIET_ECHO_POSTFIX =
else
QUIET_PREFIX = @
QUIET_ECHO_POSTFIX = > /dev/null
# Use abbreviated progress messages in the schema compiler.
VALVE_SCHEMA_QUIET = 1
export VALVE_SCHEMA_QUIET
endif
BASENAME := basename
CAT := cat
CP := cp
CUT := cut
DIRNAME := dirname
ECHO := echo
ETAGS := etags
EXPR := expr
FALSE := false
FGREP := fgrep
FIND := find
GREP := grep
ICONV := iconv
MKDIR := mkdir
PWD := PWD
PWD_TOOL := pwd
RM := rm
SED := sed
SLEEP := sleep
TAIL := tail
TOUCH := touch
TR := tr
TRUE := true
UNAME := uname
WHICH := which
ECHO_LF = $(ECHO) -e
BUILD_DEBUG_ECHO = $(TRUE)
#uncomment or define ENABLE_BUILD_DEBUG=1 on the make commandline to debug build phases and dependency updates
# ENABLE_BUILD_DEBUG = 1
ifneq "$(ENABLE_BUILD_DEBUG)" ""
BUILD_DEBUG_ECHO = $(ECHO)
endif
# SPEW_UPDATED_DEPENDENCIES spews the list of dependencies whose current timestamps invalidate this rule.
# This is only done when ENABLE_BUILD_DEBUG is 1
ifeq ("$(ENABLE_BUILD_DEBUG)","1")
SPEW_DEPENDENCY_CHUNK = \
SpewDependencyChunk () \
{ \
$(BUILD_DEBUG_ECHO) " $${1}"; \
return 0; \
}
SPEW_UPDATED_DEPENDENCIES = \
$(QUIET_PREFIX) \
{ \
$(BUILD_DEBUG_ECHO) "[SPEW_UPDATED_DEPENDENCIES] rule \"$@\" triggered by files:" && \
$(BUILD_DEBUG_ECHO) " $?"; \
}
else
SPEW_UPDATED_DEPENDENCIES = $(QUIET_PREFIX) $(TRUE)
endif
-include $(SRCROOT)/devtools/steam_def.mak
# To build with clang, set the following in your environment:
# CC = clang
# CXX = clang++
ifeq ($(CFG), release)
# With gcc 4.6.3, engine.so went from 7,383,765 to 8,429,109 when building with -O3.
# There also was no speed difference running at 1280x1024. May 2012, mikesart.
# -fno-omit-frame-pointer: need this for stack traces with perf.
OptimizerLevel_CompilerSpecific = -O2 -fno-strict-aliasing -ffast-math -fno-omit-frame-pointer
else
OptimizerLevel_CompilerSpecific = -O0
#-O1 -finline-functions
endif
# CPPFLAGS == "c/c++ *preprocessor* flags" - not "cee-plus-plus flags"
ARCH_FLAGS =
BUILDING_MULTI_ARCH = 0
CPPFLAGS = $(DEFINES) $(FORCEINCLUDES) $(addprefix -I, $(abspath $(INCLUDEDIRS) ))
ifeq ($(TARGET_PLATFORM),linux64)
CPPFLAGS += -fPIC
endif
CFLAGS = $(ARCH_FLAGS) $(CPPFLAGS) $(WARN_FLAGS) -fvisibility=$(SymbolVisibility) $(OptimizerLevel) -ffast-math -pipe $(GCC_ExtraCompilerFlags) -Usprintf -Ustrncpy -UPROTECTED_THINGS_ENABLE
# In -std=gnu++11 mode we get lots of errors about "error: narrowing conversion". -fpermissive
# turns these into warnings in gcc, and -Wno-c++11-narrowing suppresses them entirely in clang 3.1+.
ifeq ($(OS),Linux)
CXXFLAGS = $(CFLAGS) -std=gnu++0x -fpermissive
else
CXXFLAGS = $(CFLAGS) -std=gnu++11 -stdlib=libc++ -Wno-c++11-narrowing -Wno-dangling-else
endif
DEFINES += -DVPROF_LEVEL=1 -DGNUC
# This causes all filesystem interfaces to default to their 64bit versions on
# 32bit systems, which means we don't break on filesystems with inodes > 32bit.
DEFINES += -D_FILE_OFFSET_BITS=64
LDFLAGS = $(CFLAGS) $(GCC_ExtraLinkerFlags) $(OptimizerLevel)
GENDEP_CXXFLAGS = -MD -MP -MF $(@:.o=.P)
MAP_FLAGS =
ifeq ($(STEAM_BRANCH),1)
WARN_FLAGS = -Wall -Wextra -Wshadow -Wno-invalid-offsetof
else
WARN_FLAGS = -Wno-write-strings -Wno-multichar
endif
WARN_FLAGS += -Wno-unknown-pragmas -Wno-unused-parameter -Wno-unused-value -Wno-missing-field-initializers -Wno-sign-compare -Wno-reorder -Wno-invalid-offsetof -Wno-float-equal -Wno-switch -fdiagnostics-show-option -Wformat -Werror=format-security -Wstrict-aliasing=2
ifeq ($(OS),Linux)
# We should always specify -Wl,--build-id, as documented at:
# http://linux.die.net/man/1/ld and http://fedoraproject.org/wiki/Releases/FeatureBuildId.http://fedoraproject.org/wiki/Releases/FeatureBuildId
LDFLAGS += -Wl,--build-id
UUID_LIB =
# Set USE_STEAM_RUNTIME to build with the Steam Runtime. Otherwise uses
# The toolchain in /valve
ifneq ($(USE_STEAM_RUNTIME),1)
# dedicated server flags
ifeq ($(TARGET_PLATFORM),linux64)
VALVE_BINDIR = /valve/bin64/
MARCH_TARGET = nocona
else
VALVE_BINDIR = /valve/bin/
MARCH_TARGET = pentium4
endif
STRIP_FLAGS = -x
LIBCPP_EXT = a
else
# linux desktop client flags
VALVE_BINDIR =
DEFINES +=
# If the steam-runtime is available, use it. We should just default to using it when
# buildbot and everyone has a bit of time to get it installed.
ifneq "$(wildcard /valve/steam-runtime/bin/)" ""
# The steam-runtime is incompatible with clang at this point, so disable it
# if clang is enabled.
ifneq ($(CXX),clang++)
VALVE_BINDIR = /valve/steam-runtime/bin/
endif
endif
GCC_VER =
ifeq ($(TARGET_PLATFORM),linux64)
MARCH_TARGET = nocona
else
MARCH_TARGET = pentium4
endif
# On dedicated servers, some plugins depend on global variable symbols in addition to functions.
# So symbols like _Z16ClearMultiDamagev should show up when you do "nm server_srv.so" in TF2.
STRIP_FLAGS = -x
LIBCPP_EXT = so
UUID_LIB = -luuid
endif
# We want to make all TLS use the global-dynamic
# model, to avoid having to use -fpic but avoid problems with dlopen()
# failing due to TLS clashes. This happens in particular when trying
# to run the game with primus. Note that -ftls-model=global-dynamic
# doesn't work due to undocumented 'features' in gcc that only allow
# the TLS model to be 'downgraded' from the default and not upgraded.
CFLAGS += -D__thread='__thread __attribute__((tls_model("global-dynamic")))'
CXXFLAGS += -D__thread='__thread __attribute__((tls_model("global-dynamic")))'
ifeq ($(CXX),clang++)
# Clang does not support -mfpmath=sse
SSE_GEN_FLAGS = -msse2
else
SSE_GEN_FLAGS = -msse2 -mfpmath=sse
endif
# Turn this on when ready to fix errors that crop up (can merge fixes from console eventually).
#WARN_FLAGS += -Werror=return-type
ifeq ($(CXX),clang++)
# The C-linkage return-type warning (no returning of references) must be disabled after the
# return-type error is enabled.
WARN_FLAGS += -Wno-return-type-c-linkage
# -g0 must be specified because -g2 makes server.so.dbg so huge that the linker sometimes
# fails due to memory exhaustion.
CFLAGS += -g0
endif
CCACHE := $(SRCROOT)/devtools/bin/linux/ccache
ifeq ($(origin GCC_VER), undefined)
GCC_VER=-4.6
endif
ifeq ($(origin AR), default)
AR = $(VALVE_BINDIR)ar crs
endif
ifeq ($(origin CC),default)
CC = $(CCACHE) $(VALVE_BINDIR)gcc$(GCC_VER)
endif
ifeq ($(origin CXX), default)
CXX = $(CCACHE) $(VALVE_BINDIR)g++$(GCC_VER)
endif
# Support ccache with clang. Add -Qunused-arguments to avoid excessive warnings due to
# a ccache quirk. Could also upgrade ccache.
# http://petereisentraut.blogspot.com/2011/05/ccache-and-clang.html
ifeq ($(CC),clang)
CC = $(CCACHE) $(VALVE_BINDIR)clang -Qunused-arguments
endif
ifeq ($(CXX),clang++)
CXX = $(CCACHE) $(VALVE_BINDIR)clang++ -Qunused-arguments
endif
LINK ?= $(CC)
ifeq ($(TARGET_PLATFORM),linux64)
# nocona = pentium4 + 64bit + MMX, SSE, SSE2, SSE3 - no SSSE3 (that's three s's - added in core2)
ARCH_FLAGS += -march=$(MARCH_TARGET) -mtune=core2
LD_SO = ld-linux-x86-64.so.2
LIBSTDCXX := $(shell $(CXX) -print-file-name=libstdc++.$(LIBCPP_EXT))
LIBSTDCXXPIC := $(shell $(CXX) -print-file-name=libstdc++.$(LIBCPP_EXT))
else
# core2 = Intel Core2 CPU with 64-bit extensions, MMX, SSE, SSE2, SSE3 and SSSE3 instruction set support.
# changed for DOTA since we are running servers on newer hardware
ifeq ($(TARGET_PLATFORM_EXT),_client)
# on non-server Linux client builds let's be a little more conservative
ARCH_FLAGS += -m32 -march=prescott -mtune=core2 $(SSE_GEN_FLAGS)
else
ARCH_FLAGS += -m32 -march=core2 -mtune=core2 $(SSE_GEN_FLAGS)
endif
LD_SO = ld-linux.so.2
LIBSTDCXX := $(shell $(CXX) $(ARCH_FLAGS) -print-file-name=libstdc++.$(LIBCPP_EXT))
LIBSTDCXXPIC := $(shell $(CXX) $(ARCH_FLAGS) -print-file-name=libstdc++.$(LIBCPP_EXT))
LDFLAGS += -m32
endif
GEN_SYM ?= $(SRCROOT)/devtools/gendbg.sh
ifeq ($(CFG),release)
STRIP ?= strip $(STRIP_FLAGS) -S
# CFLAGS += -ffunction-sections -fdata-sections
# LDFLAGS += -Wl,--gc-sections -Wl,--print-gc-sections
else
STRIP ?= true
endif
VSIGN ?= true
LINK_MAP_FLAGS = -Wl,-Map,$(@:.so=).map
SHLIBLDFLAGS = -shared $(LDFLAGS) -Wl,--no-undefined
_WRAP := -Xlinker --wrap=
PATHWRAP = $(_WRAP)fopen $(_WRAP)freopen $(_WRAP)open $(_WRAP)creat $(_WRAP)access $(_WRAP)__xstat \
$(_WRAP)stat $(_WRAP)lstat $(_WRAP)fopen64 $(_WRAP)open64 $(_WRAP)opendir $(_WRAP)__lxstat \
$(_WRAP)chmod $(_WRAP)chown $(_WRAP)lchown $(_WRAP)symlink $(_WRAP)link $(_WRAP)__lxstat64 \
$(_WRAP)mknod $(_WRAP)utimes $(_WRAP)unlink $(_WRAP)rename $(_WRAP)utime $(_WRAP)__xstat64 \
$(_WRAP)mount $(_WRAP)mkfifo $(_WRAP)mkdir $(_WRAP)rmdir $(_WRAP)scandir $(_WRAP)realpath
LIB_START_EXE = $(PATHWRAP) -static-libgcc -Wl,--start-group
LIB_END_EXE = -Wl,--end-group -lm -ldl $(LIBSTDCXX) -lpthread $(UUID_LIB)
LIB_START_SHLIB = $(PATHWRAP) -static-libgcc -Wl,--start-group
LIB_END_SHLIB = -Wl,--end-group -lm -ldl $(LIBSTDCXXPIC) -lpthread $(UUID_LIB) -l:$(LD_SO) -Wl,--version-script=$(SRCROOT)/devtools/version_script.linux.txt
endif
ifeq ($(OS),Darwin)
LDFLAGS += -stdlib=libc++
OSXVER := $(shell sw_vers -productVersion)
CCACHE := $(SRCROOT)/devtools/bin/osx32/ccache
DEVELOPER_DIR := $(shell /usr/bin/xcode-select -print-path)
XCODEVER := $(shell /usr/bin/xcode-select -version)
USE_DEV_USR_BIN := 0
ifeq (,$(findstring 10.7, $(OSXVER)))
USE_DEV_USR_BIN := 1
endif
ifeq (/Developer, $(DEVELOPER_DIR))
USE_DEV_USR_BIN := 1
endif
ifeq (1,$(USE_DEV_USR_BIN))
COMPILER_BIN_DIR := $(DEVELOPER_DIR)/usr/bin
SDK_DIR := $(DEVELOPER_DIR)/SDKs
else
COMPILER_BIN_DIR := $(DEVELOPER_DIR)/Toolchains/XcodeDefault.xctoolchain/usr/bin
SDK_DIR := $(DEVELOPER_DIR)/Platforms/MacOSX.platform/Developer/SDKs
endif
SDKROOT ?= $(SDK_DIR)/MacOSX10.9.sdk
#test to see if you have a compiler in the right place, if you don't abort with an error
ifeq ($(wildcard $(COMPILER_BIN_DIR)/clang),)
$(error Unable to find compiler, install and configure XCode)
endif
ifeq ($(wildcard $(COMPILER_BIN_DIR)/clang++),)
$(error Unable to find compiler, install and configure XCode)
endif
ifeq ($(origin AR), default)
AR = libtool -static -o
endif
ifeq ($(origin CC), default)
CC = $(CCACHE) $(COMPILER_BIN_DIR)/clang -Qunused-arguments -Wno-c++11-narrowing -Wno-dangling-else
endif
ifeq ($(origin CXX), default)
CXX = $(CCACHE) $(COMPILER_BIN_DIR)/clang++ -Qunused-arguments -Wno-c++11-narrowing -Wno-dangling-else
endif
LINK ?= $(CXX)
ifeq ($(TARGET_PLATFORM),osx64)
ARCH_FLAGS += -arch x86_64 -m64 -march=core2
else ifeq (,$(findstring -arch x86_64,$(GCC_ExtraCompilerFlags)))
ARCH_FLAGS += -arch i386 -m32 -march=prescott -momit-leaf-frame-pointer -mtune=core2
else
# dirty hack to build a universal binary - don't specify the architecture
ARCH_FLAGS += -arch i386 -Xarch_i386 -march=prescott -Xarch_i386 -mtune=core2 -Xarch_i386 -momit-leaf-frame-pointer -Xarch_x86_64 -march=core2
endif
#FIXME: NOTE:Full path specified because the xcode 4.0 preview has a terribly broken dsymutil, so ref the 3.2 one
GEN_SYM ?= /usr/bin/dsymutil
ifeq ($(CFG),release)
STRIP ?= strip -x -S
else
STRIP ?= true
endif
VSIGN ?= true
CPPFLAGS += -I$(SDKROOT)/usr/include/malloc -ftemplate-depth=1024
CFLAGS += -isysroot $(SDKROOT) -mmacosx-version-min=10.7 -fasm-blocks -fno-color-diagnostics
WARN_FLAGS += -Wno-parentheses -Wno-constant-logical-operand -Wno-deprecated
LIB_START_EXE = -lm -ldl -lpthread
LIB_END_EXE =
LIB_START_SHLIB =
LIB_END_SHLIB =
SHLIBLDFLAGS = $(LDFLAGS) -bundle -flat_namespace -undefined suppress -Wl,-dead_strip -Wl,-no_dead_strip_inits_and_terms
ifeq (lib,$(findstring lib,$(GAMEOUTPUTFILE)))
SHLIBLDFLAGS = $(LDFLAGS) -dynamiclib -current_version 1.0 -compatibility_version 1.0 -install_name @rpath/$(basename $(notdir $(GAMEOUTPUTFILE))).dylib $(SystemLibraries) -Wl,-dead_strip -Wl,-no_dead_strip_inits_and_terms
endif
endif
#
# Profile-directed optimizations.
# Note: Last time these were tested 3/5/08, it actually slowed down the server benchmark by 5%!
#
# First, uncomment these, build, and test. It will generate .gcda and .gcno files where the .o files are.
# PROFILE_LINKER_FLAG=-fprofile-arcs
# PROFILE_COMPILER_FLAG=-fprofile-arcs
#
# Then, comment the above flags out again and rebuild with this flag uncommented:
# PROFILE_COMPILER_FLAG=-fprofile-use
#
#############################################################################
# The compiler command lne for each src code file to compile
#############################################################################
OBJ_DIR = ./obj_$(NAME)_$(TARGET_PLATFORM)$(TARGET_PLATFORM_EXT)/$(CFG)
CPP_TO_OBJ = $(CPPFILES:.cpp=.o)
CXX_TO_OBJ = $(CPP_TO_OBJ:.cxx=.o)
CC_TO_OBJ = $(CXX_TO_OBJ:.cc=.o)
MM_TO_OBJ = $(CC_TO_OBJ:.mm=.o)
C_TO_OBJ = $(MM_TO_OBJ:.c=.o)
OBJS = $(addprefix $(OBJ_DIR)/, $(notdir $(C_TO_OBJ)))
export OBJ_DIR
ifeq ($(MAKE_VERBOSE),1)
QUIET_PREFIX =
QUIET_ECHO_POSTFIX =
else
QUIET_PREFIX = @
QUIET_ECHO_POSTFIX = > /dev/null
endif
ifeq ($(MAKE_CC_VERBOSE),1)
CC += -v
endif
ifeq ($(CONFTYPE),lib)
LIB_File = $(OUTPUTFILE)
endif
ifeq ($(CONFTYPE),dll)
SO_File = $(OUTPUTFILE)
endif
ifeq ($(CONFTYPE),exe)
EXE_File = $(OUTPUTFILE)
endif
# we generate dependencies as a side-effect of compilation now
GEN_DEP_FILE=
PRE_COMPILE_FILE =
POST_COMPILE_FILE =
ifeq ($(BUILDING_MULTI_ARCH),1)
SINGLE_ARCH_CXXFLAGS=$(subst -arch x86_64,,$(CXXFLAGS))
COMPILE_FILE = \
$(QUIET_PREFIX) \
echo "---- $(lastword $(subst /, ,$<)) as MULTIARCH----";\
mkdir -p $(OBJ_DIR) && \
$(CXX) $(SINGLE_ARCH_CXXFLAGS) $(GENDEP_CXXFLAGS) -o $@ -c $< && \
$(CXX) $(CXXFLAGS) -o $@ -c $<
else
COMPILE_FILE = \
$(QUIET_PREFIX) \
echo "---- $(lastword $(subst /, ,$<)) ----";\
mkdir -p $(OBJ_DIR) && \
$(CXX) $(CXXFLAGS) $(GENDEP_CXXFLAGS) -o $@ -c $<
endif
ifneq "$(origin VALVE_NO_AUTO_P4)" "undefined"
P4_EDIT_START = chmod -R +w
P4_EDIT_END = || true
P4_REVERT_START = true
P4_REVERT_END =
else
ifndef P4_EDIT_CHANGELIST
# You can use an environment variable to specify what changelist to check the Linux Binaries out into. Normally the default
# setting is best, but here is an alternate example:
# export P4_EDIT_CHANGELIST_CMD="echo 1424335"
# ?= means that if P4_EDIT_CHANGELIST_CMD is already set it won't be changed.
P4_EDIT_CHANGELIST_CMD ?= p4 changes -c `p4 client -o | grep ^Client | cut -f 2` -s pending | fgrep 'POSIX Auto Checkout' | cut -d' ' -f 2 | tail -n 1
P4_EDIT_CHANGELIST := $(shell $(P4_EDIT_CHANGELIST_CMD))
endif
ifeq ($(P4_EDIT_CHANGELIST),)
# If we haven't found a changelist to check out to then create one. The name must match the one from a few
# lines above or else a new changelist will be created each time.
# Warning: the behavior of 'echo' is not consistent. In bash you need the "-e" option in order for \n to be
# interpreted as a line-feed, but in dash you do not, and if "-e" is passed along then it is printed, which
# confuses p4. So, if you run this command from the bash shell don't forget to add "-e" to the echo command.
P4_EDIT_CHANGELIST = $(shell echo "Change: new\nDescription: POSIX Auto Checkout" | p4 change -i | cut -f 2 -d ' ')
endif
P4_EDIT_START := for f in
P4_EDIT_END := ; do if [ -n $$f ]; then if [ -d $$f ]; then find $$f -type f -print | p4 -x - edit -c $(P4_EDIT_CHANGELIST); else p4 edit -c $(P4_EDIT_CHANGELIST) $$f; fi; fi; done $(QUIET_ECHO_POSTFIX)
P4_REVERT_START := for f in
P4_REVERT_END := ; do if [ -n $$f ]; then if [ -d $$f ]; then find $$f -type f -print | p4 -x - revert; else p4 revert $$f; fi; fi; done $(QUIET_ECHO_POSTFIX)
endif
ifeq ($(CONFTYPE),dll)
all: $(OTHER_DEPENDENCIES) $(OBJS) $(GAMEOUTPUTFILE)
@echo $(GAMEOUTPUTFILE) $(QUIET_ECHO_POSTFIX)
else
all: $(OTHER_DEPENDENCIES) $(OBJS) $(OUTPUTFILE)
@echo $(OUTPUTFILE) $(QUIET_ECHO_POSTFIX)
endif
.PHONY: clean cleantargets cleanandremove rebuild relink RemoveOutputFile SingleFile
rebuild :
$(MAKE) -f $(firstword $(MAKEFILE_LIST)) cleanandremove
$(MAKE) -f $(firstword $(MAKEFILE_LIST))
# Use the relink target to force to relink the project.
relink: RemoveOutputFile all
RemoveOutputFile:
rm -f $(OUTPUTFILE)
# This rule is so you can say "make SingleFile SingleFilename=/home/myname/valve_main/src/engine/language.cpp" and have it only build that file.
# It basically just translates the full filename to create a dependency on the appropriate .o file so it'll build that.
SingleFile : RemoveSingleFile $(OBJ_DIR)/$(basename $(notdir $(SingleFilename))).o
@echo ""
RemoveSingleFile:
$(QUIET_PREFIX) rm -f $(OBJ_DIR)/$(basename $(notdir $(SingleFilename))).o
clean:
ifneq "$(OBJ_DIR)" ""
$(QUIET_PREFIX) echo "rm -rf $(OBJ_DIR)"
$(QUIET_PREFIX) rm -rf $(OBJ_DIR)
endif
ifneq "$(OUTPUTFILE)" ""
$(QUIET_PREFIX) if [ -e $(OUTPUTFILE) ]; then \
echo "p4 revert $(OUTPUTFILE)"; \
$(P4_REVERT_START) $(OUTPUTFILE) $(OUTPUTFILE)$(SYM_EXT) $(P4_REVERT_END); \
fi;
endif
ifneq "$(OTHER_DEPENDENCIES)" ""
$(QUIET_PREFIX) echo "rm -f $(OTHER_DEPENDENCIES)"
ifneq "$(GAMEOUTPUTFILE)" ""
endif
$(QUIET_PREFIX) rm -f $(OTHER_DEPENDENCIES)
endif
ifneq "$(GAMEOUTPUTFILE)" ""
$(QUIET_PREFIX) echo "p4 revert $(GAMEOUTPUTFILE)"
$(QUIET_PREFIX) $(P4_REVERT_START) $(GAMEOUTPUTFILE) $(GAMEOUTPUTFILE)$(SYM_EXT) $(P4_REVERT_END)
endif
# Do the above cleaning, except with p4 edit and rm. Reason being ar crs adds and replaces obj files to the
# archive. However if you've renamed or deleted a source file, $(AR) won't remove it. This can leave
# us with archive files that have extra unused symbols, and also potentially cause compilation errors
# when you rename a file and have many duplicate symbols.
cleanandremove:
ifneq "$(OBJ_DIR)" ""
$(QUIET_PREFIX) echo "rm -rf $(OBJ_DIR)"
$(QUIET_PREFIX) -rm -rf $(OBJ_DIR)
endif
ifneq "$(OUTPUTFILE)" ""
$(QUIET_PREFIX) if [ -e $(OUTPUTFILE) ]; then \
echo "p4 edit and rm -f $(OUTPUTFILE) $(OUTPUTFILE)$(SYM_EXT)"; \
$(P4_EDIT_START) $(OUTPUTFILE) $(OUTPUTFILE)$(SYM_EXT) $(P4_EDIT_END); \
fi;
$(QUIET_PREFIX) -rm -f $(OUTPUTFILE) $(OUTPUTFILE)$(SYM_EXT);
endif
ifneq "$(OTHER_DEPENDENCIES)" ""
$(QUIET_PREFIX) echo "rm -f $(OTHER_DEPENDENCIES)"
$(QUIET_PREFIX) -rm -f $(OTHER_DEPENDENCIES)
endif
ifneq "$(GAMEOUTPUTFILE)" ""
$(QUIET_PREFIX) echo "p4 edit and rm -f $(GAMEOUTPUTFILE) $(GAMEOUTPUTFILE)$(SYM_EXT)"
$(QUIET_PREFIX) $(P4_EDIT_START) $(GAMEOUTPUTFILE) $(GAMEOUTPUTFILE)$(SYM_EXT) $(P4_EDIT_END)
$(QUIET_PREFIX) -rm -f $(GAMEOUTPUTFILE)
endif
# This just deletes the final targets so it'll do a relink next time we build.
cleantargets:
$(QUIET_PREFIX) rm -f $(OUTPUTFILE) $(GAMEOUTPUTFILE)
$(LIB_File): $(OTHER_DEPENDENCIES) $(OBJS)
$(QUIET_PREFIX) -$(P4_EDIT_START) $(LIB_File) $(P4_EDIT_END);
$(QUIET_PREFIX) $(AR) $(LIB_File) $(OBJS) $(LIBFILES);
SO_GameOutputFile = $(GAMEOUTPUTFILE)
$(SO_GameOutputFile): $(SO_File)
$(QUIET_PREFIX) \
$(P4_EDIT_START) $(GAMEOUTPUTFILE) $(P4_EDIT_END) && \
echo "----" $(QUIET_ECHO_POSTFIX);\
echo "---- COPYING TO $@ [$(CFG)] ----";\
echo "----" $(QUIET_ECHO_POSTFIX);
$(QUIET_PREFIX) -$(P4_EDIT_START) $(GAMEOUTPUTFILE) $(P4_EDIT_END);
$(QUIET_PREFIX) -mkdir -p `dirname $(GAMEOUTPUTFILE)` > /dev/null;
$(QUIET_PREFIX) cp -v $(OUTPUTFILE) $(GAMEOUTPUTFILE) $(QUIET_ECHO_POSTFIX);
$(QUIET_PREFIX) -$(P4_EDIT_START) $(GAMEOUTPUTFILE)$(SYM_EXT) $(P4_EDIT_END);
$(QUIET_PREFIX) $(GEN_SYM) $(GAMEOUTPUTFILE);
$(QUIET_PREFIX) -$(STRIP) $(GAMEOUTPUTFILE);
$(QUIET_PREFIX) $(VSIGN) -signvalve $(GAMEOUTPUTFILE);
$(QUIET_PREFIX) if [ "$(IMPORTLIBRARY)" != "" ]; then\
echo "----" $(QUIET_ECHO_POSTFIX);\
echo "---- COPYING TO IMPORT LIBRARY $(IMPORTLIBRARY) ----";\
echo "----" $(QUIET_ECHO_POSTFIX);\
$(P4_EDIT_START) $(IMPORTLIBRARY) $(P4_EDIT_END) && \
mkdir -p `dirname $(IMPORTLIBRARY)` > /dev/null && \
cp -v $(OUTPUTFILE) $(IMPORTLIBRARY); \
fi;
$(SO_File): $(OTHER_DEPENDENCIES) $(OBJS) $(LIBFILENAMES)
$(QUIET_PREFIX) \
echo "----" $(QUIET_ECHO_POSTFIX);\
echo "---- LINKING $@ [$(CFG)] ----";\
echo "----" $(QUIET_ECHO_POSTFIX);\
\
$(LINK) $(LINK_MAP_FLAGS) $(SHLIBLDFLAGS) $(PROFILE_LINKER_FLAG) -o $(OUTPUTFILE) $(LIB_START_SHLIB) $(OBJS) $(LIBFILES) $(SystemLibraries) $(LIB_END_SHLIB);
$(VSIGN) -signvalve $(OUTPUTFILE);
$(EXE_File) : $(OTHER_DEPENDENCIES) $(OBJS) $(LIBFILENAMES)
$(QUIET_PREFIX) \
echo "----" $(QUIET_ECHO_POSTFIX);\
echo "---- LINKING EXE $@ [$(CFG)] ----";\
echo "----" $(QUIET_ECHO_POSTFIX);\
\
$(P4_EDIT_START) $(OUTPUTFILE) $(P4_EDIT_END);\
$(LINK) $(LINK_MAP_FLAGS) $(LDFLAGS) $(PROFILE_LINKER_FLAG) -o $(OUTPUTFILE) $(LIB_START_EXE) $(OBJS) $(LIBFILES) $(SystemLibraries) $(LIB_END_EXE);
$(QUIET_PREFIX) -$(P4_EDIT_START) $(OUTPUTFILE)$(SYM_EXT) $(P4_EDIT_END);
$(QUIET_PREFIX) $(GEN_SYM) $(OUTPUTFILE);
$(QUIET_PREFIX) -$(STRIP) $(OUTPUTFILE);
$(QUIET_PREFIX) $(VSIGN) -signvalve $(OUTPUTFILE);
tags:
etags -a -C -o $(SRCROOT)/TAGS *.cpp *.cxx *.h *.hxx
P4EXE ?= p4
# DETECT_STRING_CHANGE_BETWEEN_BUILDS is a macro that lets you update the timestamp on a file whenever a string changes between invokations of make
# This lets us know that our compile flags are consistent with the last time we ran and avoid overbuilding
#
# Parameters: $(1) = a unique name as a basis for intermediate variables and file names, the exact name will not be used if you want to give it a name used for $(2).
# $(2) = extra escaped deref or call that you would invoke to fully evaluate the string in $(1)
# A file specified with $(call DETECT_STRING_CHANGE_BETWEEN_BUILDS_TIMESTAMP_FILE,$(1)) will have it's timestamp updated whenever the cached settings change
# Make string substitions on the value so it can be represented cleanly in an "$(ECHO) > file" operation
DETECT_STRING_CHANGE_BETWEEN_BUILDS_STRING_FILTER = $(strip $(subst $$,_dollar,$(subst \\,_bs,$(subst =,_eq,$(subst ',_sq,$(subst ",_dq,$(1)))))))
DETECT_STRING_CHANGE_BETWEEN_BUILDS_TIMESTAMP_FILE = $(OBJ_DIR)/_detect_string_change_between_builds/$(1)_updated
define DETECT_STRING_CHANGE_BETWEEN_BUILDS
ifeq "$$(DISABLE_DETECT_STRING_CHANGE_BETWEEN_BUILDS)" ""
include $$(wildcard $$(OBJ_DIR)/_detect_string_change_between_builds/$(1)_previous)
unexport $(1)_FILTERED_PREV
$(1)_FILTERED_CURRENT := $$(call DETECT_STRING_CHANGE_BETWEEN_BUILDS_STRING_FILTER,$(2))
unexport $(1)_FILTERED_CURRENT
ifeq "1" "0"
# Invalidate any cached settings whenever the base makefile changes in any way. This is mostly paranoia and we should be able to rely on the second rule by itself
$$(OBJ_DIR)/_detect_string_change_between_builds/$(1)_eval:: $(MAKEFILE_BASE_POSIX_MAK) ; \
$$(QUIET_PREFIX) \
{ \
$$(BUILD_DEBUG_ECHO) detect string change between builds $(1) eval base start && \
if [ -e "$$(OBJ_DIR)/_detect_string_change_between_builds/$(1)_updated" ]; then \
{ \
$$(BUILD_DEBUG_ECHO) "Discarding $(1) cached value due to changes in \"$$^\""; \
}; \
fi; \
$$(RM) -f $$(OBJ_DIR)/_detect_string_change_between_builds/$(1)_updated; \
$$(RM) -f $$(OBJ_DIR)/_detect_string_change_between_builds/$(1)_previous; \
$$(RM) -f $$(OBJ_DIR)/_detect_string_change_between_builds/$(1)_eval; \
}
endif
ifneq ("$$($(1)_FILTERED_CURRENT)","$$($(1)_FILTERED_PREV)")
$(1)_WRITE_CHUNK_FUNC = \
WriteStringChunkToPrevFile () \
{ \
$$(ECHO) -n "$$$${1}" >> $$(OBJ_DIR)/_detect_string_change_between_builds/$(1)_previous && \
return 0; \
}
#value changed, write out the new value, touch the updated and eval file
$$(OBJ_DIR)/_detect_string_change_between_builds/$(1)_eval:: $(MAKEFILE_BASE_POSIX_MAK) $(COMPILE_DEPENDANT_MAKEFILES)
$$(QUIET_PREFIX) $$(BUILD_DEBUG_ECHO) detect string change between builds $(1) eval incremental start
$$(SPEW_UPDATED_DEPENDENCIES)
$$(QUIET_PREFIX) \
{ \
{ $$(MKDIR) -p $$(OBJ_DIR)/_detect_string_change_between_builds $$(QUIET_ECHO_POSTFIX) || $(TRUE); } && \
$$(BUILD_DEBUG_ECHO) "$(1) changed since last build" && \
$$(TOUCH) $$(OBJ_DIR)/_detect_string_change_between_builds/$(1)_updated && \
$$(ECHO) -n "$(1)_FILTERED_PREV = " > $$(OBJ_DIR)/_detect_string_change_between_builds/$(1)_previous; \
}
$$(QUIET_PREFIX) $$(call CHUNK_OUT_STRING_FOR_SHELL_LIMITS,$$($(1)_WRITE_CHUNK_FUNC),WriteStringChunkToPrevFile, ,$$($(1)_FILTERED_CURRENT))
$$(QUIET_PREFIX) $$(TOUCH) $$(OBJ_DIR)/_detect_string_change_between_builds/$(1)_eval
else
#value is the same, just touch the eval file
$$(OBJ_DIR)/_detect_string_change_between_builds/$(1)_eval:: $(MAKEFILE_BASE_POSIX_MAK) $(COMPILE_DEPENDANT_MAKEFILES)
$$(QUIET_PREFIX) $$(BUILD_DEBUG_ECHO) detect string change between builds $(1) eval incremental start
$$(SPEW_UPDATED_DEPENDENCIES)
$$(QUIET_PREFIX) \
{ \
{ $$(MKDIR) -p $$(OBJ_DIR)/_detect_string_change_between_builds $$(QUIET_ECHO_POSTFIX) || $(TRUE); } && \
$$(BUILD_DEBUG_ECHO) $(1) unchanged since last build && \
$$(TOUCH) $$(OBJ_DIR)/_detect_string_change_between_builds/$(1)_eval; \
}
endif
$$(OBJ_DIR)/_detect_string_change_between_builds/$(1)_updated: $$(OBJ_DIR)/_detect_string_change_between_builds/$(1)_eval ; \
$$(QUIET_PREFIX) \
{ \
if [ ! -e "$$(OBJ_DIR)/_detect_string_change_between_builds/$(1)_updated" ]; then \
{ \
$$(TOUCH) $$(OBJ_DIR)/_detect_string_change_between_builds/$(1)_updated; \
}; \
fi; \
$$(BUILD_DEBUG_ECHO) detect string change between builds $(1) has evaluated; \
}
else
# if $(DISABLE_DETECT_STRING_CHANGE_BETWEEN_BUILDS) is defined to not do anything, always update the strings when any relevant makefile changes
$$(OBJ_DIR)/_detect_string_change_between_builds/$(1)_updated: $(MAKEFILE_BASE_POSIX_MAK) $(COMPILE_DEPENDANT_MAKEFILES) ; \
$$(QUIET_PREFIX) \
{
$$(BUILD_DEBUG_ECHO) detect string change between builds $(1) updated disabled start && \
$$(TOUCH) $$(OBJ_DIR)/_detect_string_change_between_builds/$(1)_updated; \
}
endif
endef
unexport DETECT_STRING_CHANGE_BETWEEN_BUILDS
# RUN_RECIPE_ACTION_ONCE ensures you run a recipe action exactly one time among many parallel threads
# and none of the recipes trying to run it return from the function until the action has completed
#
# Parameters: $(1) = unique "already run" sentinel file, $(2) = unique mutex directory, $(3) = action to run
# The existence of the sentinel is used to note that the action has already run and should not run again. The contents of the file are a shell script to replciate the exit status of the action. You are responsible for ensuring this file is deleted before the action will run again
# The existence of the mutex directory causes parallel recipes to spin until it is removed (which automatically happens at the end of the function). You are responsible for ensuring this directory is deleted before any locks can be acquired
# "_prebuild_always::" is a good place to remove both files.
# You are also responsible for ensuring the base directories for both items exist prior to calling RUN_RECIPE_ACTION_ONCE
#
# The sentinel file is used because shell scripts cannot promote environment variables to the parent make process, so the filesystem is used to create a boolean flag out of the sentinel file
# The mutex directory is used because directory creation is atomic and will return an error if the directory cannot be created (already exists)
RUN_RECIPE_ACTION_ONCE = \
( \
until [ -e $(1) ]; do \
{ \
$(MKDIR) -p $(2) > /dev/null 2>&1 && \
{ \
! [ -e $(1) ] && \
{ \
{ $(3); } && \
$(ECHO) "exit 0" > $(1) || \
$(ECHO) "exit 1" > $(1); \
}; \
$(RM) -fr $(2); \
} \
|| \
{ \
$(SLEEP) 1; \
}; \
}; \
done; \
$(SHELL) $(1); \
)
#
# Standard directory creation targets to ensure we can just touch files we need knowing that their directory exists
#
# Ensure $(OBJ_DIR) exists
$(OBJ_DIR)/_create_dir:
$(QUIET_PREFIX) $(BUILD_DEBUG_ECHO) $(OBJ_DIR)/_create_dir start
$(QUIET_PREFIX) $(MKDIR) -p $(OBJ_DIR) $(QUIET_ECHO_POSTFIX)
$(QUIET_PREFIX) $(TOUCH) $(OBJ_DIR)/_create_dir
PREBUILD_EVENT_ACTION ?= { $(TRUE); }
PREBUILD_EVENT_WRAPPED = \
{ \
{ \
$(BUILD_DEBUG_ECHO) "Pre-Build Event For \"$(NAME)\"" && \
$(call PREBUILD_EVENT_ACTION); \
} \
|| \
{ \
$(ECHO) "Error executing Pre-Build Event for \"$(NAME)\""; \
$(FALSE); \
}; \
}
RUN_PREBUILD_EVENT_ONCE = $(call RUN_RECIPE_ACTION_ONCE,"$(OBJ_DIR)/_ran_prebuild_event","$(OBJ_DIR)/_lock_prebuild_event",$(call PREBUILD_EVENT_WRAPPED))
_prebuild_always::
$(QUIET_PREFIX) $(BUILD_DEBUG_ECHO) _prebuild_always delete prebuild event start
$(QUIET_PREFIX) $(RM) -fr $(OBJ_DIR)/_ran_prebuild_event
$(QUIET_PREFIX) $(RM) -fr $(OBJ_DIR)/_lock_prebuild_event
# Analogous to MSVC Pre-Link Event
PRELINK_EVENT_ACTION ?= { $(TRUE); }
$(OBJ_DIR)/_prelink_event: $(LINK_STEP_DEPENDENCIES) | _prebuild_steps _predepgen_steps _precompile_steps
$(QUIET_PREFIX) $(BUILD_DEBUG_ECHO) _prelink_event start
$(SPEW_UPDATED_DEPENDENCIES)
$(QUIET_PREFIX) \
{ \
{ \
$(call RUN_PREBUILD_EVENT_ONCE) && \
$(BUILD_DEBUG_ECHO) "Pre-Link Event For \"$(NAME)\"" && \
$(call PRELINK_EVENT_ACTION) && \
$(TOUCH) $(OBJ_DIR)/_prelink_event && \
$(RM) -f $(OBJ_DIR)/_prelink_event_failed; \
} \
|| \
{ \
$(ECHO) "Error executing Pre-Link Event for \"$(NAME)\""; \
$(RM) -f $(OBJ_DIR)/_prelink_event; \
$(TOUCH) $(OBJ_DIR)/_prelink_event_failed; \
$(FALSE); \
}; \
}
# Analogous to MSVC Post-Build Event
POSTBUILD_EVENT_ACTION ?= { $(TRUE); }
$(OBJ_DIR)/_postbuild_event: $(ALL_CUSTOM_BUILD_TOOL_OUTPUTS) $(LINK_STEP) $(wildcard $(OBJ_DIR)/_postbuild_event_failed) | _prebuild_steps
$(QUIET_PREFIX) $(BUILD_DEBUG_ECHO) _postbuild_event start
$(SPEW_UPDATED_DEPENDENCIES)
$(QUIET_PREFIX) \
{ \
{ \
$(call RUN_PREBUILD_EVENT_ONCE) && \
$(BUILD_DEBUG_ECHO) "Post-Build Event For \"$(NAME)\"" && \
$(call POSTBUILD_EVENT_ACTION) && \
$(TOUCH) $(OBJ_DIR)/_postbuild_event && \
$(RM) -f $(OBJ_DIR)/_postbuild_event_failed; \
} \
|| \
{ \
$(ECHO) "Error executing Post-Build Event for \"$(NAME)\""; \
$(RM) -f $(OBJ_DIR)/_postbuild_event; \
$(TOUCH) $(OBJ_DIR)/_postbuild_event_failed; \
$(FALSE); \
}; \
}
# Everything that should run before anything starts generating intermediate files
_prebuild_steps: _prebuild_always $(OBJ_DIR)/_create_dir
$(QUIET_PREFIX) $(BUILD_DEBUG_ECHO) _prebuild_steps completed
# Everything that needs to run before depgen. Running after custom build tools because they can generate cpp's we depend on
_predepgen_steps: _prebuild_steps $(ALL_CUSTOM_BUILD_TOOL_OUTPUTS)
$(QUIET_PREFIX) $(BUILD_DEBUG_ECHO) _predepgen_steps completed
# Everything that needs to finish before compiling cpps.
_precompile_steps: _predepgen_steps
$(QUIET_PREFIX) $(BUILD_DEBUG_ECHO) _precompile_steps completed
# Everything that needs to finish before linking
_prelink_steps: $(OBJ_DIR)/_prelink_event
$(QUIET_PREFIX) $(BUILD_DEBUG_ECHO) _prelink_steps completed
# Everything to do after linking
_postbuild_steps: $(OBJ_DIR)/_postbuild_event
$(QUIET_PREFIX) $(BUILD_DEBUG_ECHO) _postbuild_steps completed