build.sh 2.6 KB

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