# $Id$
# 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!!
SRC_DIR = !!SRC_DIR!!
SCRIPT_SRC_DIR = !!SCRIPT_SRC_DIR!!
MEDIA_DIR = !!MEDIA_DIR!!
TTD = !!TTD!!
STRGEN = !!STRGEN!!
ENDIAN_CHECK = !!ENDIAN_CHECK!!
DEPEND = !!DEPEND!!
ENDIAN_FORCE = !!ENDIAN_FORCE!!
OS = !!OS!!
STAGE = !!STAGE!!
MAKEDEPEND = !!MAKEDEPEND!!
CFLAGS_MAKEDEP = !!CFLAGS_MAKEDEP!!
SORT = !!SORT!!
REVISION = !!REVISION!!
AWK = !!AWK!!
CONFIG_CACHE_COMPILER = $( SRC_OBJS_DIR) /!!CONFIG_CACHE_COMPILER!!
CONFIG_CACHE_LINKER = $( SRC_OBJS_DIR) /!!CONFIG_CACHE_LINKER!!
CONFIG_CACHE_ENDIAN = $( SRC_OBJS_DIR) /!!CONFIG_CACHE_ENDIAN!!
CONFIG_CACHE_SOURCE = $( SRC_OBJS_DIR) /!!CONFIG_CACHE_SOURCE!!
CONFIG_CACHE_VERSION = $( SRC_OBJS_DIR) /!!CONFIG_CACHE_VERSION!!
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) endian_target.h
# Create all dirs and subdirs
RES := $( shell mkdir -p $( BIN_DIR) $( sort $( dir $( OBJS) ) ) )
# Make sure endian_target.h is reasable as if it was in the src/ dir
CFLAGS += -I $( SRC_OBJS_DIR) -I $( LANG_OBJS_DIR)
CFLAGS_MAKEDEP += -I $( SRC_OBJS_DIR) -I $( LANG_OBJS_DIR) -I $( SCRIPT_SRC_DIR)
ENDIAN_TARGETS := endian_target.h $( ENDIAN_CHECK)
# 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' ' )
i f d e f R E V I S I O N
# Use specified revision (which should be of the form "r000").
REV := $( REVISION)
REV_NR := $( shell echo $( REVISION) | sed "s@[^0-9]@@g" )
e l s e
# Use autodetected revisions
REV := $( shell echo " $( VERSIONS) " | cut -f 1 -d' ' )
REV_NR := $( shell echo " $( VERSIONS) " | cut -f 2 -d' ' )
e n d i f
# Make sure we have something in REV and REV_NR
i f e q ( $( REV ) , )
REV := norev000
e n d i f
i f e q ( $( REV_NR ) , )
REV_NR := 0
e n d i f
# This helps to recompile if flags change
RES := $( shell if [ " `cat $( CONFIG_CACHE_COMPILER) 2>/dev/null` " != " $( CXXFLAGS) $( CFLAGS) " ] ; then echo " $( CXXFLAGS) $( CFLAGS) " > $( CONFIG_CACHE_COMPILER) ; fi )
RES := $( shell if [ " `cat $( CONFIG_CACHE_LINKER) 2>/dev/null` " != " $( LDFLAGS) $( LIBS) " ] ; then echo " $( LDFLAGS) $( LIBS) " > $( CONFIG_CACHE_LINKER) ; fi )
RES := $( shell if [ " `cat $( CONFIG_CACHE_ENDIAN) 2>/dev/null` " != " $( ENDIAN_FORCE) " ] ; then echo " $( ENDIAN_FORCE) " > $( CONFIG_CACHE_ENDIAN) ; 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` " != " $( REV) $( MODIFIED) " ] ; then echo " $( REV) $( MODIFIED) " > $( CONFIG_CACHE_VERSION) ; fi )
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 $ ( ENDIAN_TARGETS ) %.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) $( CXXFLAGS) $( CFLAGS) -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) $( CC_HOST) $( CFLAGS) -MM $< | sed 's@^$(@F:%.d=%.o):@$@ $(@:%.d=%.o):@' > $@
$(OBJS_RC : %.o =%.d ): %.d : $( SRC_DIR ) /%.rc $( FILE_DEP )
$( E) '$(STAGE) DEP $(<:$(SRC_DIR)/%.mm=%.mm)'
$( 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 $ ( ENDIAN_TARGETS ) 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) $( CXXFLAGS_BUILD) $( CFLAGS_BUILD) $( LDFLAGS_BUILD) -o $@ $<
e n d i 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
$( Q) $( MAKEDEPEND) -f$( SRC_OBJS_DIR) /Makefile.dep.tmp -o.o -Y -v -- $( CFLAGS_MAKEDEP) -- $( SRCS:%= $( SRC_DIR) /%) 2>/dev/null
# Convert x:/... paths to /x/... for mingw
i f e q ( $( OS ) , M I N G W )
@cat Makefile.dep.tmp | sed 's@/\([a-zA-Z]\):\/@\/\1\/@g' > Makefile.dep.tmp.mingw
@cp Makefile.dep.tmp.mingw Makefile.dep.tmp
@rm -f Makefile.dep.tmp.mingw
e n d i f
# 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@ $$ @@' | $( 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 $@ $<
$(OBJS_CPP) : %.o : $( SRC_DIR ) /%.cpp $( DEP_MASK ) $( FILE_DEP )
$( E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.cpp=%.cpp)'
$( Q) $( CXX_HOST) $( CXXFLAGS) $( CFLAGS) -c -o $@ $<
$(OBJS_MM) : %.o : $( SRC_DIR ) /%.mm $( DEP_MASK ) $( FILE_DEP )
$( E) '$(STAGE) Compiling $(<:$(SRC_DIR)/%.mm=%.mm)'
$( Q) $( CC_HOST) $( CFLAGS) -c -o $@ $<
$(OBJS_RC) : %.o : $( SRC_DIR ) /%.rc $( FILE_DEP )
$( E) '$(STAGE) Compiling resource $(<:$(SRC_DIR)/%.rc=%.rc)'
$( Q) $( WINDRES) -o $@ -I $( MEDIA_DIR) $<
$(BIN_DIR)/$(TTD) : $( TTD )
$( Q) cp $< $@
$(TTD) : $( OBJS ) $( CONFIG_CACHE_LINKER )
$( E) '$(STAGE) Linking $@'
i f e q ( $( OS ) , P S P )
# Because of a bug in the PSP GCC tools, linking via CXX results
# in total chaos and more problems then you can handle. So we need
# CC to link OpenTTD for PSP
$( Q) $( CC_HOST) $( LDFLAGS) $( OBJS) $( LIBS) -o $@
e l s e
$( Q) $( CXX_HOST) $( LDFLAGS) $( OBJS) $( LIBS) -o $@
e n d i f
i f d e f S T R I P
$( Q) $( STRIP) $@
i f e q ( $( OS ) , D O S )
$( E) '$(STAGE) Adding CWSDPMI stub to $@'
$( Q) $( ROOT_DIR) /os/dos/make_dos_binary_selfcontained.sh $( SRC_OBJS_DIR) /$@
e n d i f
e n d i f
# The targets to compile the endian-code
endian_target.h : $( ENDIAN_CHECK ) $( CONFIG_CACHE_ENDIAN )
$( E) '$(STAGE) Testing endianness for target'
$( Q) ./$( ENDIAN_CHECK) $( ENDIAN_FORCE) > $@
$(ENDIAN_CHECK) : $( SRC_DIR ) /endian_check .cpp
$( E) '$(STAGE) Compiling and Linking $@'
$( Q) $( CXX_BUILD) $( CXXFLAGS_BUILD) $( CFLAGS_BUILD) $< -o $@
# Revision files
$(SRC_DIR)/rev.cpp : $( CONFIG_CACHE_VERSION ) $( SRC_DIR ) /rev .cpp .in
$( Q) cat $( SRC_DIR) /rev.cpp.in | sed " s@\!\!REVISION\!\!@ $( REV_NR) @g;s@!!VERSION!!@ $( REV) @g;s@!!MODIFIED!!@ $( MODIFIED) @g;s@!!DATE!!@`date +%d.%m.%y`@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@\!\!REVISION\!\!@ $( REV_NR) @g;s@!!VERSION!!@ $( REV) @g;s@!!DATE!!@`date +%d.%m.%y`@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) /%) $( CONFIG_CACHE_COMPILER) $( CONFIG_CACHE_LINKER) $( CONFIG_CACHE_ENDIAN) $( CONFIG_CACHE_SOURCE) $( ENDIAN_TARGETS)
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