blob: c58c0605863f6e8066104fd6cff33299e9e34db1 [file] [log] [blame]
Amaury Poulyf5f97842015-01-08 22:44:35 +01001#/bin/bash
2
3TMPDIR="./tmp-check-defines"
4SEARCH_DIRS="apps/ firmware/ uisimulator/"
5
6function usage()
7{
8 echo "Usage: $0 <build file> <define 1> [<define 2>...]"
9 echo ""
10 echo "This tool tries to detect which macros are defined in each build,"
11 echo "it uses the www repository build list to find the targets to build."
12 echo "By default it ignores wps and sim builds, feel free to hack the code,"
13 echo "if you want to change this. The tool can not only detect which macros"
14 echo "get define but also print the values and try to pretty print it."
15 echo ""
16 echo "If the define name is suffixed with @ or ~, the tool will also print its value"
17 echo "Furthermore, if a regex follows the @, the tool will try to list all defines"
18 echo "matching this regex to pretty print the output"
19 echo "If the define name is suffixed with ~, the tool will try to list all definitions"
20 echo "of the macro and compare the right hand side value with the actual value"
21 echo "to pretty print the value"
22 echo ""
23 echo "IMPORTANT: the tools needs to be ran from the root directory of the"
24 echo " repository"
25 echo ""
26 echo "Examples:"
27 echo "$0 ../www/buildserver/builds HAVE_USBSTACK "
28 echo "$0 ../www/buildserver/builds 'CONFIG_LCD@LCD_[[:alnum:]_]*'"
29 echo "$0 ../www/buildserver/builds CONFIG_CPU~"
30 exit 1
31}
32
33# pattern_check define file
34function pattern_check()
35{
36 cat >>"$2" <<EOF
37#ifdef $1
38#pragma message "cafebabe-$1"
39#else
40#pragma message "deadbeef-$1"
41#endif
42EOF
43}
44
45# pattern_check define file
46function pattern_value()
47{
48 cat >>"$2" <<EOF
49#ifdef $1
50#pragma message "cafebabe-$1@"MYEVAL($1)"@"
51#else
52#pragma message "deadbeef-$1"
53#endif
54EOF
55}
56
57# pattern_check define regex file
58function pattern_regex()
59{
60 # not implemented yet
61 cat >>"$3" <<EOF
62#ifdef $1
63#pragma message "cafebabe-$1@"MYEVAL($1)"@"
64#else
65#pragma message "deadbeef-$1"
66#endif
67EOF
68}
69
70# pattern_list define file
71function pattern_list()
72{
73 cat >>"$2" <<EOF
74#if !defined($1)
75#pragma message "deadbeef-$1"
76EOF
77 # find all occurences
78 grep -REh "^#define[[:space:]]+$1[[:space:]]+" $SEARCH_DIRS |
79 awk -v "DEF=$1" '{ match($0,/#define[[:space:]]+[[:alnum:]_]+[[:space:]]+(.*)/,arr);
80 print("#elif "DEF" == ("arr[1]")");
81 print("#pragma message \"cafebabe-"DEF"@"arr[1]"@\""); }' >> $2
82cat >>"$2" <<EOF
83#else
84#pragma message "cafebabe-$1@"MYEVAL($1)"@"
85#endif
86EOF
87}
88
89# check number of arguments
90if [ $# -le 1 ]; then
91 usage
92fi
93
94# try to check that the tool is ran from the root directory
95if [ ! -f "tools/configure" ]; then
96 echo "You must run this tool from the root directory of the repository"
97 exit 2
98fi
99
100# print invocation, for reference
101echo "#invocation $0 $*"
102
103# build file
104BUILD_FILE="$1"
105shift
106
107# check build file
108if [ ! -f $BUILD_FILE ]; then
109 echo "ERROR: build file doesn't exist"
110 exit 2
111fi
112
113# fill template test file
114TMPLFILE=template.c
115cat > "$TMPLFILE" <<EOF
116/* Automatically generated. http://www.rockbox.org/ */
117#include "system.h"
118#include "usb.h"
119#include "usb_ch9.h"
120/* add more includes here if needed */
121#define MYEVAL_(x) #x
122#define MYEVAL(x) MYEVAL_(x)
123EOF
124# generate test pattern for each define
125for DEFINE in "$@"
126do
127 # check if define must be printed (named suffixed by @)
128 if [[ "$DEFINE" =~ "@" ]]; then
129 REGEX=`echo "$DEFINE" | awk '{ match($0,/@(.*)$/,arr); print(arr[1]); }'`
130 DEFINE=`echo "$DEFINE" | awk '{ match($0,/([^@]*)@/,arr); print(arr[1]); }'`
131 # if regex is empty, it's simple
132 if [ "$REGEX" = "" ]; then
133 pattern_value "$DEFINE" "$TMPLFILE"
134 else
135 pattern_regex "$DEFINE" "$REGEX" "$TMPLFILE"
136 fi
137 elif [[ "$DEFINE" =~ "~" ]]; then
138 DEFINE=`echo "$DEFINE" | awk '{ match($0,/([^~]*)~/,arr); print(arr[1]); }'`
139 pattern_list "$DEFINE" "$TMPLFILE"
140 else
141 pattern_check "$DEFINE" "$TMPLFILE"
142 fi
143done
144
145# process lines in the build
146while read line
147do
148 # ignore wps and manual lines, also sim
149 if `echo "$line" | grep -E "(wps)|(manual)|(sim)" &> /dev/null`; then
150 continue
151 fi
152 # format of each line: compiler:x:name:title:file:hint:command
153 NAME=`echo "$line" | awk 'BEGIN { FS=":" } { print $3 }'`
154 CMD=`echo "$line" | awk 'BEGIN { FS=":" } { print $7 }'`
155 # remove temporary directory
156 rm -rf "$TMPDIR"
157 # create temporary directory and cd into it
158 mkdir "$TMPDIR"
159 cd "$TMPDIR"
160 # create a fake generated file
161 TESTFILE=mytest
162 cp "../$TMPLFILE" "$TESTFILE.c"
163 # the command extract is of the form
164 # ../tools/configure <options> && make <blabla>
165 # extract the part before && and replace the whole thing with:
166 # ../tools/configure <options> && make $TESTFILE.o
167 CFGCMD=`echo "$CMD" | awk '{ i=index($0, "&&"); print(substr($0,1,i-1)); }'`
168 # try to run configure
169 # it might error if the target compiler is not installed for example
170 if eval $CFGCMD &>/dev/null; then
171 # pretend dependencies were generated (because it's very long)
172 touch make.dep
173 # try to build our test file
174 OUTPUT=out.txt
175 ERROR=err.txt
176 if ! make $TESTFILE.o >$OUTPUT 2>$ERROR; then
177 # print make error
178 echo "$NAME: <make error>"
179 else
180 # print defines
181 echo "$NAME:" `cat "$ERROR" | awk 'BEGIN { list="" }
182 { if(match($0,/cafebabe-([[:alnum:]_]+)/,arr) != 0) list = list " " arr[1];
183 if(match($0,/@([^@]*)@/,arr)) list = list "=" arr[1]; }
184 END { print(list); }'`
185 fi
186 else
187 # print config error
188 echo "$NAME: <config error>"
189 fi
190 # cd back to root
191 cd ..
192done < "$BUILD_FILE"
193
194# remove everything
195rm -rf "$TMPDIR"
196rm -f "$TMPLFILE"