2011-07-07 16:04:10 +04:00
|
|
|
#!/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
|
2011-07-08 11:29:44 +04:00
|
|
|
HELP_FILE=$SMAKE_DIR/help.smk
|
2011-07-07 16:04:10 +04:00
|
|
|
ENV_FILE=$SMAKE_DIR/env.smk
|
|
|
|
BUILD_FILE=$SMAKE_DIR/build.smk
|
|
|
|
RULES_FILE=$SMAKE_DIR/rules.smk
|
|
|
|
|
|
|
|
# Debug
|
2011-07-07 19:07:57 +04:00
|
|
|
DEBUG=1
|
2011-07-07 16:04:10 +04:00
|
|
|
|
|
|
|
# Parameters processing
|
2011-07-08 11:10:48 +04:00
|
|
|
TEMP=`getopt -o hc:x:i:l:t: --long help,cc:,cxx:,include:,libraries:,target: -- "$@"`
|
2011-07-07 16:04:10 +04:00
|
|
|
eval set -- "$TEMP"
|
|
|
|
|
|
|
|
while true ; do
|
|
|
|
case "$1" in
|
2011-07-08 11:10:48 +04:00
|
|
|
-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."
|
2011-07-08 11:11:31 +04:00
|
|
|
echo -e "-t [TGT], --target [TGT]\tSet TGT as target name."
|
2011-07-08 11:10:48 +04:00
|
|
|
echo
|
|
|
|
echo -e "This program works on any Linux with GNU Baurne's shell"
|
|
|
|
echo -e "Report bugs to <mecareful@gmail.com>"
|
|
|
|
exit 0 ;
|
|
|
|
;;
|
2011-07-07 16:04:10 +04:00
|
|
|
-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
|
|
|
|
|
2011-07-08 11:29:44 +04:00
|
|
|
# ======= Help =======
|
|
|
|
cat $HELP_FILE > Makefile
|
|
|
|
echo >> Makefile
|
|
|
|
|
2011-07-08 18:12:20 +04:00
|
|
|
# ======= Test for target =======
|
|
|
|
[ ! -f $REP_TARGET.c ] && echo "$REP_TARGET.c doesn't exist" && exit -1
|
|
|
|
|
2011-07-07 16:26:23 +04:00
|
|
|
# ======= Environment =======
|
2011-07-07 16:04:10 +04:00
|
|
|
sed "s~REP_CC~$REP_CC~ ; s~REP_CXX~$REP_CXX~ ; \
|
2011-07-08 11:29:44 +04:00
|
|
|
s~REP_LIBRARIES~$REP_LIBRARIES~ ; s~REP_TARGET~$REP_TARGET~" $ENV_FILE >> Makefile
|
2011-07-07 16:04:10 +04:00
|
|
|
|
|
|
|
# INCLUDE0, INCLUDE1, INCLUDE2, ...
|
2011-07-07 16:13:03 +04:00
|
|
|
REP_INCLUDE=`echo $REP_INCLUDE | sed "s~-I~~g"`
|
2011-07-07 16:04:10 +04:00
|
|
|
|
|
|
|
i=1
|
|
|
|
for d in $REP_INCLUDE; do
|
|
|
|
echo "INCLUDE$i=$d" >> Makefile
|
|
|
|
i=$((i+1))
|
|
|
|
done
|
|
|
|
|
2011-07-07 16:13:03 +04:00
|
|
|
echo -n "INCLUDE=" >> Makefile
|
|
|
|
|
|
|
|
i=1
|
2011-07-07 16:04:10 +04:00
|
|
|
for d in $REP_INCLUDE; do
|
2011-07-07 16:13:03 +04:00
|
|
|
if [ $i != 1 ]; then
|
|
|
|
echo -n ' ' >> Makefile
|
|
|
|
fi
|
|
|
|
echo -n '-I$(INCLUDE'$i')' >> Makefile
|
|
|
|
i=$((i+1))
|
2011-07-07 16:04:10 +04:00
|
|
|
done
|
|
|
|
echo >> Makefile
|
|
|
|
|
|
|
|
echo >> Makefile
|
|
|
|
|
2011-07-07 16:26:23 +04:00
|
|
|
# ======= Build =======
|
2011-07-07 16:04:10 +04:00
|
|
|
cat $BUILD_FILE >> Makefile
|
|
|
|
|
|
|
|
echo >> Makefile
|
|
|
|
|
2011-07-07 16:26:23 +04:00
|
|
|
# ======= Rules =======
|
2011-07-07 16:04:10 +04:00
|
|
|
cat $RULES_FILE >> Makefile
|
|
|
|
|
2011-07-08 17:31:01 +04:00
|
|
|
REP_INCLUDE=`echo $REP_INCLUDE | sed "s~-I~~g ; s~\\$(HOME)~${HOME}~g"`
|
|
|
|
flist[0]=$REP_TARGET.c
|
2011-07-08 18:12:20 +04:00
|
|
|
fpath[0]=$REP_TARGET.c
|
2011-07-08 17:31:01 +04:00
|
|
|
nfiles=1
|
|
|
|
nparsed=0
|
|
|
|
fdeplist[0]=`remove_c_comments.pl $REP_TARGET.c | grep -P '^[\t ]*#include[\t ]*"' | sed 's~[^"]*"\([^"]*\)".*~\1~' | sort -u`
|
|
|
|
files_not_found=
|
|
|
|
while [ $nfiles != $nparsed ]; do
|
|
|
|
for f in ${fdeplist[$nparsed]}; do
|
2011-07-08 18:12:20 +04:00
|
|
|
extension=`basename $f | sed 's~.*\.~~g'`
|
|
|
|
f=`echo $f | sed "s~.$extension$~~"`
|
|
|
|
for ext in "$extension" c cxx cpp; do
|
|
|
|
already_in_list=false
|
|
|
|
for i in `seq 0 $((nfiles))`; do
|
|
|
|
if [ "${flist[$i]}" == "$f.$ext" ]; then
|
|
|
|
already_in_list=true
|
|
|
|
break;
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
[ $already_in_list == true ] && continue
|
|
|
|
|
|
|
|
F=
|
|
|
|
for d in . $REP_INCLUDE; do
|
|
|
|
if [ -f "$d/$f.$ext" ]; then
|
|
|
|
F="$d/$f.$ext"
|
2011-07-08 18:14:25 +04:00
|
|
|
elif [ -f "$d/`basename $f.$ext`" ]; then
|
|
|
|
F="$d/`basename $f.$ext`"
|
2011-07-08 18:12:20 +04:00
|
|
|
fi
|
|
|
|
if [ "$F" != "" ]; then
|
|
|
|
flist[$nfiles]=$f.$ext
|
|
|
|
fpath[$nfiles]=$F
|
|
|
|
fdeplist[$nfiles]=`remove_c_comments.pl $F | grep -P '^[\t ]*#include[\t ]*"' | sed 's~[^"]*"\([^"]*\)".*~\1~' | sort -u`
|
|
|
|
let nfiles++
|
|
|
|
break
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
[[ "$F" == "" && "$ext" == "$extension" ]] && files_not_found=`echo "$files_not_found\n$f.$ext" | sort -u`
|
|
|
|
[[ "$F" != "" && "$ext" != "$extension" ]] && break
|
2011-07-08 17:31:01 +04:00
|
|
|
done
|
|
|
|
done
|
|
|
|
let nparsed++
|
|
|
|
done
|
|
|
|
|
|
|
|
for i in `seq 0 $((nfiles-1))`; do
|
|
|
|
echo ${flist[$i]}:${fdeplist[$i]}
|
|
|
|
done
|
|
|
|
|
|
|
|
# ======= 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
|
|
|
|
|
|
|
|
#####################################################################################
|
|
|
|
#####################################################################################
|
|
|
|
#####################################################################################
|
|
|
|
#####################################################################################
|
|
|
|
#####################################################################################
|
|
|
|
exit 0
|
|
|
|
cat $RULES_FILE >> Makefile
|
|
|
|
|
2011-07-07 16:13:03 +04:00
|
|
|
REP_INCLUDE=`echo $REP_INCLUDE | sed "s~-I~~g ; s~\\$(HOME)~${HOME}~"`
|
|
|
|
|
2011-07-07 16:26:23 +04:00
|
|
|
# --- Target deplist ---
|
2011-07-07 18:31:32 +04:00
|
|
|
target_dep_lst=`remove_c_comments.pl $REP_TARGET.c | grep -P '^[\t ]*#include[\t ]*"' | sed 's~[^"]*"\([^"]*\)".*~\1~' | sort -u`
|
|
|
|
files_not_found=
|
2011-07-07 16:26:23 +04:00
|
|
|
|
|
|
|
while [[ "$target_dep_lst" != "$old_target_dep_lst" ]]; do
|
|
|
|
old_target_dep_lst=$target_dep_lst
|
|
|
|
for f in $target_dep_lst; do
|
2011-07-07 16:04:10 +04:00
|
|
|
F=""
|
|
|
|
for d in . $REP_INCLUDE; do
|
|
|
|
if [ -f "$d/$f" ]; then
|
|
|
|
F="$d/$f"
|
2011-07-07 17:53:19 +04:00
|
|
|
C=`echo $f | sed 's~\.h$~\.c~'`
|
|
|
|
if [ -f "$d/$C" ]; then
|
|
|
|
target_dep_lst="$target_dep_lst $C"
|
|
|
|
fi
|
2011-07-07 16:04:10 +04:00
|
|
|
break
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
if [ "$F" == "" ]; then
|
2011-07-07 18:31:32 +04:00
|
|
|
files_not_found="$files_not_found\n$f"
|
|
|
|
continue
|
2011-07-07 16:04:10 +04:00
|
|
|
fi
|
2011-07-07 18:36:57 +04:00
|
|
|
target_dep_lst="$target_dep_lst "`remove_c_comments.pl $F \
|
|
|
|
| grep -P '^[\t ]*#include[\t ]*"' \
|
|
|
|
| sed 's~[^"]*"\([^"]*\)".*~\1~' | sort -u`
|
2011-07-07 16:26:23 +04:00
|
|
|
target_dep_lst=`echo $target_dep_lst | sed 's~ ~\n~g' | sort -u`
|
2011-07-07 16:04:10 +04:00
|
|
|
done
|
|
|
|
done
|
|
|
|
|
2011-07-07 18:31:32 +04:00
|
|
|
if [ $DEBUG == 1 ]; then
|
|
|
|
echo -e "target_dep_lst:\n`echo $target_dep_lst | sed -e 's~ ~\n~g' | sed 's~\(^..\)~ \1~g'`"
|
|
|
|
fi
|
|
|
|
|
2011-07-07 19:07:57 +04:00
|
|
|
# --- 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 ;) ---
|
2011-07-08 10:56:55 +04:00
|
|
|
echo "target_objs = \\" >> Makefile
|
|
|
|
for to in $target_obj_lst; do
|
|
|
|
echo -e "\t$to \\" >> Makefile
|
|
|
|
done
|
2011-07-08 16:28:51 +04:00
|
|
|
echo >> Makefile
|
2011-07-08 10:56:55 +04:00
|
|
|
|
|
|
|
echo '$(TARGET): $(target_objs)' >> Makefile
|
|
|
|
echo -e '\t$(CC) $(LDFLAGS) -o $@ $(target_objs)' >> Makefile
|
|
|
|
|
|
|
|
echo >> Makefile
|
2011-07-07 19:07:57 +04:00
|
|
|
|
2011-07-07 18:36:57 +04:00
|
|
|
# --- Object files deplist ---
|
2011-07-08 15:25:29 +04:00
|
|
|
for cf in `echo "$target_dep_lst" | grep -P '.c$'`; do
|
|
|
|
CF=""
|
|
|
|
for d in . $REP_INCLUDE; do
|
|
|
|
if [ -f "$d/$cf" ]; then
|
|
|
|
CF="$d/$cf"
|
|
|
|
break
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
if [ "$CF" == "" ]; then
|
2011-07-08 16:28:51 +04:00
|
|
|
files_not_found="$files_not_found\n$cf"
|
2011-07-08 15:25:29 +04:00
|
|
|
continue
|
|
|
|
fi
|
|
|
|
|
|
|
|
to=`basename "$cf" | sed 's~.c$~.o~'`
|
|
|
|
|
|
|
|
target_dep_lst="$CF "`remove_c_comments.pl $CF | grep -P '^[\t ]*#include[\t ]*"' | sed 's~[^"]*"\([^"]*\)".*~\1~' | sort -u`
|
2011-07-08 16:28:51 +04:00
|
|
|
old_target_dep_lst=
|
2011-07-08 15:25:29 +04:00
|
|
|
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"
|
|
|
|
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
|
2011-07-07 18:36:57 +04:00
|
|
|
|
2011-07-08 16:28:51 +04:00
|
|
|
target_dep_lst=
|
|
|
|
for f in $old_target_dep_lst; do
|
|
|
|
F=""
|
|
|
|
for d in . $REP_INCLUDE; do
|
|
|
|
if [ -f "$d/$f" ]; then
|
|
|
|
F="$d/$f"
|
|
|
|
break
|
|
|
|
fi
|
|
|
|
done
|
|
|
|
if [ "$F" == "" ]; then
|
|
|
|
files_not_found="$files_not_found\n$f"
|
|
|
|
continue
|
|
|
|
fi
|
|
|
|
target_dep_lst=`echo "$F $target_dep_lst" | sed 's~ ~\n~g' | sort -u`
|
|
|
|
done
|
|
|
|
|
|
|
|
echo "$to: \\" >> Makefile
|
2011-07-08 15:25:29 +04:00
|
|
|
for td in $target_dep_lst; do
|
2011-07-08 16:28:51 +04:00
|
|
|
td=`echo "$td" | sed "s~^\./~~ ; s~^\./~~ ; s~${HOME}~$\(HOME\)~"`
|
2011-07-08 15:25:29 +04:00
|
|
|
echo -e "\t$td \\" >> Makefile
|
|
|
|
done
|
|
|
|
echo >> Makefile
|
|
|
|
done
|
2011-07-07 18:36:57 +04:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ======= Warning =======
|
2011-07-07 18:31:32 +04:00
|
|
|
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
|
2011-07-07 16:04:10 +04:00
|
|
|
|
2011-07-07 19:07:57 +04:00
|
|
|
|