#!/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}."