Jordan Bancino
461357b526
This makes it easier to build Cytoplasm as a component of another program (for example, Telodendria), or as a standalone system library.
288 lines
6.8 KiB
Bash
Executable file
288 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}install -D ${OUT}/lib/lib${LIB_NAME}.a \$(PREFIX)/lib/lib${LIB_NAME}.a
|
|
${TAB}install -D ${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}."
|