#!/usr/bin/env bash

#   Licensed to the Apache Software Foundation (ASF) under one
#   or more contributor license agreements.  See the NOTICE file
#   distributed with this work for additional information
#   regarding copyright ownership.  The ASF licenses this file
#   to you under the Apache License, Version 2.0 (the
#   "License"); you may not use this file except in compliance
#   with the License.  You may obtain a copy of the License at
# 
#       http://www.apache.org/licenses/LICENSE-2.0
# 
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.

host="x86_64-pc-linux-gnu"
prefix="/usr"
exec_prefix="${prefix}"
libdir="/usr/lib/trafficserver"
localstatedir="/var"

INSTALLDIR=`eval echo "/usr/lib/trafficserver/modules"`
INCLUDEDIR=`eval echo "${prefix}/include"`
CPPFLAGS="$CPPFLAGS -I$INCLUDEDIR"
CFLAGS="$CFLAGS -std=gnu99 -g -pipe -Wall -Wextra -Wno-ignored-qualifiers -Wno-unused-parameter -Wno-format-truncation -feliminate-unused-debug-symbols -fno-strict-aliasing -mcx16"
CXXFLAGS="$CXXFLAGS -std=c++11 -g -pipe -Wall -Wextra -Wno-ignored-qualifiers -Wno-unused-parameter -Wno-format-truncation -feliminate-unused-debug-symbols -fno-strict-aliasing -Wno-invalid-offsetof -mcx16"
BUILD=
DEBUGECHO=
LDFLAGS="$LDFLAGS -Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-z,now"

if [ -z "$CC" ]; then
	CC="cc"
fi
if [ -z "$CXX" ]; then
	CXX="c++"
fi

debug() {
	if [ -n "$DEBUGECHO" ]; then
		echo $*
	fi
}

bail() {
	echo tsxs: $*
	exit 1
}

usage() {
	cat <<EOF
$0 : a tool to compile, link and install trafficserver plugins.

Compilation and Linking Options:
-o modulename.so                        ## the name of the module
-I include                              ## add -Iinclude to CFLAGS
-L library path				## add -Lpath to LDFLAGS
-l library                              ## add -llib to the LDFLAGS

Installation Options:
-o modulename.so                        ## the name of the module
-i                                      ## install the object

Query Options:
-q varname                              ## query a Traffic Server build variable

Example:
  $0 -I/foo/include -L/foo/lib -lsomelib -o tsmodule.so src1.c src2.c ...

EOF

}

query() {
  case $1 in
    CC) echo cc ;;
    CXX) echo c++ ;;
    CFLAGS) echo -std=gnu99 -g -pipe -Wall -Wextra -Wno-ignored-qualifiers -Wno-unused-parameter -Wno-format-truncation -feliminate-unused-debug-symbols -fno-strict-aliasing -mcx16 ;;
    CXXFLAGS) echo -std=c++11 -g -pipe -Wall -Wextra -Wno-ignored-qualifiers -Wno-unused-parameter -Wno-format-truncation -feliminate-unused-debug-symbols -fno-strict-aliasing -Wno-invalid-offsetof -mcx16 ;;
    PREFIX) echo /usr ;;
    SYSCONFDIR) echo /etc/trafficserver ;;
    INCLUDEDIR) echo ${prefix}/include ;;
    LIBEXECDIR) echo /usr/lib/trafficserver/modules ;;
    BINDIR) echo ${exec_prefix}/bin ;;
    LOCALSTATEDIR) echo /var ;;
    RUNTIMEDIR) echo /var/run/trafficserver ;;
    LOGDIR) echo /var/log/trafficserver ;;
    *) bail "unrecognized query label: $1" ;;
  esac
}

compile() {
	SRC=$1
	extension=`echo $SRC | sed -e 's/^.*\.//g'`
	case $extension in
		c)
			MY_CFLAGS="$CPPFLAGS $CFLAGS"
			MY_CC=$CC
			;;
		cpp|cxx|cc|CPP|CXX|CC|C)
			MY_CFLAGS="$CPPFLAGS $CXXFLAGS"
			MY_CC=$CXX
			;;
		lo|o|a)
			OBJS="${OBJS} ${SRC}"
			BUILD=1
			return
			;;
		*)
			bail "unrecognized input file: $SRC"
			;;
	esac

	obj=`echo $SRC | sed -e 's/\.[a-z]*$/\.lo/g;'`
	echo "  compiling $SRC -> $obj"
	debug "$MY_CC $MY_CFLAGS $PICFLAGS -c $SRC -o $obj"
	$MY_CC $MY_CFLAGS $PICFLAGS -c $SRC -o $obj ||
		bail "compilation failed: $MY_CC $MY_CFLAGS $PICFLAGS -c $SRC -o $obj"
	OBJS="$OBJS $obj"
	BUILD=1
}

case $host in
*-*-darwin*)
        PICFLAGS="-fPIC"
        MODULELD="$CC -bundle -flat_namespace -undefined suppress"
        MODULELDXX="$CXX -bundle -flat_namespace -undefined suppress"
        MODULEEXT=bundle
        RLDFLAG="-Wl,-rpath,"
        ;;
*-*-solaris*)
        PICFLAGS="-fpic"
        if test "x$CC" != "xgcc" ; then
                CFLAGS="$CFLAGS -mt"
        	PICFLAGS="-Kpic"
        fi
        MODULELD="$CC -G"
        MODULELDXX="$CXX -G"
        MODULEEXT=so
        RLDFLAG="-R"
        WHOLE_ARCHIVE="-Wl,-z -Wl,allextract"
        NOWHOLE_ARCHIVE="-Wl,-z -Wl,defaultextract"
        ;;
*-*-linux*)
        LDFLAGS="$LDFLAGS -Wl,-E"
        CPPFLAGS="$CPPFLAGS"
        PICFLAGS="-fpic"
        MODULELD="$CC -shared"
        MODULELDXX="$CXX -shared"
        MODULEEXT=so
        RLDFLAG="-Wl,--rpath="
        WHOLE_ARCHIVE="-Wl,--whole-archive"
        NOWHOLE_ARCHIVE="-Wl,--no-whole-archive"
        ;;
*-*-freebsd*)
        PICFLAGS="-fpic"
        MODULELD="$CC -shared"
        MODULELDXX="$CXX -shared"
        MODULEEXT=so
        RLDFLAG="-Wl,--rpath="
        ;;
*)
        PICFLAGS="-fpic"
        MODULELD="$CC -shared"
        MODULEEXT=so
        RLDFLAG="-Wl,--rpath="
        ;;
esac

files=()

LD=$MODULELD
while getopts "hivl:L:I:c:C:o:q:" OPTION
do
	case $OPTION in 
	v)
		DEBUGECHO=1
		;;
	h)
		usage
		exit 1
		;;
  q)
    query "$OPTARG"
    ;;
	I)
		CPPFLAGS="$CPPFLAGS -I$OPTARG"
		;;
	L)
		LDFLAGS="$LDFLAGS -L$OPTARG $RLDFLAG$OPTARG"
		;;
	l)
		LIBS="$LIBS -l$OPTARG"
		;;
	o)
		OBJ=$OPTARG
		;;
	i)
		INSTALL=1
		;;
	c)
		files[${#files[@]}]="$OPTARG"
		;;
	C)
		files[${#files[@]}]="$OPTARG"
		;;
	esac
done
shift $(( OPTIND - 1))

for file in "${files[@]}" "$@"; do
	compile $file
done

if [ "$BUILD" = "1" -a -n "$OBJ" ]; then
	echo "  linking -> $OBJ"
	debug "$LD $LDFLAGS -o $OBJ $OBJS $LIBS"
	$LD $LDFLAGS -o $OBJ $OBJS $LIBS ||
		bail "link failed: $LD $LDFLAGS -o $OBJ $OBJS $LIBS"
fi

if [ -n "$OBJ" ]; then
	if [ -r "$OBJ" ]; then
		if [ "$INSTALL" = "1" ]; then
			echo "  installing $OBJ -> $INSTALLDIR/$OBJ"
			cp $OBJ ${DESTDIR}${INSTALLDIR}/${OBJ}
			chmod 0755 ${DESTDIR}${INSTALLDIR}/${OBJ}
		fi
	else
		echo "No $OBJ"
	fi
fi
