7fe6717cff19f5bdc338d2ecfa33d4b48e753c1c
[nit.git] / bin / gccx
1 #!/bin/sh
2 # This file is part of NIT ( http://www.nitlanguage.org ).
3 #
4 # Copyright 2008 Jean Privat <jean@pryen.org>
5 #
6 # Licensed under the Apache License, Version 2.0 (the "License");
7 # you may not use this file except in compliance with the License.
8 # You may obtain a copy of the License at
9 #
10 #     http://www.apache.org/licenses/LICENSE-2.0
11 #
12 # Unless required by applicable law or agreed to in writing, software
13 # distributed under the License is distributed on an "AS IS" BASIS,
14 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 # See the License for the specific language governing permissions and
16 # limitations under the License.
17
18 # Separately recompile a bunch of c files then link them
19
20 OPTS="-g" # option for compiler call
21 objs="" # List of .o files
22 libs=""
23 CC="cc" # Default compiler call
24 ext="_savo _sav" # Default flavor to reuse
25 out="a.out"  # Default output binary filename
26 dir="" # Default tmp dir
27 nolibgc="false" # Disable boehm libgc?
28 CKSUM="cksum" # Tool that perfors checksum. cksum seems to be very portable
29 recompile="false"
30
31 usage()
32 {
33         e=`basename "$0"`
34         cat<<END
35 Usage: $e [options] modulename [options for module execution]
36 -R          Force full recompilation
37 -O          Compile with optimizations
38 -i          Use the intel compiler instead of gcc
39 -l          C library to link with
40 -ll         Use the clang compiler (llvm) instead of gcc
41 -I path     Add a include directory
42 -o name     Call name the executable
43 -d          Create temporary files in a specific directory
44 -nolibgc    Do not include libgc
45 -v          Verbose (show compilation steps)
46 -vv         Verbose+ (show gcc calls)
47 -h          This help
48 END
49 }
50
51 test_libgc() {
52 cat > .tmp.c <<END
53 #include <stdlib.h>
54 #include <gc/gc.h>
55 int main(void) {
56         void *r = GC_malloc(1);
57                 return r == NULL;
58         }
59 END
60 gcc .tmp.c -lgc -o .tmp.bin 2> /dev/null
61 res=$?
62 rm .tmp.c
63 if [ $res = 0 ]; then
64         ./.tmp.bin
65         res=$?
66         rm .tmp.bin
67 fi
68 return $res
69 }
70
71 cache=true
72 if ( ccache -V ) 2>/dev/null >/dev/null; then
73         cache=ccache
74 fi
75
76 stop=false
77 verbose=false
78 vverbose=false
79 while [ $stop = false ]; do
80         case $1 in 
81                 -R) recompile=true; shift;;
82                 -O) OPTS="$OPTS -O2" ext="_savo"; shift;;
83                 -i) CC="/opt/intel/cc/10.1.015/bin/icc -O2" ext="_savi"; shift;;
84                 -l) libs="$libs -l$2"; shift; shift;;
85                 -ll) CC="clang --ansi --pedantic -O3"; ext="_savll"; shift;;
86                 -I) OPTS="$OPTS -I $2"; shift; shift;;
87                 -o) out="$2"; shift; shift;;
88                 -d) dir="$2/"; shift; shift;;
89                 --nolibgc) nolibgc=true; shift;;
90                 -x) OPTS="$OPTS $2"; shift; shift;;
91                 -vv) vverbose=true; verbose=true; shift;;
92                 -v) verbose=true; shift;;
93                 -h|"") usage; exit;;
94                 *) stop=true
95         esac
96 done
97
98 if [ $nolibgc != true ] && test_libgc; then
99         OPTS="$OPTS -DWITH_LIBGC"
100         libs="$libs -lgc"
101 fi
102
103 if [ $cache = "ccache" ]; then
104         CC="ccache $CC"
105 fi
106
107 for i in "$@"; do
108         j=`basename "$i" .c`
109         transformed=`echo "$i" | sed "
110                 /\.nit_compile\/.*_sep\.c/s/\.nit_compile\/\(.*\)\._sep\.c/Module \1/
111                 /\.nit_compile\/.*_glob\.c/s/\.nit_compile\/\(.*\)\._glob\.c/Module \1/
112                 /\.nit_compile[1-9]\/.*_sep\.c/s/\.nit_compile[1-9]\/\(.*\)\._sep\.c/Module \1/
113                 /\.nit_compile[1-9]\/.*_glob\.c/s/\.nit_compile[1-9]\/\(.*\)\._glob\.c/Module \1/
114                 /\/nit_main\.c/s/.*\/nit_main\.c/Main/
115                 /\.nit_compile\/.*\._tables\.c/s/.*/Tables/
116                 /\.nit_compile[1-9]\/.*\._tables\.c/s/.*/Tables/
117                 /\/\/.*_nit\.c/s/.*\/\/\(.*\)_nit.c/Native \1/
118                 s/.*\/gc.c/Garbage Collector/
119                 s/.*\/gc_static_objects_list.c/Garbage Collector object list/
120         "`
121
122         found="false"
123         if [ $cache != true ]; then
124                 o="$dir$j.o"
125                 if [ $vverbose = true  ] ; then
126                         echo "* $CC $OPTS -c $i -o $o" >&2
127                 fi
128                 $CC $OPTS -c $i -o $o || exit 1
129         else
130         # We remove starting # to be path independent (after preprocess, there are the only # remainings)
131         cksum=`gcc -E $OPTS $i 2> /dev/null | grep -v "^#" | $CKSUM`
132         for e in $ext; do
133                 o="$dir$j.$e.o"
134                 cksumfile="$dir$j.$e.cksum"
135                 if [ -f "$cksumfile" -a -f "$o" -a "x$recompile" != "xtrue" ]; then
136                         cksumtry=`cat $cksumfile`
137                         if [ "x$cksum" = "x$cksumtry" ]; then
138                                 if [ $vverbose = true  ] ; then
139                                         echo "* $transformed up-to-date"
140                                 fi
141                                 found=true
142                                 break
143                         fi
144                 fi
145         done
146         if [ $found = false ]; then
147                 if [ $verbose = true  ] ; then
148                         if [ $vverbose = true  ] ; then
149                                 echo "* $CC $OPTS -c $i -o $o" >&2
150                         else
151                                 echo "* $transformed"
152                         fi
153                 fi
154                 if $CC $OPTS -c $i -o $o; then
155                         echo "$cksum" > "$cksumfile"
156                 else
157                         exit 1
158                 fi
159         fi
160 fi
161         objs="$objs $o"
162 done
163
164 if [ $vverbose = true  ] ; then
165         echo "* $CC $OPTS $objs -lm $libs -o $out" >&2
166 fi
167 $CC $OPTS $objs -lm $libs -o "$out"