dev/bash/smake/smake.sh

150 lines
3.9 KiB
Bash
Executable File

#!/bin/bash
REP_CC=cc
REP_CXX=c++
REP_INCLUDE='-I$(HOME)/projects/include -I/usr/include'
REP_LIBRARIES=
REP_TARGET=target
SMAKE_DIR=~/dev/bash/smake/etc/smake
HELP_FILE=$SMAKE_DIR/help.smk
ENV_FILE=$SMAKE_DIR/env.smk
BUILD_FILE=$SMAKE_DIR/build.smk
RULES_FILE=$SMAKE_DIR/rules.smk
# Debug
DEBUG=1
# Parameters processing
TEMP=`getopt -o hc:x:i:l:t: --long help,cc:,cxx:,include:,libraries:,target: -- "$@"`
eval set -- "$TEMP"
while true ; do
case "$1" in
-h|--help) echo "Usage: smake.sh [key]... [goal]..." ;
echo "Keys:"
echo -e "-h, --help\t\t\tShow this help and exit."
echo -e "-c [CC], --cc [CC]\t\tUse CC as C compiler."
echo -e "-x [CXX], --cxx [CXX]\t\tUse CXX as C++ compiler."
echo -e "-i [INC], --include [INC]\tSet INC as include path."
echo -e "-l [LIB], --libraries [LIB]\tSet LIB as libraries that must be linked with."
echo -e "-t [TGT], --target [TGT]\tSet TGT as target name."
echo
echo -e "This program works on any Linux with GNU Baurne's shell"
echo -e "Report bugs to <mecareful@gmail.com>"
exit 0 ;
;;
-c|--cc) REP_CC=$2 ; echo "CC=$REP_CC" ; shift 2 ;;
-x|--cxx) REP_CXX=$2 ; echo "CXX=$REP_CXX" ; shift 2 ;;
-i|--include) REP_INCLUDE=$2 ; echo "INCLUDE=$REP_INCLUDE"; shift 2 ;;
-l|--libraries) REP_LIBRARIES=$2 ; echo "LIBRARIES=$REP_LIBRARIES"; shift 2 ;;
-t|--target) REP_TARGET=$2 ; echo "TARGET=$REP_TARGET"; shift 2 ;;
--) shift ; break ;;
*) echo "Internal error!" ; exit 1 ;;
esac
done
# ======= Help =======
cat $HELP_FILE > Makefile
echo >> Makefile
# ======= Environment =======
sed "s~REP_CC~$REP_CC~ ; s~REP_CXX~$REP_CXX~ ; \
s~REP_LIBRARIES~$REP_LIBRARIES~ ; s~REP_TARGET~$REP_TARGET~" $ENV_FILE >> Makefile
# INCLUDE0, INCLUDE1, INCLUDE2, ...
REP_INCLUDE=`echo $REP_INCLUDE | sed "s~-I~~g"`
i=1
for d in $REP_INCLUDE; do
echo "INCLUDE$i=$d" >> Makefile
i=$((i+1))
done
echo -n "INCLUDE=" >> Makefile
i=1
for d in $REP_INCLUDE; do
if [ $i != 1 ]; then
echo -n ' ' >> Makefile
fi
echo -n '-I$(INCLUDE'$i')' >> Makefile
i=$((i+1))
done
echo >> Makefile
echo >> Makefile
# ======= Build =======
cat $BUILD_FILE >> Makefile
echo >> Makefile
# ======= Rules =======
cat $RULES_FILE >> Makefile
REP_INCLUDE=`echo $REP_INCLUDE | sed "s~-I~~g ; s~\\$(HOME)~${HOME}~"`
# --- Target deplist ---
target_dep_lst=`remove_c_comments.pl $REP_TARGET.c | grep -P '^[\t ]*#include[\t ]*"' | sed 's~[^"]*"\([^"]*\)".*~\1~' | sort -u`
files_not_found=
while [[ "$target_dep_lst" != "$old_target_dep_lst" ]]; do
old_target_dep_lst=$target_dep_lst
for f in $target_dep_lst; do
F=""
for d in . $REP_INCLUDE; do
if [ -f "$d/$f" ]; then
F="$d/$f"
C=`echo $f | sed 's~\.h$~\.c~'`
if [ -f "$d/$C" ]; then
target_dep_lst="$target_dep_lst $C"
fi
break
fi
done
if [ "$F" == "" ]; then
files_not_found="$files_not_found\n$f"
continue
fi
target_dep_lst="$target_dep_lst "`remove_c_comments.pl $F \
| grep -P '^[\t ]*#include[\t ]*"' \
| sed 's~[^"]*"\([^"]*\)".*~\1~' | sort -u`
target_dep_lst=`echo $target_dep_lst | sed 's~ ~\n~g' | sort -u`
done
done
if [ $DEBUG == 1 ]; then
echo -e "target_dep_lst:\n`echo $target_dep_lst | sed -e 's~ ~\n~g' | sed 's~\(^..\)~ \1~g'`"
fi
# --- Target's objects ---
target_obj_lst=`echo "$target_dep_lst" | grep -P '.c$' | sed -e 's~.c$~.o~'`
if [ $DEBUG == 1 ]; then
echo -e "target_obj_lst:\n`echo $target_obj_lst | sed -e 's~ ~\n~g' | sed 's~\(^..\)~ \1~g'`"
fi
# --- Target's target ;) ---
echo "target_objs = \\" >> Makefile
for to in $target_obj_lst; do
echo -e "\t$to \\" >> Makefile
done
echo '$(TARGET): $(target_objs)' >> Makefile
echo -e '\t$(CC) $(LDFLAGS) -o $@ $(target_objs)' >> Makefile
echo >> Makefile
# --- Object files deplist ---
# ======= Warning =======
files_not_found=`echo -e "$files_not_found" | sort -u`
if [ "$files_not_found" != "" ]; then
echo WARNING: Include files not found: $files_not_found
fi