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