New upstream version 18.02
[deb_dpdk.git] / devtools / check-includes.sh
1 #!/bin/sh -e
2 #
3 #   BSD LICENSE
4 #
5 #   Copyright 2016 6WIND S.A.
6 #
7 #   Redistribution and use in source and binary forms, with or without
8 #   modification, are permitted provided that the following conditions
9 #   are met:
10 #
11 #     * Redistributions of source code must retain the above copyright
12 #       notice, this list of conditions and the following disclaimer.
13 #     * Redistributions in binary form must reproduce the above copyright
14 #       notice, this list of conditions and the following disclaimer in
15 #       the documentation and/or other materials provided with the
16 #       distribution.
17 #     * Neither the name of 6WIND S.A. nor the names of its
18 #       contributors may be used to endorse or promote products derived
19 #       from this software without specific prior written permission.
20 #
21 #   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 #   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 #   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
24 #   A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
25 #   OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
26 #   SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
27 #   LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 #   DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 #   THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 #   (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
31 #   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32
33 # This script checks that header files in a given directory do not miss
34 # dependencies when included on their own, do not conflict and accept being
35 # compiled with the strictest possible flags.
36 #
37 # Files are looked up in the directory provided as the first argument,
38 # otherwise build/include by default.
39 #
40 # Recognized environment variables:
41 #
42 # VERBOSE=1 is the same as -v.
43 #
44 # QUIET=1 is the same as -q.
45 #
46 # SUMMARY=1 is the same as -s.
47 #
48 # CC, CPPFLAGS, CFLAGS, EXTRA_CPPFLAGS, EXTRA_CFLAGS, CXX, CXXFLAGS and
49 # EXTRA_CXXFLAGS are taken into account.
50 #
51 # PEDANTIC_CFLAGS, PEDANTIC_CXXFLAGS and PEDANTIC_CPPFLAGS provide strict
52 # C/C++ compilation flags.
53 #
54 # IGNORE contains a list of shell patterns matching files (relative to the
55 # include directory) to avoid. It is set by default to known DPDK headers
56 # which must not be included on their own.
57 #
58 # IGNORE_CXX provides additional files for C++.
59
60 while getopts hqvs arg; do
61         case $arg in
62         h)
63                 cat <<EOF
64 usage: $0 [-h] [-q] [-v] [-s] [DIR]
65
66 This script checks that header files in a given directory do not miss
67 dependencies when included on their own, do not conflict and accept being
68 compiled with the strictest possible flags.
69
70   -h    display this help and exit
71   -q    quiet mode, disable normal output
72   -v    show command lines being executed
73   -s    show summary
74
75 With no DIR, default to build/include.
76
77 Any failed header check yields a nonzero exit status.
78 EOF
79                 exit
80                 ;;
81         q)
82                 QUIET=1
83                 ;;
84         v)
85                 VERBOSE=1
86                 ;;
87         s)
88                 SUMMARY=1
89                 ;;
90         *)
91                 exit 1
92                 ;;
93         esac
94 done
95
96 shift $(($OPTIND - 1))
97
98 include_dir=${1:-build/include}
99
100 : ${PEDANTIC_CFLAGS=-std=c99 -pedantic -Wall -Wextra -Werror}
101 : ${PEDANTIC_CXXFLAGS=}
102 : ${PEDANTIC_CPPFLAGS=-D_XOPEN_SOURCE=600}
103 : ${CC:=cc}
104 : ${CXX:=c++}
105 : ${IGNORE= \
106         'rte_atomic_32.h' \
107         'rte_atomic_64.h' \
108         'rte_byteorder_32.h' \
109         'rte_byteorder_64.h' \
110         'generic/*' \
111         'exec-env/*' \
112         'rte_vhost.h' \
113         'rte_eth_vhost.h' \
114         'rte_eal_interrupts.h' \
115 }
116 : ${IGNORE_CXX= \
117         'rte_vhost.h' \
118         'rte_eth_vhost.h' \
119 }
120
121 temp_cc=/tmp/${0##*/}.$$.c
122 pass_cc=
123 failures_cc=0
124
125 temp_cxx=/tmp/${0##*/}.$$.cc
126 pass_cxx=
127 failures_cxx=0
128
129 # Process output parameters.
130
131 [ "$QUIET" = 1 ] &&
132 exec 1> /dev/null
133
134 [ "$VERBOSE" = 1 ] &&
135 output ()
136 {
137         local CCV
138         local CXXV
139
140         shift
141         CCV=$CC
142         CXXV=$CXX
143         CC="echo $CC" CXX="echo $CXX" "$@"
144         CC=$CCV
145         CXX=$CXXV
146
147         "$@"
148 } ||
149 output ()
150 {
151
152         printf '  %s\n' "$1"
153         shift
154         "$@"
155 }
156
157 trap 'rm -f "$temp_cc" "$temp_cxx"' EXIT
158
159 compile_cc ()
160 {
161         ${CC} -I"$include_dir" \
162                 ${PEDANTIC_CPPFLAGS} ${CPPFLAGS} ${EXTRA_CPPFLAGS} \
163                 ${PEDANTIC_CFLAGS} ${CFLAGS} ${EXTRA_CFLAGS} \
164                 -c -o /dev/null "${temp_cc}"
165 }
166
167 compile_cxx ()
168 {
169         ${CXX} -I"$include_dir" \
170                 ${PEDANTIC_CPPFLAGS} ${CPPFLAGS} ${EXTRA_CPPFLAGS} \
171                 ${PEDANTIC_CXXFLAGS} ${CXXFLAGS} ${EXTRA_CXXFLAGS} \
172                 -c -o /dev/null "${temp_cxx}"
173 }
174
175 ignore ()
176 {
177         file="$1"
178         shift
179         while [ $# -ne 0 ]; do
180                 case "$file" in
181                 $1)
182                         return 0
183                         ;;
184                 esac
185                 shift
186         done
187         return 1
188 }
189
190 # Check C/C++ compilation for each header file.
191
192 while read -r path
193 do
194         file=${path#$include_dir}
195         file=${file##/}
196         if ignore "$file" $IGNORE; then
197                 output "SKIP $file" :
198                 continue
199         fi
200         if printf "\
201 #include <%s>
202
203 int main(void)
204 {
205         return 0;
206 }
207 " "$file" > "$temp_cc" &&
208                 output "CC $file" compile_cc
209         then
210                 pass_cc="$pass_cc $file"
211         else
212                 failures_cc=$(($failures_cc + 1))
213         fi
214         if ignore "$file" $IGNORE_CXX; then
215                 output "SKIP CXX $file" :
216                 continue
217         fi
218         if printf "\
219 #include <%s>
220
221 int main()
222 {
223 }
224 " "$file" > "$temp_cxx" &&
225                 output "CXX $file" compile_cxx
226         then
227                 pass_cxx="$pass_cxx $file"
228         else
229                 failures_cxx=$(($failures_cxx + 1))
230         fi
231 done <<EOF
232 $(find "$include_dir" -name '*.h')
233 EOF
234
235 # Check C compilation with all includes.
236
237 : > "$temp_cc" &&
238 for file in $pass_cc; do
239         printf "\
240 #include <%s>
241 " "$file" >> $temp_cc
242 done
243 if printf "\
244 int main(void)
245 {
246         return 0;
247 }
248 " >> "$temp_cc" &&
249         output "CC (all includes that did not fail)" compile_cc
250 then
251         :
252 else
253         failures_cc=$(($failures_cc + 1))
254 fi
255
256 # Check C++ compilation with all includes.
257
258 : > "$temp_cxx" &&
259 for file in $pass_cxx; do
260         printf "\
261 #include <%s>
262 " "$file" >> $temp_cxx
263 done
264 if printf "\
265 int main()
266 {
267 }
268 " >> "$temp_cxx" &&
269         output "CXX (all includes that did not fail)" compile_cxx
270 then
271         :
272 else
273         failures_cxx=$(($failures_cxx + 1))
274 fi
275
276 # Report results.
277
278 if [ "$SUMMARY" = 1 ]; then
279         printf "\
280 Summary:
281  %u failure(s) for C using '%s'.
282  %u failure(s) for C++ using '%s'.
283 " $failures_cc "$CC" $failures_cxx "$CXX" 1>&2
284 fi
285
286 # Exit with nonzero status if there are failures.
287
288 [ $failures_cc -eq 0 ] &&
289 [ $failures_cxx -eq 0 ]