# This file is part of OpenTTD.
# OpenTTD is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, version 2.
# OpenTTD is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenTTD. If not, see <http://www.gnu.org/licenses/>.
CC_HOST = !!CC_HOST!!
CXX_HOST = !!CXX_HOST!!
CC_BUILD = !!CC_BUILD!!
CXX_BUILD = !!CXX_BUILD!!
WINDRES = !!WINDRES!!
STRIP = !!STRIP!!
CFLAGS = !!CFLAGS!!
CFLAGS_BUILD = !!CFLAGS_BUILD!!
CXXFLAGS = !!CXXFLAGS!!
CXXFLAGS_BUILD = !!CXXFLAGS_BUILD!!
LIBS = !!LIBS!!
LDFLAGS = !!LDFLAGS!!
LDFLAGS_BUILD = !!LDFLAGS_BUILD!!
ROOT_DIR = !!ROOT_DIR!!
BIN_DIR = !!BIN_DIR!!
LANG_DIR = !!LANG_DIR!!
SRC_OBJS_DIR = !!SRC_OBJS_DIR!!
LANG_OBJS_DIR = !!LANG_OBJS_DIR!!
SETTING_OBJS_DIR = !!SETTING_OBJS_DIR!!
SRC_DIR = !!SRC_DIR!!
SCRIPT_SRC_DIR = !!SCRIPT_SRC_DIR!!
MEDIA_DIR = !!MEDIA_DIR!!
TTD = !!TTD!!
STRGEN = !!STRGEN!!
DEPEND = !!DEPEND!!
OS = !!OS!!
STAGE = !!STAGE!!
MAKEDEPEND = !!MAKEDEPEND!!
CFLAGS_MAKEDEP = !!CFLAGS_MAKEDEP!!
SORT = !!SORT!!
AWK = !!AWK!!
CONFIGURE_INVOCATION = !!CONFIGURE_INVOCATION!!
CONFIG_CACHE_COMPILER = $( SRC_OBJS_DIR) /!!CONFIG_CACHE_COMPILER!!
CONFIG_CACHE_LINKER = $( SRC_OBJS_DIR) /!!CONFIG_CACHE_LINKER!!
CONFIG_CACHE_SOURCE = $( SRC_OBJS_DIR) /!!CONFIG_CACHE_SOURCE!!
CONFIG_CACHE_VERSION = $( SRC_OBJS_DIR) /!!CONFIG_CACHE_VERSION!!
CONFIG_CACHE_INVOCATION = $( SRC_OBJS_DIR) /!!CONFIG_CACHE_INVOCATION!!
OBJS_C := !!OBJS_C!!
OBJS_CPP := !!OBJS_CPP!!
OBJS_MM := !!OBJS_MM!!
OBJS_RC := !!OBJS_RC!!
OBJS := $( OBJS_C) $( OBJS_CPP) $( OBJS_MM) $( OBJS_RC)
SRCS := !!SRCS!!
# All C-files depend on those 3 files
FILE_DEP := $( CONFIG_CACHE_COMPILER)
# Create all dirs and subdirs
RES := $( shell mkdir -p $( BIN_DIR) $( sort $( dir $( OBJS) ) ) )
CFLAGS += -I $( SRC_OBJS_DIR) -I $( LANG_OBJS_DIR) -I $( SETTING_OBJS_DIR)
CFLAGS_MAKEDEP += -I $( SRC_OBJS_DIR) -I $( LANG_OBJS_DIR) -I $( SETTING_OBJS_DIR)
i f d e f S C R I P T _ S R C _ D I R
CFLAGS_MAKEDEP += -I $( SCRIPT_SRC_DIR)
e n d i f
# Check if we want to show what we are doing
i f d e f V E R B O S E
Q =
E = @true
e l s e
Q = @
E = @echo
e n d i f
# Our default target
all : $( BIN_DIR ) /$( TTD )
# This are 2 rules that are pointing back to STRGEN stuff.
# There is not really a need to have them here, but in case
# some weirdo wants to run 'make' in the 'src' dir and expects
# the languages to be recompiled, this catches that case and
# takes care of it nicely.
$(LANG_OBJS_DIR)/$(STRGEN) :
$( MAKE) -C $( LANG_OBJS_DIR) $( STRGEN)
$(LANG_OBJS_DIR)/table/strings.h : $( LANG_DIR ) /english .txt $( LANG_OBJS_DIR ) /$( STRGEN )
$( MAKE) -C $( LANG_OBJS_DIR) table/strings.h
# Always run version detection, so we always have an accurate modified
# flag
VERSIONS := $( shell AWK = " $( AWK) " " $( ROOT_DIR) /findversion.sh " )
MODIFIED := $( shell echo " $( VERSIONS) " | cut -f 3 -d' ' )
# Use autodetected revisions
VERSION := $( shell echo " $( VERSIONS) " | cut -f 1 -d' ' )
ISODATE := $( shell echo " $( VERSIONS) " | cut -f 2 -d' ' )
GITHASH := $( shell echo " $( VERSIONS) " | cut -f 4 -d' ' )
ISTAG := $( shell echo " $( VERSIONS) " | cut -f 5 -d' ' )
ISSTABLETAG := $( shell echo " $( VERSIONS) " | cut -f 6 -d' ' )
# Make sure we have something in VERSION and ISODATE
i f e q ( $( VERSION ) , )
VERSION := norev000
e n d i f
i f e q ( $( ISODATE ) , )
ISODATE := 00000000
e n d i f
# This helps to recompile if flags change
RES := $( shell if [ " `cat $( CONFIG_CACHE_COMPILER) 2>/dev/null` " != " $( CFLAGS) $( CXXFLAGS) " ] ; then echo " $( CFLAGS) $( CXXFLAGS) " > $( CONFIG_CACHE_COMPILER) ; fi )
RES := $( shell if [ " `cat $( CONFIG_CACHE_LINKER) 2>/dev/null` " != " $( LDFLAGS) $( LIBS) " ] ; then echo " $( LDFLAGS) $( LIBS) " > $( CONFIG_CACHE_LINKER) ; fi )
# If there is a change in the source-file-list, make sure we recheck the deps
RES := $( shell if [ " `cat $( CONFIG_CACHE_SOURCE) 2>/dev/null` " != " $( SRCS) " ] ; then echo " $( SRCS) " > $( CONFIG_CACHE_SOURCE) ; fi )
# If there is a change in the revision, make sure we recompile rev.cpp
RES := $( shell if [ " `cat $( CONFIG_CACHE_VERSION) 2>/dev/null` " != " $( VERSION) $( MODIFIED) " ] ; then echo " $( VERSION) $( MODIFIED) " > $( CONFIG_CACHE_VERSION) ; fi )
# If there is a change in the configure invocation, make sure we recompile rev.cpp
RES := $( shell if [ " `cat $( CONFIG_CACHE_INVOCATION) 2>/dev/null` " != " $( CONFIGURE_INVOCATION) " ] ; then echo " $( CONFIGURE_INVOCATION) " > $( CONFIG_CACHE_INVOCATION) ; fi )
FILTER_OUT = $( foreach v,$( 2) ,$( if $( findstring $( 1) ,$( v) ) ,,$( v) ) )
CONFIGURE_DEFINES := $( strip $( call FILTER_OUT,_DIR= ,$( patsubst -D%,%,$( filter -D%,$( CFLAGS) ) ) ) )
i f n d e f M A K E D E P E N D
# The slow, but always correct, dep-check
DEP_MASK := %.d
DEPS := $( OBJS:%.o= %.d)
# Only include the deps if we are compiling everything
i f e q ( $( filter %.o clean mrproper , $ ( MAKECMDGOALS ) ) , )
- i n c l u d e $( DEPS )
e l s e
# In case we want to compile a single target, include the .d file for it
i f n e q ( $( filter %.o , $ ( MAKECMDGOALS ) ) , )
SINGLE_DEP := $( filter %.o, $( MAKECMDGOALS) )
-include $(SINGLE_DEP : %.o =%.d )
e n d i f
e n d i f
# Find the deps via GCC. Rarely wrong, but a bit slow
$(OBJS_C : %.o =%.d ): %.d : $( SRC_DIR ) /%.c $( FILE_DEP )
$( E) '$(STAGE) DEP $(<:$(SRC_DIR)/%.c=%.c)'
$( Q) $( CC_HOST) $( CFLAGS) -MM $< | sed 's@^$(@F:%.d=%.o):@$@ $(@:%.d=%.o):@' > $@
$(OBJS_CPP : %.o =%.d ): %.d : $( SRC_DIR ) /%.cpp $( FILE_DEP )
$( E) '$(STAGE) DEP $(<:$(SRC_DIR)/%.cpp=%.cpp)'
$( Q) $( CXX_HOST) $( CFLAGS) $( CXXFLAGS) -MM $< | sed 's@^$(@F:%.d=%.o):@$@ $(@:%.d=%.o):@' > $@
$(OBJS_MM : %.o =%.d ): %.d : $( SRC_DIR ) /%.mm $( FILE_DEP )
$( E) '$(STAGE) DEP $(<:$(SRC_DIR)/%.mm=%.mm)'
$( Q) $( CXX_HOST) $( CFLAGS) $( CXXFLAGS) -MM $< | sed 's@^$(@F:%.d=%.o):@$@ $(@:%.d=%.o):@' > $@
$(OBJS_RC : %.o =%.d ): %.d : $( SRC_DIR ) /%.rc $( FILE_DEP )
$( E) '$(STAGE) DEP $(<:$(SRC_DIR)/%.rc=%.rc)'
$( Q) touch $@
e l s e
# The much faster, but can be wrong, dep-check
DEP_MASK :=
DEPS := Makefile.dep
# Only include the deps if we are not cleaning
i f e q ( $( filter depend clean mrproper , $ ( MAKECMDGOALS ) ) , )
- i n c l u d e M a k e f i l e . d e p
e n d i f
i f e q ( "$(SRC_OBJS_DIR)/$(DEPEND)" , "$(MAKEDEPEND)" )
DEP := $( MAKEDEPEND)
$(SRC_OBJS_DIR)/$(DEPEND) : $( SRC_DIR ) /depend /depend .cpp
$( E) '$(STAGE) Compiling and linking $(DEPEND)'
$( Q) $( CXX_BUILD) $( CFLAGS_BUILD) $( CXXFLAGS_BUILD) $( LDFLAGS_BUILD) -o $@ $<
e n d i f
# Macro for invoking a command on groups of 100 words at a time
# (analogous to xargs(1)). The macro invokes itself recursively
# until the list of words is depleted.
#
# Usage: $(call xargs,COMMAND,LIST)
#
# COMMAND should be a shell command to which the words will be
# appended as arguments in groups of 100.
d e f i n e x a r g s
$( 1) $( wordlist 1,100,$ ( 2) )
$( if $ ( word 101,$ ( 2) ) ,$ ( call xargs ,$ ( 1) ,$ ( wordlist 101,$ ( words $ ( 2) ) ,$ ( 2) ) ) )
e n d e f
# Make sure that only 'make depend' ALWAYS triggers a recheck
i f e q ( $( filter depend , $ ( MAKECMDGOALS ) ) , )
Makefile.dep : $( FILE_DEP ) $( SRCS :%=$ ( SRC_DIR ) /%) $( CONFIG_CACHE_SOURCE ) $( DEP )
e l s e
Makefile.dep : $( FILE_DEP ) $( SRCS :%=$ ( SRC_DIR ) /%) $( DEP ) FORCE
e n d i f
$( E) '$(STAGE) DEP CHECK (all files)'
$( Q) rm -f Makefile.dep.tmp
$( Q) touch Makefile.dep.tmp
# Calculate the deps via makedepend
$( call xargs,$( Q) $( MAKEDEPEND) -f$( SRC_OBJS_DIR) /Makefile.dep.tmp -o.o -Y -v -a -- $( CFLAGS_MAKEDEP) -- 2>/dev/null,$( SRCS:%= $( SRC_DIR) /%) )
# Remove all comments and includes that don't start with $(SRC_DIR)
# Remove $(SRC_DIR) from object-file-name
@$( AWK) ' \
/^# DO NOT/ { print $$ 0 ; next} \
/^#/ { next} \
/: / { \
left = NF - 1; \
for ( n = 2; n <= NF; n++) { \
if ( match( $$ n, " ^ $( ROOT_DIR) " ) = = 0) { \
$$ n = "" ; \
left--; \
} \
} \
gsub( " $( SRC_DIR) / " , "" , $$ 1) ; \
if ( left > 0) { \
print $$ 0; \
$$ 1 = "Makefile.dep:" ; \
print $$ 0; \
} \
next \
} \
{ \
print $$ 0 \
} \
' < Makefile.dep.tmp | sed ' s@ *@ @g; s@ $$ @@' | LC_ALL = C $( SORT) > Makefile.dep
$( Q) rm -f Makefile.dep.tmp Makefile.dep.tmp.bak
e n d i f
# Avoid problems with deps if a .h/.hpp/.hpp.sq file is deleted without the deps
# being updated. Now the Makefile continues, the deps are recreated
# and all will be fine.
%.h %.hpp %.hpp.sq :
@true
# Compile all the files according to the targets
$(OBJS_C) : %.o : $( SRC_DIR ) /%.c $( DEP_MASK ) $( FILE_DEP )
$( E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.c=%.c)'
$( Q) $( CC_HOST) $( CFLAGS) -c -o $@ $<
$(filter-out %sse2.o, $(filter-out %ssse3.o, $(filter-out %sse4.o, $(OBJS_CPP)))) : %.o : $( SRC_DIR ) /%.cpp $( DEP_MASK ) $( FILE_DEP )
$( E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
$( Q) $( CXX_HOST) $( CFLAGS) $( CXXFLAGS) -c -o $@ $<
$(filter %sse2.o, $(OBJS_CPP)) : %.o : $( SRC_DIR ) /%.cpp $( DEP_MASK ) $( FILE_DEP )
$( E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
$( Q) $( CXX_HOST) $( CFLAGS) $( CXXFLAGS) -c -msse2 -o $@ $<
$(filter %ssse3.o, $(OBJS_CPP)) : %.o : $( SRC_DIR ) /%.cpp $( DEP_MASK ) $( FILE_DEP )
$( E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
$( Q) $( CXX_HOST) $( CFLAGS) $( CXXFLAGS) -c -mssse3 -o $@ $<
$(filter %sse4.o, $(OBJS_CPP)) : %.o : $( SRC_DIR ) /%.cpp $( DEP_MASK ) $( FILE_DEP )
$( E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
$( Q) $( CXX_HOST) $( CFLAGS) $( CXXFLAGS) -c -msse4.1 -o $@ $<
$(OBJS_MM) : %.o : $( SRC_DIR ) /%.mm $( DEP_MASK ) $( FILE_DEP )
$( E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.mm=%.mm)'
$( Q) $( CXX_HOST) $( CFLAGS) $( CXXFLAGS) -c -o $@ $<
$(OBJS_RC) : %.o : $( SRC_DIR ) /%.rc $( FILE_DEP )
$( E) '$(STAGE) Compiling resource $(<:$(SRC_DIR)/%.rc=%.rc)'
$( Q) $( WINDRES) -o $@ $<
$(BIN_DIR)/$(TTD) : $( TTD )
$( Q) cp $( TTD) $( BIN_DIR) /$( TTD)
i f e q ( $( OS ) , U N I X )
$( Q) cp $( MEDIA_DIR) /openttd.32.bmp $( BIN_DIR) /baseset/
e n d i f
i f e q ( $( OS ) , O S X )
$( Q) cp $( ROOT_DIR) /os/macosx/splash.png $( BIN_DIR) /baseset/
e n d i f
$(TTD) : $( OBJS ) $( CONFIG_CACHE_LINKER )
$( E) '$(STAGE) Linking $@'
$( Q) +$( CXX_HOST) $( LDFLAGS) $( OBJS) $( LIBS) -o $@
i f d e f S T R I P
$( Q) $( STRIP) $@
e n d i f
# Revision files
$(SRC_DIR)/rev.cpp : $( CONFIG_CACHE_VERSION ) $( CONFIG_CACHE_INVOCATION ) $( SRC_DIR ) /rev .cpp .in
$( Q) cat $( SRC_DIR) /rev.cpp.in | sed " s@\!\!ISODATE\!\!@ $( ISODATE) @g;s@!!VERSION!!@ $( VERSION) @g;s@!!MODIFIED!!@ $( MODIFIED) @g;s@!!DATE!!@`date +%d.%m.%y`@g;s@!!GITHASH!!@ $( GITHASH) @g;s@!!ISTAG!!@ $( ISTAG) @g;s@!!ISSTABLETAG!!@ $( ISSTABLETAG) @g;s@\!\!CONFIGURE_INVOCATION\!\!@ $( subst \" ,\\ \\ \\ \" ,$( subst @,\\ @,$( CONFIGURE_INVOCATION) ) ) @g;s@\!\!CONFIGURE_DEFINES\!\!@ $( subst \" ,\\ \\ \\ \" ,$( subst @,\\ @,$( subst \\ ,\\ \\ ,$( CONFIGURE_DEFINES) ) ) ) @g; " > $( SRC_DIR) /rev.cpp
$(SRC_DIR)/os/windows/ottdres.rc : $( CONFIG_CACHE_VERSION ) $( SRC_DIR ) /os /windows /ottdres .rc .in
$( Q) cat $( SRC_DIR) /os/windows/ottdres.rc.in | sed " s@\!\!ISODATE\!\!@ $( ISODATE) @g;s@!!VERSION!!@ $( VERSION) @g;s@!!DATE!!@`date +%d.%m.%y`@g;s@!!GITHASH!!@ $( GITHASH) @g;s@!!ISTAG!!@ $( ISTAG) @g;s@!!ISSTABLETAG!!@ $( ISSTABLETAG) @g " > $( SRC_DIR) /os/windows/ottdres.rc
FORCE :
depend : $( DEPS )
clean :
$( E) '$(STAGE) Cleaning up object files'
$( Q) rm -f $( DEPS) $( OBJS) $( TTD) $( DEPEND) $( TTD:%= $( BIN_DIR) /%) $( BIN_DIR) /baseset/openttd.32.bmp $( CONFIG_CACHE_COMPILER) $( CONFIG_CACHE_LINKER) $( CONFIG_CACHE_SOURCE)
mrproper : clean
$( Q) rm -f $( SRC_DIR) /rev.cpp $( SRC_DIR) /os/windows/ottdres.rc
%.o :
@echo '$(STAGE) No such source-file: $(@:%.o=%).[c|cpp|mm|rc]'
.PHONY : all mrproper depend clean FORCE