#!/bin/sh

# acprep, version 3.0
#
# This script configures my ledger source tree on my Mac OS/X machine.  This
# is not necessary, however, since I keep all the files necessary for building
# checked in to the source tree.  Users can just type './configure && make'.
# This script simply sets up the compiler and linker flags for all the various
# build permutations I use for testing and profiling.

if [ -d .git ]; then
    # Make sure that all of the dependencies are available
    git submodule init
    git submodule update

    COMMIT=$(git describe --all --long | sed 's/heads\///')
else
    COMMIT=unknown
fi


echo "m4_define([VERSION_NUMBER], [$COMMIT])" > version.m4
sh autogen.sh


# configure the template files
if [ ! -f po/Makevars ]; then
    mv po/Makevars.template po/Makevars
fi
git ls-files '*.cc' '*.h' | egrep '^(src|python)/' > po/POTFILES.in

# regenerate aclocal.m4
aclocal -I m4


SWITCHES="--with-included-gettext"

if [ -z "$PYTHON_HOME" ]; then
    PYTHON_HOME="/usr"
fi
if [ -z "$PYTHON_VERSION" ]; then
    PYTHON_VERSION="2.5"
fi


BOOST_VERSION="1_38"
BOOST_SUFFIX=""
for lib in $(ls -1 /opt/local/lib/libboost_regex*.a \
                   /usr/local/lib/libboost_regex*.a 2> /dev/null \
             | sort -r)
do
    lib=$(basename "$lib")
    suffix=$(echo "$lib" | sed 's/libboost_regex-//' | sed 's/\.a//')
    if [ ! "$suffix" = "libboost_regex" ]; then
	echo "Discovered Boost suffix: --boost $suffix"
	BOOST_SUFFIX="-$suffix"
    fi
    break
done


USE_GLIBCXX_DEBUG=true
CXXFLAGS=""
ARCHFLAGS=""
LDFLAGS=""
LDARCHFLAGS=""


INCDIRS=""
for include in					\
    /usr/local/include				\
    /usr/local/include/boost-$BOOST_VERSION	\
    $PYTHON_HOME/include/python$PYTHON_VERSION	\
    /opt/local/include				\
    /sw/include
do
    if [ -d "$include" ]; then
	INCDIRS="$INCDIRS -isystem $include"
    fi
done

LIBDIRS=""
for lib in						\
    /usr/local/lib					\
    $PYTHON_HOME/lib					\
    $PYTHON_HOME/lib/python$PYTHON_VERSION/config	\
    /opt/local/lib					\
    /sw/lib
do
    if [ -d "$lib" ]; then
	LIBDIRS="$LIBDIRS -L$lib"
    fi
done


SYSTEM=$(uname -s)

if [ $SYSTEM = Linux ]; then
    if [ "$(uname -m)" = x86_64 ]; then
	SWITCHES="--disable-static"
    fi
    CXXFLAGS="-pthread"
elif [ $SYSTEM = Solaris ]; then
    CXXFLAGS="-pthreads"
elif [ $SYSTEM = Darwin ]; then
    ARCHFLAGS="-arch i386 -arch ppc -isysroot /Developer/SDKs/MacOSX10.5.sdk"
    LDARCHFLAGS="$ARCHFLAGS -Wl,-syslibroot,/Developer/SDKs/MacOSX10.5.sdk"
fi


# Building the command-line tool as a shared library is a luxury,
# since there are no clients except a GUI tool which might use it (and
# that is built again anyway by Xcode).
CPPFLAGS="$INCDIRS"
CXXFLAGS="$CXXFLAGS -pipe"
LDFLAGS="$LDFLAGS $LIBDIRS"
BUILD_DIR=false


# The following are options to prepare a developer tree of Ledger for
# building:
#
# --debug
#
#   Build with debugging information.  This doesn't slow things down by much,
#   but gives you useful stack traces to mention in your bug reports.
#   Recommended if you're not running a release version.
#
# --build PATH
#
#   Building the sources in PATH instead of in the source directory.  This
#   breaks pre-compiled headers, but keeps your source tree clean.
#
# --boost SUFFIX
#
#   Use the boost library with the given SUFFIX.  Check the Boost "Getting
#   Started" documentation for what the different suffixes are and what they
#   mean.  Usually you can see the available suffixes on your system using
#   something like this command:
#
#    $ ls /usr/local/lib/libboost_date_time*
#
#   Here's everything that's available on my machine right now:
#
#    ""      - dynamic optimized Boost library
#    d       - dynamic debug
#    s       - static optimized
#    sd      - static debug
#    mt      - multi-threaded optimized
#    mt-d    - multi-threaded debug
#    mt-s    - multi-threaded static optimized
#    mt-sd   - multi-threaded static debug
#
#   Since Ledger does not use threading, I recommend using the static
#   optimized library unless you wish to build with debugging enabled.  If you
#   want to do that, see the --devel switch below.
#
# --devel
#
#   This means you want to build like the developer does, which means:
#
#    * using pre-compiled headers
#    * with glibc debugging enabled
#    * static linking as much as possible
#
#   The glibc debugging is the only tricky part, since you must have Boost
#   compiled with _GLIBCXX_DEBUG defined also -- which it won't be on your
#   system by default.
#  
#   So, you have to roll your own set of Boost debug libraries in order to
#   support this.  I like this because it gives me the most amount of safety
#   and checking possible, which is great for testing.  Here's how I build a
#   super-debugging Boost:
#
#      src $ git clone git://repo.or.cz/boost.git
#      src $ git checkout svn/Version_$BOOST_VERSION
#      src $ cd boost
#    boost $ sudo bjam release --prefix=/usr/local/stow/boost_$BOOST_VERSION \
#                --build-dir=$HOME/Products/boost_$BOOST_VERSION --toolset=darwin \
#                architecture=combined install
#    boost $ sudo bjam debug --prefix=/usr/local/stow/boost_$BOOST_VERSION \
#                --build-dir=$HOME/Products/boost_$BOOST_VERSION --toolset=darwin \
#                architecture=combined define=_GLIBCXX_DEBUG=1 install
#    boost $ cd /usr/local/stow
#     stow $ stow boost_$BOOST_VERSION
#
#   Of course, you'll need MacPorts to do this, with both the "bjam" and "stow"
#   packages installed.
#
#   Lastly, you need to build cppunit by hand with GLIBCXX_DEBUG also, or else
#   you'll see UniTests crash in flames and none of the unit tests will run.
#  
#   Now you're ready to run acprep like this:
#  
#    $ ./acprep --devel --debug --boost sd
#
#   Or, as I do it:
#
#    $ ./myacprep
#
# --release
#
#   This is the opposite of --devel: it means you wish to build in a release
#   scenario, preparing a universal binary and building against the non-debug
#   versions of Boost and CppUnit.
#
# NOTE: I do not expect anyone but me to use --devel or --release, so don't be
# surprised if it doesn't work as advertised.  In that case, look for me in
# the #ledger channel on the IRC server irc.freenode.net.

DO_BUILD=false

while [ -n "$1" ]; do
  case "$1" in
    --pch)
	  USE_GLIBCXX_DEBUG=false

	  SWITCHES="$SWITCHES --enable-pch"

          # These can cause problems when run against a full set of headers,
          # but with PCH, they only apply to Ledger itself
	  CXXFLAGS="$CXXFLAGS -Wconversion"
	  CXXFLAGS="$CXXFLAGS -Wold-style-cast"

	  # g++ 4.0.1 cannot use PCH headers on OS X 10.5, so we must use a
	  # newer version.  However, it also means I can't use GLIBCXX_DEBUG.
	  if [ -f /usr/bin/g++-4.2 ]; then
	      if [ -f /opt/local/bin/ccache ]; then
		  CC="ccache /usr/bin/gcc-4.2"
		  CXX="ccache /usr/bin/g++-4.2"
		  LD="ccache /usr/bin/g++-4.2"
	      else
		  CC=/usr/bin/gcc-4.2
		  CXX=/usr/bin/g++-4.2
		  LD=/usr/bin/g++-4.2
	      fi
	  fi
	  shift 1 ;;

    --devel)
	if [ $USE_GLIBCXX_DEBUG = true ]; then
	    CPPFLAGS="$CPPFLAGS -D_GLIBCXX_DEBUG=1"
	    CPPFLAGS="-isystem /usr/local/stow/cppunit-debug/include $CPPFLAGS"
	    LDFLAGS="-L/usr/local/stow/cppunit-debug/lib $LDFLAGS"

	    # I build my debug Boost libs with _GLIBCXX_DEBUG
	    BOOST_SUFFIX="-xgcc40-d-$BOOST_VERSION"
	else

	    CPPFLAGS="-isystem /usr/local/stow/cppunit/include $CPPFLAGS"
	    LDFLAGS="-L/usr/local/stow/cppunit/lib $LDFLAGS"
	fi
	shift 1 ;;

    --warn)
	# Warning flags
	CXXFLAGS="$CXXFLAGS -Wall -ansi -Winvalid-pch"
	CXXFLAGS="$CXXFLAGS -Wextra"
	CXXFLAGS="$CXXFLAGS -Wcast-align"
	CXXFLAGS="$CXXFLAGS -Wcast-qual"
	CXXFLAGS="$CXXFLAGS -Wfloat-equal"
	CXXFLAGS="$CXXFLAGS -Wmissing-field-initializers"
	CXXFLAGS="$CXXFLAGS -Wno-endif-labels"
	CXXFLAGS="$CXXFLAGS -Woverloaded-virtual"
	CXXFLAGS="$CXXFLAGS -Wsign-compare"
	CXXFLAGS="$CXXFLAGS -Wsign-promo"
	CXXFLAGS="$CXXFLAGS -Wstrict-null-sentinel"
	CXXFLAGS="$CXXFLAGS -Wwrite-strings"
	CXXFLAGS="$CXXFLAGS -Wno-old-style-cast"
	CXXFLAGS="$CXXFLAGS -Wno-deprecated"
	shift 1 ;;

    --debug)
	SWITCHES="$SWITCHES --enable-debug"
	CXXFLAGS="$CXXFLAGS -g"
	LDFLAGS="$LDFLAGS -g"
	shift 1 ;;
      
    --boost)
	shift 1
	BOOST_SUFFIX="-$1"
	shift 1 ;;

    --gcov)
	CXXFLAGS="$CXXFLAGS -fprofile-arcs -ftest-coverage"
	shift 1 ;;

    --gprof)
        CXXFLAGS="$CXXFLAGS -g -pg"
        LDFLAGS="$LDFLAGS -g -pg"
	shift 1 ;;

    --pic)
	CXXFLAGS="$CXXFLAGS -fPIC"
	shift 1 ;;

    --opt)
	CXXFLAGS="$CXXFLAGS -fomit-frame-pointer -O3"
	shift 1 ;;

    --output)
	shift 1
	BUILD_DIR="$1"
	shift 1 ;;

    --build)
	DO_BUILD=true
	shift 1 ;;

    --switch)
	shift 1
	SWITCHES="$SWITCHES $1"
	shift 1 ;;

    --local)
	shift 1 ;;

    --release)
	SWITCHES="$SWITCHES --disable-dependency-tracking"
	CPPFLAGS="-isystem /usr/local/stow/cppunit/include $CPPFLAGS"
	#CXXFLAGS="$CXXFLAGS $ARCHFLAGS"
	#LDFLAGS="$LDFLAGS $LDARCHFLAGS"
	LDFLAGS="-L/usr/local/stow/cppunit/lib $LDFLAGS"

	shift 1 ;;

    *)
	break ;;
  esac
done


HERE="$PWD"

if [ ! "$BUILD_DIR" = "false" ]; then
    if [ ! -d "$BUILD_DIR" ]; then
	mkdir -p "$BUILD_DIR"
    fi
    cd "$BUILD_DIR" || (echo "Cannot change to $BUILD_DIR"; exit 1)
fi

SWITCHES="$SWITCHES --with-boost-suffix=$BOOST_SUFFIX"

PATH="$PYTHON_HOME/bin:$PATH" \
    "$HERE/configure" --srcdir="$HERE" \
	CXX="$CXX" CPPFLAGS="$CPPFLAGS" CXXFLAGS="$CXXFLAGS" \
	LDFLAGS="$LDFLAGS" LIBS="$LIBS" \
	$SWITCHES


# Alter the Makefile so that it's not nearly so verbose.  This makes errors
# and warnings much easier to spot.

if [ -f Makefile ]; then
    perl -i -pe 's/^\t(\$\((LIBTOOL|CXX)\).*?\.(cc|cpp))$/\t\@echo "   " CXX \$\@;$1 > \/dev\/null/;' Makefile
    perl -i -pe 's/^\tmv -f/\t\@mv -f/;' Makefile
    perl -i -pe 's/^\t(\$\((.*?)LINK\).*)/\t\@echo "   " LD \$\@;$1 > \/dev\/null/;' Makefile
fi


# If the --build flag was passed, start a build right away with the right
# options.

echo '#!/bin/bash' > make.sh
MAKE_VARS="ARCHFLAGS=\"$ARCHFLAGS\""
MAKE_VARS="$MAKE_VARS CPPFLAGS=\"$CPPFLAGS\""
MAKE_VARS="$MAKE_VARS LDFLAGS=\"$LDFLAGS\""
MAKE_VARS="$MAKE_VARS CXXFLAGS=\"$CXXFLAGS\""
MAKE_VARS="$MAKE_VARS DISTCHECK_CONFIGURE_FLAGS=\"$SWITCHES\""
echo "make $MAKE_VARS \"\$@\"" >> make.sh
chmod u+x make.sh

if [ $DO_BUILD = true ]; then
    sh -x make.sh "$@"
fi