
# Makefile for MobileSim.
# 
# This Makefile should work on Linux, MinGW on Windows, and perhaps other
# Unix-like systems as well.
#
# Some variables you can override with environment variables:
# 	prefix    Set the installation directory prefix (default is /usr/local)
# 	DESTDIR		Set an alternative filesystem root (normally only used for making
# 						e.g. Debian packages)
# 	CXX				C++ compiler (default is make's default, usually 'c++')
# 	CC      	C compiler (default is make's default, usually 'cc')
# 	CFLAGS    Compilation flags.  This Makefile will also append various options
# 						(see below)
# 	LFLAGS    Linker flags (e.g. library directories). This Makefile will also
# 						append various options (see below)
# 	STAGEDIR  Where to find the Stage source code (default is stage/)
# 	STAGELIBDIR Where to find the Stage library for linking (default is
# 						$(STAGEDIR)/src/.libs)
#
# Some variables that set build options:
#   MOBILESIM_RELEASE  If defined, then an optimized version 
#                          will be built instead of an unoptimized debug
#                          version. Both libstage and MobileSim are built
#                          with optimization.  Also, stage tests will be 
#                          skipped. Use this for releases.
#   
#   MOBILESIM_PROFILE   If defined, then profiling will be enabled
#                          with -pg (for gprof).
#
# Used for variations on the tar.gz bindist package:
# 	TAR_DIRECTORY		If defined, put files to be tarred in a new directory with
# 	this name, rather than MobileSim-$(VERSION). 
# 	BINDIST_SUFFIX	If defined, append this string to the tar.gz package name.
#

ifdef TRACE
REAL_SHELL:=$(SHELL)
SHELL=$(warning at rule   $@.   Modified prerequisites are: [$?]    All prerequisites are: [$^])$(REAL_SHELL)
endif


all: MobileSim

# The current (or next in the case of 'dev' releases) version number. Must match Debian changelog!!
VERSION:=0.5.0
DEBIAN_PKG_REV_APPEND:=
# e.g. DEBIAN_PKG_REV_APPEND:="-3"
RPM_PKG_REV:=0

# TODO automatically use debchange to change debian changelog (see aria/arnl
# makefiles)


COMMON_DISTRIBUTED_FILES=Makefile COPYING Changes.txt README.html screenshot.png PioneerRobotModels.world.inc config/AMROffice.map config/columbia.map icon.png config/MobileSim.desktop version.txt INSTALL.txt

BINARY_DISTRIBUTED_FILES=$(COMMON_DISTRIBUTED_FILES) MobileSim gdbhelper 

SOURCE_DISTRIBUTED_FILES=$(COMMON_DISTRIBUTED_FILES) main.cc README.src.txt *.cpp *.h *.hh *.cc stage/src/*.c stage/src/*.h stage/src/stagecpp.cc stage/src/worldfile.hh stage/src/worldfile.cc stage/src/config.h.in stage/tests/*.c stage/configure.in stage/*/Makefile.in stage/*/Makefile.am stage/*/*/Makefile.in stage/*/*/Makefile.am stage/Makefile.in stage/Makefile.am stage/AUTHORS stage/COPYING stage/ChangeLog stage/README stage/README-Windows.txt stage/aclocal.m4 stage/doxygen.conf.in stage/INSTALL stage/NEWS stage/autoconf-mingw.sh stage/ltmain.sh stage/stage.pc.in stage/replace/*.c stage/replace/*.h convertBitmapToArMap.cc util.h
SOURCE_DISTRIBUTED_FILES_EXEC=stage/configure stage/config.guess stage/config.sub stage/install-sh stage/missing  gdbhelper 

SOURCE_DISTRIBUTED_FILES_MAYBE=stage/compile stage/depcomp

CFLAGS+=-fPIC

#### Different options for debug or release modes
ifdef MOBILESIM_RELEASE

CFLAGS+=-O2
STAGE_CONFIGURE_ARGS:=--disable-debug --enable-optimize=2 --enable-tests

else	 #MOBILESIM_RELEASE

CFLAGS+=-g -O0 -Wall -W -Wconversion
 # -W is the same as -Wextra but supported by gcc 2
STAGE_CONFIGURE_ARGS:=--disable-optimize --enable-debug --enable-tests
datestamp:=$(shell date +%y%m%d)
-include lastDevReleaseVer
ifdef lastDevReleaseVer
lastDevReleaseVerDatestamp:=$(shell echo $(lastDevReleaseVer) | cut -d '.' -f 1)
lastDevReleaseVerRev:=$(shell echo $(lastDevReleaseVer) | cut -d '.' -f 2)
ifeq ($(lastDevReleaseVerDatestamp),$(datestamp))
 ifeq ($(lastDevReleaseVerDatestamp),$(lastDevReleaseVerRev))
  # has no revision
  DEV_RELEASE_VER:=$(datestamp).1
 else
  # increment revision
  DEV_RELEASE_VER:=$(datestamp).$(shell let foo=$(lastDevReleaseVerRev)+1; echo $$foo)
 endif
else
  # new date
  DEV_RELEASE_VER:=$(datestamp)
endif #ifeq lastDevRelease, datestamp
else
  DEV_RELEASE_VER:=$(datestamp)
endif #ifdef lastDevReleaseVer
VERSION:=$(VERSION)~dev$(DEV_RELEASE_VER)
endif	 #MOBILESIM_RELEASE

ifdef MOBILESIM_PROFILE
CXX+=-pg -g -O0
CC+=-pg -g -O0
STAGE_CONFIGURE_ARGS+=--enable-profile --enable-debug --disable-optimize
endif	 #MOBILESIM_PROFILE


# Simbox rule overrides this 
ifndef TAR_DIRECTORY
TAR_DIRECTORY:=MobileSim-$(VERSION)
endif

#### Different options for Windows or Linux:
host:=$(shell uname | cut -d _ -f 1)
ifeq ($(host),MINGW32)	# host is MINGW32 on Windows:

ifdef MOBILESIM_RELEASE
CFLAGS+=-mwindows -mms-bitfields -DMINGW -D__MINGW__ -DARIA_STATIC
else #MOBILESIM_RELEASE
# Omitting -mwindows makes it show stdout to a DOS command window:
CFLAGS+=-mms-bitfields -DMINGW -D__MINGW__ -DARIA_STATIC
endif #MOBILESIM_RELEASE
binary_suffix:=.exe

platformsuffix:=_WIN
SYSTEM_LINK:=-lpthreadGC2 -lwinmm -lws2_32 -lstdc++ 

LIBNETPBM:=libnetpbm/lib/libnetpbm.a
$(LIBNETPBM):
	$(MAKE) -C libnetpbm

else #else assume Linux or Unix:

platformsuffix:=_LIN
SYSTEM_LINK:=-lpthread -lrt
LIBNETPBM:=-lnetpbm

endif #host is MINGW32 or not




###


ARIA_SOURCES:=\
	ariaUtil.cpp \
	ArArgumentBuilder.cpp \
	ArArgumentParser.cpp \
	ArBasePacket.cpp \
	ArConfig.cpp \
	ArConfigArg.cpp \
	ArDeviceConnection.cpp \
	ArFileParser.cpp \
	ArLog.cpp \
	ArMap.cpp \
	ArMutex_LIN.cpp \
	ArRobotPacket.cpp \
	ArRobotPacketReceiver.cpp \
	ArRobotPacketSender.cpp \
	ArRobotParams.cpp \
	ArSocket.cpp \
	ArSocket$(platformsuffix).cpp \
	ArTcpConnection.cpp \
# Note, ArMutex_LIN works on both Linux ond MinGW, since it just uses pthreads.
# ArSocket is different, since it uses Winsock on Windows and Unix sockets on
# Linux.

SOURCES:=\
	main.cc \
	EmulatePioneer.cc \
	RobotFactory.cc \
	StageInterface.cc \
	StageRobotFactory.cc \
	CrashHandler.cc \
	Config.cc \
	$(ARIA_SOURCES)

OBJS:=$(patsubst %.cc,%.o,$(patsubst %.cpp,%.o,$(SOURCES)))

ARIA_OBJS:=$(patsubst %.cpp,%.o,$(ARIA_SOURCES))


CFLAGS+=-I/usr/local/include
LFLAGS+=-L/usr/local/lib

ifndef STAGEDIR
STAGEDIR:=stage
endif

ifndef STAGELIBDIR
STAGELIBDIR:=$(STAGEDIR)/src/.libs
endif

# Root directory that install is relative too. Normally relative 
# to nothing (i.e. in /)
ifndef DESTDIR
DESTDIR:=
endif

STAGELIBS:=$(STAGELIBDIR)/libstage.a $(STAGEDIR)/replace/libreplace.a


#GTK_LIBS=`pkg-config --libs gtk+-2.0`
#GTK_CFLAGS=`pkg-config --cflags gtk+-2.0`
GTK_LIBS:=$(shell pkg-config --libs gtk+-2.0)
GTK_CFLAGS:=$(shell pkg-config --cflags gtk+-2.0)


# For dynamic linkage (always works fine):
GTK_LINK:=$(GTK_LIBS)

# A try at static linkage, has mysterious problems with gobject initialization at runtime:
#GTK_CFLAGS=`pkg-config --cflags --static gtk+-2.0`
#GTK_LINK = \
#	-Wl,-Bstatic \
#		`pkg-config --libs --static gtk+-2.0 | sed 's/-ldl//' | sed 's/-lm//'` \
#		`pkg-config --libs --static xft | sed 's/-ldl//'` \
#		`pkg-config --libs --static xcursor | sed 's/-ldl//' | sed 's/-lX11//'` \
#		`pkg-config --libs --static xrender | sed 's/-ldl//' | sed 's/-lX11//'` \
#		-lXinerama -lXrandr -lfreetype -lexpat -ltiff -ljpeg -lpng -lz -lm \
#	-Wl,-Bdynamic \
#		-lXi -lX11 -ldl


MSIM_CFLAGS := -DMOBILESIM_VERSION=\"$(VERSION)\" \
  -I. $(CFLAGS) -I$(STAGEDIR) -I$(STAGEDIR)/replace  -I$(STAGEDIR)/src \
	$(GTK_CFLAGS)

MSIM_LFLAGS := $(LFLAGS) 


# For installation:
ifndef prefix
prefix:=$(DESTDIR)/usr/local/MobileSim
endif

bindir:=$(prefix)
docdir:=$(prefix)
confdir:=$(prefix)
ourlibdir:=$(prefix)/lib
sysbindir:=$(DESTDIR)/usr/local/bin

# Bypases DESTDIR:
ifndef installed_bindir
installed_bindir:=$(bindir)
endif





debug: MobileSim_debug$(binary_suffix)

%.o: %.cc Makefile.dep 
	$(CXX) -c $(MSIM_CFLAGS) -o $@ $<

%.o: %.cpp Makefile.dep
	$(CXX) -c $(MSIM_CFLAGS) -o $@ $<

%.o: %.c Makefile.dep
	$(CC) -c $(MSIM_CFLAGS) -o $@ $<

Makefile.dep:  $(STAGEDIR)/src/config.h
	$(CXX) $(MSIM_CFLAGS) -MM $(SOURCES) >Makefile.dep

#$(STAGEDIR)/src/config.h

dep: clean clean-dep 
	$(MAKE) Makefile.dep

clean-dep:
	rm Makefile.dep

ifeq (main.cc,$(wildcard main.cc))

# We have source code, depend on it being built
# could depend on $(STAGELIBS) instead of just libstage.a to get both libs, but that can cause make to try
# to build stage twice in parallel if using parallel jobserver, which causes
# corrupted output files.
MobileSim: $(STAGEDIR)/src/stage.h $(STAGEDIR)/src/config.h $(STAGELIBDIR)/libstage.a $(OBJS) 
	$(CXX) $(MSIM_CFLAGS) $(MSIM_LFLAGS) -o MobileSim $(OBJS) $(STAGELIBS) $(GTK_LINK) $(SYSTEM_LINK)

else

# We don't have source code, no dependencies for MobileSim

endif

MobileSim_debug$(binary_suffix): MobileSim
	cp MobileSim$(binary_suffix) MobileSim_debug$(binary_suffix)





ifndef AUTOCONF
AUTOCONF:=autoconf
endif

ifndef AUTORECONF
AUTORECONF:=autoreconf
endif

ifndef ACLOCAL
ACLOCAL:=aclocal
endif

$(STAGEDIR)/config.status $(STAGEDIR)/Makefile $(STAGEDIR)/src/config.h: $(STAGEDIR)/configure
	test -d $(STAGEDIR) || { echo "STAGEDIR \"$(STAGEDIR)\" does not exist. Set STAGEDIR in the environment."; false; }
	+cd $(STAGEDIR); export PKG_CONFIG_PATH=$$PKG_CONFIG_PATH:/usr/local/lib/pkgconfig; \
    ./configure --disable-shared --enable-static \
      --disable-fiducial-model --disable-blobfinder-model --disable-gripper-model \
      --disable-save-world --disable-grid-labels --disable-reload-world \
	  	$(STAGE_CONFIGURE_ARGS)
	touch $@

$(STAGEDIR)/configure:  $(STAGEDIR)/configure.in
	+cd $(STAGEDIR); if test -d /usr/local/share/aclocal; then ARGS="-I /usr/local/share/aclocal"; else ARGS=""; fi; $(AUTORECONF) -i $$ARGS && $(ACLOCAL) $$ARGS && $(AUTOCONF) $$ARGS

stageconf: $(STAGEDIR)/config.status

#	@echo "ERROR: configure script missing from stage! enter stage directory and run 'autoreconf -i' (use --force to force creation or re-creation of files), or unpack the tar archive again."
#	false


convertBitmapToArMap: convertBitmapToArMap.cc $(ARIA_OBJS)
	$(CXX) -o $@ $^ $(LIBNETPBM) -lm -ldl $(SYSTEM_LINK)


help:
	@echo 'Usage:'
	@echo '       make help       This message'
	@echo '       make all or make MobileSim  Build MobileSim program (in debug/dev mode)'
	@echo '       make opt        Build MobileSim program (in optimized/release mode)'
	@echo '       make clean'
	@echo '       make install'
	@echo '       make distclean  Clean temporary files, but leave binaries to be distributed'
	@echo '       make release-dist'
	@echo '       make dev-dist'
	@echo '       make release-srcdist'
	@echo '       make dev-srcdist'
	@echo '       make release-bindist'
	@echo '       make dev-bindist'
	@echo '       make release-windist'
	@echo '       make dev-windist'
	@echo '       make rpm'
	@echo '       make dev-rpm'
	@echo '       make deb'
	@echo '       make dev-deb'
	@echo '       make simbox'
	@echo '       make dev-simbox'
	@echo 'Set environment variable MOBILESIM_RELEASE to build a non-debug version (with optimization flags, with no debugger information, no compiler warnings, and with no logging to terminal on Windows)'
	@echo 'Set environment variable MOBILESIM_PROFILE to build with profiling information (for use with gprof)'
	
info:
	@echo SOURCES=$(SOURCES)
	@echo
	@echo OBJS=$(OBJS)
	@echo
	@echo MSIM_CFLAGS=$(MSIM_CFLAGS)
	@echo
	@echo MSIM_LFLAGS=$(MSIM_LFLAGS)
	@echo
	@echo GTK_LINK=$(GTK_LINK)
	@echo
	@echo SYSTEM_LINK=$(SYSTEM_LINK)

$(STAGELIBDIR)/libstage.a $(STAGEDIR)/replace/libreplace.a: $(STAGEDIR)/config.status $(STAGEDIR)/src/*.c $(STAGEDIR)/src/*.h Makefile $(STAGEDIR)/Makefile
	test -d $(STAGEDIR) || { echo "STAGEDIR \"$(STAGEDIR)\" does not exist. Set STAGEDIR in the environment, or check if there is something wrong with your original source archive or VCS checkout..."; false; }
	$(MAKE) -C $(STAGEDIR) -j1

clean:
	+$(MAKE) -C $(STAGEDIR) -j1 clean
	-rm MobileSim *.o

distclean: 
	$(MAKE) -C $(STAGEDIR) -k -j1 clean distclean 
	-rm *.o


sudo-install:
	sudo $(MAKE) install

dist-install: $(BINARY_DISTRIBUTED_FILES) 
	$(MAKE) install

install:
	install -d $(bindir) $(docdir) $(confdir) $(DESTDIR)/usr/share/applications $(sysbindir) 
	install -s -m 755 MobileSim $(bindir)/MobileSim
	install -m 644 icon.png $(confdir)/icon.png
	install -m 644 config/columbia.map $(confdir)/columbia.map
	install -m 644 config/AMROffice.map $(confdir)/AMROffice.map
	install -m 644 PioneerRobotModels.world.inc $(confdir)/PioneerRobotModels.world.inc
	install -m 644 config/MobileSim.desktop $(DESTDIR)/usr/share/applications/MobileSim.desktop
	install -m 644 README.html $(docdir)/README.html
	install -m 644 screenshot.png $(docdir)/screenshot.png
	install -m 644 Changes.txt $(docdir)/Changes.txt
	install -m 644 INSTALL.txt $(docdir)/INSTALL.txt
	install -m 644 COPYING $(docdir)/COPYING
	install -m 644 version.txt $(docdir)/version.txt
	install -m 755 gdbhelper $(bindir)/gdbhelper
	ln -s -f $(installed_bindir)/MobileSim $(sysbindir)/MobileSim

uninstall:
	-rm $(bindir)/MobileSim $(confdir)/icon.png \
		$(docdir)/README.html $(docdir)/Changes.txt $(docdir)/COPYING \
		$(docdir)/INSTALL.txt \
		/usr/share/applications/MobileSim.desktop \
    $(sysbindir)/MobileSim

rpm:
	$(MAKE) real-rpm MOBILESIM_RELEASE=1

real-rpm: $(BINARY_DISTRIBUTED_FILES) sudo-dist-install config/MobileSim.spec 
	sudo rpm -bb config/MobileSim.spec && cp /usr/src/redhat/RPMS/i386/MobileSim-$(VERSION_NODASH)-$(RPM_PKG_REV).i386.rpm . && echo "Copied RPM into current directory."


debian: deb
deb: 
	fakeroot debian/rules binary MOBILESIM_RELEASE=1

dev-deb: 
	fakeroot debian/rules binary
	echo lastDevReleaseVer=$(DEV_RELEASE_VER) > lastDevReleaseVer

dev-debian: dev-deb

dist: release-dist

release-dist:
	$(MAKE) base-dist MOBILESIM_RELEASE=1

dev-dist: base-dist
	echo lastDevReleaseVer=$(DEV_RELEASE_VER) > lastDevReleaseVer

base-dist: base-srcdist base-bindist

srcdist: release-srcdist

release-srcdist:
	$(MAKE) base-srcdist MOBILESIM_RELEASE=1

dev-srcdist: base-srcdist
	echo lastDevReleaseVer=$(DEV_RELEASE_VER) > lastDevReleaseVer

base-srcdist: $(SOURCE_DISTRIBUTED_FILES)  $(SOURCE_DISTRIBUTED_FILES_EXEC)
	-mkdir MobileSim-src-$(VERSION)
	for d in $(SOURCE_DISTRIBUTED_FILES); do install -m 644 -D -p $$d MobileSim-src-$(VERSION)/$$d; done
	for d in $(SOURCE_DISTRIBUTED_FILES_MAYBE); do if test -f $$d; then install -m 644 -D -p $$d MobileSim-src-$(VERSION)/$$d; fi; done
	for d in $(SOURCE_DISTRIBUTED_FILES_EXEC); do install -m 755 -D -p $$d MobileSim-src-$(VERSION)/$$d; done
	tar cf MobileSim-src-$(VERSION).tar MobileSim-src-$(VERSION)
	gzip -9 MobileSim-src-$(VERSION).tar && mv MobileSim-src-$(VERSION).tar.gz MobileSim-src-$(VERSION).tgz

bindist: release-bindist

release-bindist:
	$(MAKE) base-bindist MOBILESIM_RELEASE=1

dev-bindist: base-bindist
	echo lastDevReleaseVer=$(VERSION) > lastDevReleaseVer


base-bindist: $(BINARY_DISTRIBUTED_FILES) 
	-mkdir -p tmp/$(TAR_DIRECTORY)
	-mkdir tmp/$(TAR_DIRECTORY)/config
	for f in $(BINARY_DISTRIBUTED_FILES); do cp $$f tmp/$(TAR_DIRECTORY)/$$f; done
	cd tmp; tar cf ../MobileSim-$(VERSION)$(BINDIST_SUFFIX).tar $(TAR_DIRECTORY)
	gzip -9 MobileSim-$(VERSION)$(BINDIST_SUFFIX).tar && mv MobileSim-$(VERSION)$(BINDIST_SUFFIX).tar.gz MobileSim-$(VERSION)$(BINDIST_SUFFIX).tgz
	rm -r tmp

test-dist: undo-dist dist
	tar xzf MobileSim-src-$(VERSION).tgz
	cd MobileSim-src-$(VERSION) && $(MAKE)

windist: release-windist

release-windist:
	test ! -d /c/dist/MobileSim
	$(MAKE) base-windist MOBILESIM_RELEASE=1


# Could do a distclean
base-windist: $(BINARY_DISTRIBUTED_FILES) 
	cp -R . /c/dist/MobileSim
	unix2dos /c/dist/MobileSim/*.txt
	@echo Running 7-zip to extract GTK support libs into dist
	cd /c/dist/MobileSim && /c/Program\ Files/7-Zip/7z.exe x /c/src/AriaInternalLibs/WindowsGTKSupportForMobileSim.zip
	@echo 7-zip is done extracting GTK libs into dist.
	@echo files have been copied to C:\\dist\\MobileSim, ready to make installer.

undo-dist:
	-rm -r MobileSim-src-$(VERSION)
	-rm MobileSim-src-$(VERSION).tgz


DATESTR:=$(shell date +'%B %e, %Y')
VERSION_NODASH:=$(subst -,,$(VERSION))

%: %.in Makefile
	sed \
		-e 's/@MOBILESIM_VERSION@/$(VERSION)/g' \
		-e "s/@DATE@/$(DATESTR)/g" \
		-e 's/@MOBILESIM_VERSION_NODASH@/$(VERSION_NODASH)/g' \
		-e 's/@MOBILESIM_RPM_PKG_REV@/$(RPM_PKG_REV)/g' \
		< $< > $@

simbank: release-simbox

simbank-dist: release-simbox

simbox: release-simbox

simbox-dist: release-simbox


release-simbox:
	$(MAKE) base-bindist MOBILESIM_RELEASE=1 TAR_DIRECTORY=MobileSim BINDIST_SUFFIX=-simbox

dev-simbox:
	$(MAKE) base-bindist TAR_DIRECTORY=MobileSim BINDIST_SUFFIX=-simbox
	echo lastDevReleaseVer=$(DEV_RELEASE_VER) > lastDevReleaseVer
	
optimize: opt

opt: 
	$(MAKE) MOBILESIM_RELEASE=1

%-opt:
	$(MAKE) $* MOBILESIM_RELEASE=1

WEBSITE_VERSION_NUMBERS_FILES:=MobileSimVersion.php

# Make PHP files with version numbers for use on website
website-version-numbers: $(WEBSITE_VERSION_NUMBERS_FILES)

# XXX TODO get debian and redhat package revisions from somewhere
%Version.php:
	echo "<?php" > $@
	echo "$$"$*Version=\"$(VERSION)\"\; >> $@
	echo "$$"$*DebianVersion=\"$(VERSION)$(DEBIAN_PKG_REV_APPEND)\"\; >> $@
	echo "$$"$*RedHatVersion=\"$(VERSION)-$(RPM_PKG_REV)\"\; >> $@
	echo "$$"$*TgzVersion=\"$(VERSION)\"\; >> $@
	echo "$$"$*WindowsVersion=\"$(VERSION)\"\; >> $@
	echo "?>" >> $@

upload-website-version-numbers: $(WEBSITE_VERSION_NUMBERS_FILES)
	rsync --update $^ root@192.168.0.8:/var/www/mediawiki/MobileRobotsSoftwareVersionNumbers/

# XXX TODO add rule to rsync the package
# files in with website download directories, creating them as neccesary
# for new versions.


.PHONY: all clean distclean install uninstall dist-install sudo-install sudo-dist-install rpm deb debian dist srcdist bindist test-dist undo-dist simbank opt optimize  stageconf windist base-windist base-bindist base-srcdist dev-debian dev-deb dev-srcdist dev-bindist dev-simbank release-simbank release-srcdist release-bindist

ifeq (Makefile.dep,$(wildcard Makefile.dep))	 # only include Makefile.dep if it exists, don't try to create it implicitly (unless a rule depends on it above)
include Makefile.dep
endif

