#!/bin/sh
set -eu
cd -- "$(dirname -- "$0")"
self=./$(basename -- "$0")
. ../build_util.sh
# Get configuration from the environment
CC=${CC:-c99}
std=c99
CFLAGS=${CFLAGS:-}
CPPFLAGS=${CPPFLAGS:-}
append_cppflag -D_DEFAULT_SOURCE
LDFLAGS=${LDFLAGS:-}
LDLIBS=
MAKE=${MAKE:-make}
JOBS=${JOBS:-1}
LTO=${LTO:-false}
PGO=${PGO:-false}
STATIC=${STATIC:-false}
NATIVE=${NATIVE:-false}
CONFIG=${CONFIG:-release}
DESTDIR=${DESTDIR+${DESTDIR%/}}
PREFIX=$DESTDIR${PREFIX:-/usr/local}
PREFIX=${PREFIX%/}
# Target specific definitions
std=c11
BIN=mus_player
gitver=$(git_version ..)
append_cppflag \
-DPROG_NAME="$(dquote "$BIN" 2)" \
-DPROG_VERSION="$(dquote "$gitver" 2)"
LDLIBS='-pthread -lm -lao -ldl'
USE_FLAC=${USE_FLAC:-true}
USE_OGG_VORBIS=${USE_OGG_VORBIS:-false}
USE_OGG_OPUS=${USE_OGG_OPUS:-false}
# Argument parsing
if "$PGO"
then
[ $# -eq 0 ] && die "PGO is useless without a command to run"
else
if [ $# -eq 1 ]
then
case "$(tolower "$1")" in
clean)
cclean
rm -f -- *.profraw default.profdata *.gcda
;;
install)
[ ! -f "$BIN" ] && "$self"
PREFIX=$(cd - >/dev/null; resolve_create_dir "$PREFIX")
install -m 755 "$PREFIX"/bin/ "$BIN"
install -m 644 "$PREFIX"/share/doc/mus/README_mus_player.txt README
install -m 644 "$PREFIX"/share/doc/mus/ IPC.txt
;;
uninstall)
PREFIX=$(cd - >/dev/null; resolve_existing_dir "$PREFIX")
uninstall -- "$PREFIX/bin/$BIN" \
"$PREFIX"/share/doc/mus/README_mus_player.txt \
"$PREFIX"/share/doc/mus/IPC.txt
;;
help)
usage 0
;;
*)
die "$1: unknown action"
;;
esac
exit
elif [ $# -gt 1 ]
then
usage 1
fi
fi
# Detect compiler vendor
case "$(tolower "$CC")" in
*gcc*)
cctype=gcc
;;
*clang*)
cctype=clang
;;
*)
cctype=c99
;;
esac
# Apply PGO with workload specified by "$@"
if "$PGO"
then
xtest_cflag -fprofile-generate
[ $# -eq 0 ] && die "PGO is useless without a command to run"
case "$cctype" in
gcc)
PGO=false CFLAGS="$CFLAGS -fprofile-generate" \
LDFLAGS="$LDFLAGS -fprofile-generate" "$self"
(
cd - >/dev/null
"$@"
)
cclean
append_ldflag -fprofile-use
append_cflag -fprofile-use
;;
clang)
PGO=false CFLAGS="$CFLAGS -fprofile-generate=$(dquote "$PWD")" \
LDFLAGS="$LDFLAGS -fprofile-generate=$(dquote "$PWD")" "$self"
(
cd - >/dev/null
"$@"
)
cclean
llvm-profdata merge -output=default.profdata default_*.profraw
append_ldflag -fprofile-use="$PWD"
append_cflag -fprofile-use="$PWD"
;;
*)
die "Unknown PGO supporting compiler"
;;
esac
fi
# Process CONFIG
case "$(tolower "$CONFIG")" in
debug)
CFLAGS=-g
test_append_cflag -Og || append_cflag -O0
test_append_cflag -fsanitize=address &&
append_ldflag -fsanitize=address
test_append_cflag -fsanitize=undefined &&
append_ldflag -fsanitize=undefined
test_append_ldflag -fsanitize=leak
;;
profile)
CFLAGS=-g
test_append_cflag -Og || append_cflag -O0
append_cppflag -DNDEBUG
;;
release)
test_append_cflag -Ofast || append_cflag -O3
append_cppflag -DNDEBUG
append_ldflag -s
test_append_ldflag -Wl,-O1
;;
*)
die "$CONFIG: unknown config"
;;
esac
# Diverse CFLAG/LDFLAG additions
"$NATIVE" && xtest_append_cflag -march=native
"$STATIC" && xtest_append_ldflag -static
xtest_append_cflag -std="$std"
test_append_cflag -pedantic -Wall -Wextra
test_append_ldflag -Wl,-z,now,-z,defs
[ "${LD:-}" ] && test_append_ldflag -fuse-ld="${LD#ld.}"
# Apply LTO
if "$LTO"
then
xtest_cflag -flto
case "$cctype" in
gcc)
append_ldflag -flto="$JOBS" "$CFLAGS"
append_cflag -flto -fno-fat-lto-objects
;;
clang)
append_cflag -flto=thin
append_ldflag "$CFLAGS"
;;
*)
die "Unknown LTO supporting compiler"
;;
esac
fi
# Prepare the object list
SRC=$(printf '%s\n' *.c | grep -v mus_udsend.c)
gperf=$(listfiles . -name '*.gperf' | sed 's#^\./##; s#\.gperf$#.c#')
if [ "$gperf" ]
then
! command -v gperf >/dev/null && die "gperf: command not found"
SRC=$(printf '%s\n%s\n' "$SRC" "$gperf")
fi
lex=$(listfiles . -name '*.lex' | sed 's#^\./##; s#\.lex$#.c#')
if [ "$lex" ]
then
SRC=$(printf '%s\n%s\n' "$SRC" "$lex")
fi
# Remove duplicates inserted by gperf/lex detection
SRC=$(echo "$SRC" | awk '!seen[$0]++')
# Conditional features processing
SRC=$(echo "$SRC" | grep -Evx '(flac|vorbis|opus)\.c')
if "$USE_FLAC"
then
append_cppflag -DUSE_FLAC
LDLIBS="$LDLIBS -lFLAC"
SRC=$(printf '%s\n%s\n' "$SRC" flac.c)
fi
if "$USE_OGG_VORBIS"
then
append_cppflag -DUSE_OGG_VORBIS
LDLIBS="$LDLIBS -lvorbisfile"
SRC=$(printf '%s\n%s\n' "$SRC" vorbis.c)
fi
if "$USE_OGG_OPUS"
then
append_cppflag -DUSE_OGG_OPUS -I/usr/include/opus
LDLIBS="$LDLIBS -lopusfile"
SRC=$(printf '%s\n%s\n' "$SRC" opus.c)
fi
OBJ=$(echo "$SRC" | sed 's#\.c$#.o#' | paste -sd' ')
cat <<'EOF' | "$MAKE" $([ $JOBS -ne 1 ] && echo -j$JOBS) -f - \
CC="$CC" BIN="$BIN" OBJ="$OBJ" CFLAGS="$CFLAGS" \
CPPFLAGS="$CPPFLAGS" LDFLAGS="$LDFLAGS" LDLIBS="$LDLIBS"
.POSIX:
.SUFFIXES:
.SUFFIXES: .c .o .gperf .lex
.gperf.c:
gperf -- $< >$@
.lex.c:
$(LEX) $(LFLAGS) -t -- $< >$@
.c.o:
$(CC) $(CFLAGS) $(CPPFLAGS) -c $<
$(BIN): $(OBJ)
$(CC) $(LDFLAGS) $(OBJ) -o $@ $(LDLIBS)
EOF