0e005667c97fbc7ce258eaf40a71ad9292503721
[libjh.git] / compile.sh
1 #!/bin/bash
2 # YES, THIS NEEDS BASH, NOT /bin/sh (e.g. for <<<).
3
4 # -f                  for files with weird names
5 # -u                  for coding mistakes (or against, to be precise)
6 # -e and -o pipefail  so that we don't have to spam the code with error handling
7 set -f -u -e -o pipefail
8
9 # flags for the build - adjust for your needs
10 # delete all the generated stuff afterwards (with `rm -r gen`)
11 CC='gcc'
12 CFLAGS='-g -O0 -Wall -Werror -fPIC -std=c99'
13
14 # create build environment if it doesn't exist yet
15 mkdir -p gen # contains all generated files
16 mkdir -p gen/realc # source files, with our preprocessing applied
17 mkdir -p gen/realc_preprocessed # source files, preprocessed by the C compiler
18 mkdir -p gen/chash # hashes of the preprocessed C files used to generate files in gen/obj
19 mkdir -p gen/obj # object files
20
21 echo "welcome. your friendly compiler will be \"$CC\" today." >&2
22 echo "going ahead with CFLAGS=\"$CFLAGS\"..." >&2
23
24 # generate header
25 for source_file in $(ls|grep '\.c$'); do
26   echo "extracting header data from $source_file..." >&2
27   source_name="$(sed 's|\.c$||' <<< "$source_file")"
28   echo "/* ----========   $source_name   ========---- */"
29   
30   cat "$source_file" |
31   sed 's|^PUBLIC_FN \(.*\){|KEEPLINE \1;|g' |
32   sed 's|^PUBLIC_CONST |KEEPLINE #define |g' |
33   sed 's|^HEADER |KEEPLINE |g' |
34   grep '^KEEPLINE' |
35   sed 's|^KEEPLINE ||g'
36   
37   echo ''
38   echo ''
39 done > gen/libjh.h
40
41 # preprocess all source files
42 for source_file in $(ls|grep '\.c$'); do
43   echo "handling source file $source_file..." >&2
44   source_name="$(sed 's|\.c$||' <<< "$source_file")"
45   
46   # do our own preprocessing
47   echo '#include "../libjh.h"' > "gen/realc/$source_name.c"
48   
49   cat "$source_file" |
50   grep -v '^PUBLIC_CONST ' |
51   sed 's|^PUBLIC_FN ||g' |
52   grep -v '^HEADER ' |
53   cat >> "gen/realc/$source_name.c"
54   if [ $? -ne 0 ]; then exit 1; fi
55   
56   # do the normal C preprocessing
57   echo 'preprocessing...' >&2
58   $CC -E "gen/realc/$source_name.c" > "gen/realc_preprocessed/$source_name.i"
59   
60   # compile if there have been changes since the last time
61   echo -n 'checking sha checksum... ' >&2
62   file_hash="$(shasum "gen/realc_preprocessed/$source_name.i" | cut -d' ' -f1)"
63   # drop errors: that file might well be missing
64   set +e
65   last_file_hash="$(cat "gen/chash/$source_name" 2>/dev/null)"
66   set -e
67   if [ "$file_hash" = "$last_file_hash" ]; then
68     echo 'unchanged, will not compile again' >&2
69   else
70     echo 'changed – recompiling.' >&2
71     $CC $CFLAGS -c -o "gen/obj/$source_name.o" "gen/realc_preprocessed/$source_name.i"
72     echo "$file_hash" > "gen/chash/$source_name"
73   fi
74 done
75
76 # ... and link!
77 cd gen/obj
78 $CC -shared -Wl,-soname,libjh.so -o ../libjh.so $(ls)
79 cd ../..