build.sh 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. #!/bin/sh
  2. #set -x
  3. exuberant-ctags --kinds-all=* --totals=yes -e -R
  4. ERR() {
  5. printf '[ERROR] %s\n' "$1"
  6. [ "$2" ] && exit "$2"
  7. }
  8. INFO() {
  9. printf '[INFO] %s\n' "$1"
  10. [ "$2" ] && exit "$2"
  11. }
  12. : "${CC:=gcc}"
  13. SRCDIR='src'
  14. OBJDIR='.obj'
  15. BINDIR='bin'
  16. TARGET=''
  17. clena_op='N'
  18. debug_op='N'
  19. tags_op='N'
  20. deps_op='Y'
  21. while [ "$1" ]
  22. do
  23. case "$1" in
  24. --no-debug) debug_op='N';;
  25. --debug|-d) debug_op='Y';;
  26. --clean|-c) clean_op='Y';;
  27. --tags|-t) tags_op='Y';;
  28. --no-deps) deps_op='N';;
  29. --srcdir|-sd) SRCDIR="$2"; shift ;;
  30. --objdir|-od) OBJDIR="$2"; shift ;;
  31. --bindir|-bd) BINDIR="$2"; shift ;;
  32. --cc) CC="$2"; shift ;;
  33. -*|--*) ERR "Invalid flag: $1" 1;;
  34. *) TARGET="$1" ;;
  35. esac
  36. shift
  37. done
  38. if [ "$clean_op" = 'Y' ]
  39. then
  40. rm -rfv "$OBJDIR" "$BINDIR"
  41. exit 0
  42. fi
  43. if [ "$tags_op" = 'Y' ]
  44. then
  45. INFO 'Genereting etags for all .c and .h files in project'
  46. find -name '*.c' -type f -exec etags -a {} \;
  47. find -name '*.h' -type f -exec etags -a {} \;
  48. exit 0
  49. fi
  50. if [ -z "$TARGET" ]
  51. then
  52. ERR '*MUST* Provide the target as the last argument.' 1
  53. fi
  54. INCS="-I include/"
  55. CFLAGS="${CFLAGS} -m64 ${INCS} -pedantic -Wall -Wextra -Wshadow
  56. -Wcast-align -Wunused -Wconversion -Wmisleading-indentation
  57. -Wduplicated-cond -Wduplicated-branches -Wlogical-op
  58. -Wdouble-promotion -Wformat=2 -Wbad-function-cast
  59. -Wmissing-declarations -Wmissing-parameter-type
  60. -Wmissing-prototypes -Wnested-externs -Werror"
  61. CC="${CC} -std=c99"
  62. LDFLAGS="${LDFLAGS} -lc -lm"
  63. if [ "$debug_op" = 'Y' ]
  64. then
  65. CFLAGS="${CFLAGS} -Og -g"
  66. LDFLAGS="${LDFLAGS} -g"
  67. else
  68. CFLAGS="${CFLAGS} -O3"
  69. fi
  70. CFLAGS="${CFLAGS} -Og -g"
  71. compile() {
  72. obj="${OBJDIR}/$1.o"
  73. src="${SRCDIR}/$1.c"
  74. [ -d "$(dirname "$obj")" ] || mkdir -pv "$(dirname "$obj")"
  75. # [ "$obj" -ot "$src" ] || { INFO "$obj Already up to date" ; return 0; }
  76. INFO "[CC] $obj $src"
  77. $CC -c $CFLAGS -o "$obj" "$src"
  78. }
  79. link() {
  80. bin="${BINDIR}/$1"
  81. objs="${OBJDIR}/$1.o"
  82. deps="$2"
  83. for dep in $deps
  84. do
  85. objs="$objs $OBJDIR/$dep.o"
  86. done
  87. [ -d "$BINDIR" ] || mkdir -pv "$BINDIR"
  88. for obj in $objs
  89. do
  90. # [ "$bin" -ot "$obj" ] && {
  91. INFO "[LD] $bin $objs";
  92. $CC $LDFLAGS -o "$bin" $objs;
  93. return 0;
  94. # }
  95. done
  96. INFO "$bin Already up to date"
  97. return 0
  98. }
  99. deps="$(grep '#include ".*"' "${SRCDIR}"/"$TARGET".c | \
  100. sed 's/#include "\(.*\)"/\1/' | \
  101. tr -d '.h')"
  102. compile "$TARGET" || exit 1
  103. if [ "$deps_op" = 'Y' ]
  104. then
  105. for dep in $deps
  106. do
  107. compile "$dep" || exit 1
  108. done
  109. fi
  110. link "$TARGET" "$dep" || exit 1
  111. exec ./"$BINDIR"/"$TARGET"