#!/bin/sh #set -x exuberant-ctags --kinds-all=* --totals=yes -e -R ERR() { printf '[ERROR] %s\n' "$1" [ "$2" ] && exit "$2" } INFO() { printf '[INFO] %s\n' "$1" [ "$2" ] && exit "$2" } : "${CC:=gcc}" SRCDIR='src' OBJDIR='.obj' BINDIR='bin' TARGET='' clena_op='N' debug_op='N' tags_op='N' deps_op='Y' while [ "$1" ] do case "$1" in --no-debug) debug_op='N';; --debug|-d) debug_op='Y';; --clean|-c) clean_op='Y';; --tags|-t) tags_op='Y';; --no-deps) deps_op='N';; --srcdir|-sd) SRCDIR="$2"; shift ;; --objdir|-od) OBJDIR="$2"; shift ;; --bindir|-bd) BINDIR="$2"; shift ;; --cc) CC="$2"; shift ;; -*|--*) ERR "Invalid flag: $1" 1;; *) TARGET="$1" ;; esac shift done if [ "$clean_op" = 'Y' ] then rm -rfv "$OBJDIR" "$BINDIR" exit 0 fi if [ "$tags_op" = 'Y' ] then INFO 'Genereting etags for all .c and .h files in project' find -name '*.c' -type f -exec etags -a {} \; find -name '*.h' -type f -exec etags -a {} \; exit 0 fi if [ -z "$TARGET" ] then ERR '*MUST* Provide the target as the last argument.' 1 fi INCS="-I include/" CFLAGS="${CFLAGS} -m64 ${INCS} -pedantic -Wall -Wextra -Wshadow -Wcast-align -Wunused -Wconversion -Wmisleading-indentation -Wduplicated-cond -Wduplicated-branches -Wlogical-op -Wdouble-promotion -Wformat=2 -Wbad-function-cast -Wmissing-declarations -Wmissing-parameter-type -Wmissing-prototypes -Wnested-externs -Werror" CC="${CC} -std=c99" LDFLAGS="${LDFLAGS} -lc -lm" if [ "$debug_op" = 'Y' ] then CFLAGS="${CFLAGS} -Og -g" LDFLAGS="${LDFLAGS} -g" else CFLAGS="${CFLAGS} -O3" fi CFLAGS="${CFLAGS} -Og -g" compile() { obj="${OBJDIR}/$1.o" src="${SRCDIR}/$1.c" [ -d "$(dirname "$obj")" ] || mkdir -pv "$(dirname "$obj")" # [ "$obj" -ot "$src" ] || { INFO "$obj Already up to date" ; return 0; } INFO "[CC] $obj $src" $CC -c $CFLAGS -o "$obj" "$src" } link() { bin="${BINDIR}/$1" objs="${OBJDIR}/$1.o" deps="$2" for dep in $deps do objs="$objs $OBJDIR/$dep.o" done [ -d "$BINDIR" ] || mkdir -pv "$BINDIR" for obj in $objs do # [ "$bin" -ot "$obj" ] && { INFO "[LD] $bin $objs"; $CC $LDFLAGS -o "$bin" $objs; return 0; # } done INFO "$bin Already up to date" return 0 } deps="$(grep '#include ".*"' "${SRCDIR}"/"$TARGET".c | \ sed 's/#include "\(.*\)"/\1/' | \ tr -d '.h')" compile "$TARGET" || exit 1 if [ "$deps_op" = 'Y' ] then for dep in $deps do compile "$dep" || exit 1 done fi link "$TARGET" "$dep" || exit 1 exec ./"$BINDIR"/"$TARGET"