diff options
author | Amaury Pouly <amaury.pouly@gmail.com> | 2015-01-08 22:44:35 +0100 |
---|---|---|
committer | Amaury Pouly <amaury.pouly@gmail.com> | 2015-02-16 11:31:05 +0100 |
commit | f5f9784ab754891675c83a4ca70a21df5d656c74 (patch) | |
tree | a54e1ca9df0b4365e6b32d3a8a0e129d39e080e4 /utils/analysis | |
parent | 74fc3efb60ed7844c8f7dbd0bd66f666e611dcfb (diff) | |
download | rockbox-f5f9784ab754891675c83a4ca70a21df5d656c74.tar.gz rockbox-f5f9784ab754891675c83a4ca70a21df5d656c74.zip |
Introduce a new analysis tool to detect which macros are defined in each build.
See the usage() for more information.
Change-Id: I712ef4d6bd21eccefa18cec144e35b8161ca5b3a
Diffstat (limited to 'utils/analysis')
-rwxr-xr-x | utils/analysis/check_defines.sh | 196 |
1 files changed, 196 insertions, 0 deletions
diff --git a/utils/analysis/check_defines.sh b/utils/analysis/check_defines.sh new file mode 100755 index 0000000000..c58c060586 --- /dev/null +++ b/utils/analysis/check_defines.sh | |||
@@ -0,0 +1,196 @@ | |||
1 | #/bin/bash | ||
2 | |||
3 | TMPDIR="./tmp-check-defines" | ||
4 | SEARCH_DIRS="apps/ firmware/ uisimulator/" | ||
5 | |||
6 | function 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 | ||
34 | function pattern_check() | ||
35 | { | ||
36 | cat >>"$2" <<EOF | ||
37 | #ifdef $1 | ||
38 | #pragma message "cafebabe-$1" | ||
39 | #else | ||
40 | #pragma message "deadbeef-$1" | ||
41 | #endif | ||
42 | EOF | ||
43 | } | ||
44 | |||
45 | # pattern_check define file | ||
46 | function 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 | ||
54 | EOF | ||
55 | } | ||
56 | |||
57 | # pattern_check define regex file | ||
58 | function 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 | ||
67 | EOF | ||
68 | } | ||
69 | |||
70 | # pattern_list define file | ||
71 | function pattern_list() | ||
72 | { | ||
73 | cat >>"$2" <<EOF | ||
74 | #if !defined($1) | ||
75 | #pragma message "deadbeef-$1" | ||
76 | EOF | ||
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 | ||
82 | cat >>"$2" <<EOF | ||
83 | #else | ||
84 | #pragma message "cafebabe-$1@"MYEVAL($1)"@" | ||
85 | #endif | ||
86 | EOF | ||
87 | } | ||
88 | |||
89 | # check number of arguments | ||
90 | if [ $# -le 1 ]; then | ||
91 | usage | ||
92 | fi | ||
93 | |||
94 | # try to check that the tool is ran from the root directory | ||
95 | if [ ! -f "tools/configure" ]; then | ||
96 | echo "You must run this tool from the root directory of the repository" | ||
97 | exit 2 | ||
98 | fi | ||
99 | |||
100 | # print invocation, for reference | ||
101 | echo "#invocation $0 $*" | ||
102 | |||
103 | # build file | ||
104 | BUILD_FILE="$1" | ||
105 | shift | ||
106 | |||
107 | # check build file | ||
108 | if [ ! -f $BUILD_FILE ]; then | ||
109 | echo "ERROR: build file doesn't exist" | ||
110 | exit 2 | ||
111 | fi | ||
112 | |||
113 | # fill template test file | ||
114 | TMPLFILE=template.c | ||
115 | cat > "$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) | ||
123 | EOF | ||
124 | # generate test pattern for each define | ||
125 | for DEFINE in "$@" | ||
126 | do | ||
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 | ||
143 | done | ||
144 | |||
145 | # process lines in the build | ||
146 | while read line | ||
147 | do | ||
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 .. | ||
192 | done < "$BUILD_FILE" | ||
193 | |||
194 | # remove everything | ||
195 | rm -rf "$TMPDIR" | ||
196 | rm -f "$TMPLFILE" \ No newline at end of file | ||