telodendria/configure

289 lines
6.8 KiB
Bash
Executable file

#!/usr/bin/env sh
#
# Argument Parsing
#
echo "Build Configuration"
echo "-------------------"
BUILD="build"
OUT="out"
SRC="src"
INCLUDE="include/Cytoplasm"
TOOLS="tools"
# Default compiler flags. These must be supported by all POSIX C compilers.
# "Fancy" compilers that have additional options must be detected and set below.
CFLAGS="-O1 -D_DEFAULT_SOURCE -I${INCLUDE}"
LIBS="-lm -lpthread"
# Default args for all platforms.
SCRIPT_ARGS="--prefix=/usr/local --lib-name=Cytoplasm"
# Set SSL flags depending on the platform.
case "$(uname)" in
OpenBSD)
SCRIPT_ARGS="${SCRIPT_ARGS} --with-libressl"
;;
*)
SCRIPT_ARGS="${SCRIPT_ARGS} --with-openssl"
;;
esac
# Set compiler depending on the platform.
case "$(uname)" in
Linux|NetBSD)
# These systems typically use GCC.
SCRIPT_ARGS="${SCRIPT_ARGS} --cc=gcc"
;;
OpenBSD|FreeBSD)
# These systems typically use Clang.
SCRIPT_ARGS="${SCRIPT_ARGS} --cc=clang"
;;
*)
# Use default compiler which is required to be present on
# all POSIX-compliant systems.
SCRIPT_ARGS="${SCRIPT_ARGS} --cc=c99"
;;
esac
# Append any additional args specified by user
SCRIPT_ARGS="${SCRIPT_ARGS} $@"
echo "Processing options..."
echo "Ran with arguments: $SCRIPT_ARGS"
# Process all arguments
for arg in $SCRIPT_ARGS; do
case "$arg" in
--cc=*)
CC=$(echo "$arg" | cut -d '=' -f 2-)
case "${CC}" in
gcc*|clang*)
# "Fancy" compilers that support a plethora of additional flags we
# want to enable if present.
CFLAGS="-Wall -Wextra -Werror -pedantic -std=c99 -O3 ${CFLAGS}"
LDFLAGS="-flto -fdata-sections -ffunction-sections -s -Wl,-gc-sections"
;;
esac
;;
--with-openssl)
TLS_IMPL="TLS_OPENSSL"
TLS_LIBS="-lcrypto -lssl"
;;
--with-libressl)
TLS_IMPL="TLS_LIBRESSL"
TLS_LIBS="-ltls -lcrypto -lssl"
;;
--disable-tls)
TLS_IMPL=""
TLS_LIBS=""
;;
--prefix=*)
PREFIX=$(echo "$arg" | cut -d '=' -f 2-)
;;
--lib-name=*)
LIB_NAME=$(echo "$arg" | cut -d '=' -f 2-)
;;
--enable-debug)
DEBUG="-O0 -g"
;;
--disable-debug)
DEBUG=""
;;
*)
echo "Invalid argument: $arg"
exit 1
;;
esac
done
if [ -n "$TLS_IMPL" ]; then
CFLAGS="${CFLAGS} -DTLS_IMPL=${TLS_IMPL}"
LIBS="${LIBS} ${TLS_LIBS}"
fi
CFLAGS="${CFLAGS} '-DLIB_NAME=\"${LIB_NAME}\"' ${DEBUG}"
LDFLAGS="${LIBS} ${LDFLAGS}"
#
# Makefile generation
#
collect() {
from="$1"
orig_ext="$2"
new_ext="$3"
prefix="$4"
exec="$5"
find "${from}" -name "*${orig_ext}" -type f | while IFS= read -r src; do
src=$(echo "$src" | sed -e "s|^${from}||g")
obj=$(echo "$src" | sed -e "s|${orig_ext}\$|${new_ext}|g")
obj="${prefix}${obj}"
src="${from}${src}"
"${exec}" "${src}" "${obj}"
done
}
print_src() {
printf '%s ' "$1"
}
print_obj() {
printf '%s ' "$2"
}
get_deps() {
src="$1"
${CC} -I${INCLUDE} -E "$src" \
| grep '^#' \
| awk '{print $3}' \
| cut -d '"' -f 2 \
| sort \
| uniq \
| grep -v '^[/<]' \
| grep "^${SRC}/" \
| while IFS= read -r dep; do
printf "%s " "$dep"
done
}
compile_obj() {
src="$1"
obj="$2"
echo "${obj}: $(get_deps ${src})"
echo "${TAB}@mkdir -p $(dirname ${obj})"
echo "${TAB}\$(CC) \$(CFLAGS) -fPIC -c -o \"${obj}\" \"${src}\""
}
compile_bin() {
src="$1"
out="$2"
echo "${out}: ${OUT}/lib/lib${LIB_NAME}.a ${OUT}/lib/lib${LIB_NAME}.so ${src}"
echo "${TAB}@mkdir -p ${OUT}/bin"
echo "${TAB}\$(CC) \$(CFLAGS) -o \"${out}\" \"${src}\" -L${OUT}/lib \$(LDFLAGS) -l${LIB_NAME}"
}
compile_doc() {
src="$1"
out="$2"
pref="LD_LIBRARY_PATH=${OUT}/lib "
echo "${out}: ${OUT}/bin/hdoc ${src}"
echo "${TAB}@mkdir -p ${OUT}/man/man3"
echo "${TAB}${pref}${OUT}/bin/hdoc -D \"Os=${LIB_NAME}\" -i \"${src}\" -o \"${out}\""
}
install_out() {
src="$1"
out="$2"
dir=$(dirname "$out")
echo "${TAB}mkdir -p \"$dir\""
echo "${TAB}cp \"$src\" \"$out\""
}
install_man() {
src="${OUT}/man/man3/${LIB_NAME}-$(basename $1 .h).3"
out="$2"
dir=$(dirname "$out")
echo "${TAB}mkdir -p \"$dir\""
echo "${TAB}cp \"$src\" \"$out\""
}
install_tool() {
src=${OUT}/bin/$(basename "$1" .c)
out="$2"
dir=$(dirname "$out")
echo "${TAB}mkdir -p \"$dir\""
echo "${TAB}cp \"$src\" \"$out\""
}
uninstall_out() {
src="$1"
out="$2"
echo "${TAB}rm \"$out\""
}
echo "Generating Makefile..."
OBJS=$(collect ${SRC}/ .c .o ${BUILD}/ print_obj)
TAB=$(printf '\t')
cat << EOF > Makefile
.POSIX:
# Generated by '$0' on $(date).
# This file should generally not be manually edited.
CC = ${CC}
PREFIX = ${PREFIX}
CFLAGS = ${CFLAGS}
LDFLAGS = ${LDFLAGS}
all: ${LIB_NAME} docs tools
docs: $(collect ${INCLUDE}/ .h .3 ${OUT}/man/man3/${LIB_NAME}- print_obj)
tools: $(collect ${TOOLS}/ .c '' ${OUT}/bin/ print_obj)
print-libs:
${TAB}@echo ${LIBS}
format:
${TAB}find . -name '*.c' | while IFS= read -r src; do \\
${TAB} if indent "\$\$src"; then \\
${TAB} rm \$\$(basename "\$\$src").BAK; \\
${TAB} fi \\
${TAB}done
license:
${TAB}find . -name '*.[ch]' | while IFS= read -r src; do \\
${TAB} srcHeader=\$\$(grep -n -m 1 '^ \*/' "\$\$src" | cut -d ':' -f 1); \\
${TAB} head -n\$\$srcHeader \$\$src | \\
${TAB} diff -u -p - "LICENSE.txt" | \\
${TAB} patch "\$\$src" | grep -v "^Hmm"; \\
${TAB}done
${LIB_NAME}: ${OUT}/lib/lib${LIB_NAME}.a ${OUT}/lib/lib${LIB_NAME}.so
install: ${LIB_NAME}
${TAB}mkdir -p ${OUT}/lib
${TAB}cp ${OUT}/lib/lib${LIB_NAME}.a \$(PREFIX)/lib/lib${LIB_NAME}.a
${TAB}cp ${OUT}/lib/lib${LIB_NAME}.so \$(PREFIX)/lib/lib${LIB_NAME}.so
$(collect ${INCLUDE}/ '' '' \$\(PREFIX\)/include/${LIB_NAME}/ install_out)
$(collect ${INCLUDE}/ .h .3 \$\(PREFIX\)/man/man3/${LIB_NAME}- install_man)
$(collect ${TOOLS}/ '.c' '' \$\(PREFIX\)/bin/ install_tool)
uninstall:
${TAB}rm -r \$(PREFIX)/lib/lib${LIB_NAME}.*
${TAB}rm -r \$(PREFIX)/include/${LIB_NAME}
${TAB}rm -r \$(PREFIX)/man/man3/${LIB_NAME}-*
$(collect ${TOOLS}/ '.c' '' \$\(PREFIX\)/bin/ uninstall_out)
clean:
${TAB}rm -r "${BUILD}" "${OUT}"
${OUT}/lib/lib${LIB_NAME}.a: ${OBJS}
${TAB}@mkdir -p ${OUT}/lib
${TAB}\$(AR) rcs ${OUT}/lib/lib${LIB_NAME}.a ${OBJS}
${OUT}/lib/lib${LIB_NAME}.so: ${OBJS}
${TAB}@mkdir -p ${OUT}/lib
${TAB}\$(CC) -shared -o ${OUT}/lib/lib${LIB_NAME}.so ${OBJS} ${LDFLAGS}
$(collect ${SRC}/ .c .o ${BUILD}/ compile_obj)
$(collect ${TOOLS}/ .c '' ${OUT}/bin/ compile_bin)
$(collect ${INCLUDE}/ .h .3 ${OUT}/man/man3/${LIB_NAME}- compile_doc)
EOF
echo "Done. Run 'make' to build ${LIB_NAME}."