New upstream version 18.11-rc1
[deb_dpdk.git] / devtools / check-includes.sh
1 #!/bin/sh -e
2 # SPDX-License-Identifier: BSD-3-Clause
3 # Copyright 2016 6WIND S.A.
4
5 # This script checks that header files in a given directory do not miss
6 # dependencies when included on their own, do not conflict and accept being
7 # compiled with the strictest possible flags.
8 #
9 # Files are looked up in the directory provided as the first argument,
10 # otherwise build/include by default.
11 #
12 # Recognized environment variables:
13 #
14 # VERBOSE=1 is the same as -v.
15 #
16 # QUIET=1 is the same as -q.
17 #
18 # SUMMARY=1 is the same as -s.
19 #
20 # CC, CPPFLAGS, CFLAGS, EXTRA_CPPFLAGS, EXTRA_CFLAGS, CXX, CXXFLAGS and
21 # EXTRA_CXXFLAGS are taken into account.
22 #
23 # PEDANTIC_CFLAGS, PEDANTIC_CXXFLAGS and PEDANTIC_CPPFLAGS provide strict
24 # C/C++ compilation flags.
25 #
26 # IGNORE contains a list of shell patterns matching files (relative to the
27 # include directory) to avoid. It is set by default to known DPDK headers
28 # which must not be included on their own.
29 #
30 # IGNORE_CXX provides additional files for C++.
31
32 while getopts hqvs arg; do
33         case $arg in
34         h)
35                 cat <<EOF
36 usage: $0 [-h] [-q] [-v] [-s] [DIR]
37
38 This script checks that header files in a given directory do not miss
39 dependencies when included on their own, do not conflict and accept being
40 compiled with the strictest possible flags.
41
42   -h    display this help and exit
43   -q    quiet mode, disable normal output
44   -v    show command lines being executed
45   -s    show summary
46
47 With no DIR, default to build/include.
48
49 Any failed header check yields a nonzero exit status.
50 EOF
51                 exit
52                 ;;
53         q)
54                 QUIET=1
55                 ;;
56         v)
57                 VERBOSE=1
58                 ;;
59         s)
60                 SUMMARY=1
61                 ;;
62         *)
63                 exit 1
64                 ;;
65         esac
66 done
67
68 shift $(($OPTIND - 1))
69
70 include_dir=${1:-build/include}
71
72 : ${PEDANTIC_CFLAGS=-std=c99 -pedantic -Wall -Wextra -Werror}
73 : ${PEDANTIC_CXXFLAGS=}
74 : ${PEDANTIC_CPPFLAGS=-D_XOPEN_SOURCE=600}
75 : ${CC:=cc}
76 : ${CXX:=c++}
77 : ${IGNORE= \
78         'rte_atomic_32.h' \
79         'rte_atomic_64.h' \
80         'rte_byteorder_32.h' \
81         'rte_byteorder_64.h' \
82         'generic/*' \
83         'exec-env/*' \
84         'rte_vhost.h' \
85         'rte_eth_vhost.h' \
86         'rte_eal_interrupts.h' \
87 }
88 : ${IGNORE_CXX= \
89         'rte_vhost.h' \
90         'rte_eth_vhost.h' \
91 }
92
93 temp_cc=$(mktemp -t dpdk.${0##*/}.XXX.c)
94 pass_cc=
95 failures_cc=0
96
97 temp_cxx=$(mktemp -t dpdk.${0##*/}.XXX.cc)
98 pass_cxx=
99 failures_cxx=0
100
101 # Process output parameters.
102
103 [ "$QUIET" = 1 ] &&
104 exec 1> /dev/null
105
106 [ "$VERBOSE" = 1 ] &&
107 output ()
108 {
109         local CCV
110         local CXXV
111
112         shift
113         CCV=$CC
114         CXXV=$CXX
115         CC="echo $CC" CXX="echo $CXX" "$@"
116         CC=$CCV
117         CXX=$CXXV
118
119         "$@"
120 } ||
121 output ()
122 {
123
124         printf '  %s\n' "$1"
125         shift
126         "$@"
127 }
128
129 trap 'rm -f "$temp_cc" "$temp_cxx"' EXIT
130
131 compile_cc ()
132 {
133         ${CC} -I"$include_dir" \
134                 ${PEDANTIC_CPPFLAGS} ${CPPFLAGS} ${EXTRA_CPPFLAGS} \
135                 ${PEDANTIC_CFLAGS} ${CFLAGS} ${EXTRA_CFLAGS} \
136                 -c -o /dev/null "${temp_cc}"
137 }
138
139 compile_cxx ()
140 {
141         ${CXX} -I"$include_dir" \
142                 ${PEDANTIC_CPPFLAGS} ${CPPFLAGS} ${EXTRA_CPPFLAGS} \
143                 ${PEDANTIC_CXXFLAGS} ${CXXFLAGS} ${EXTRA_CXXFLAGS} \
144                 -c -o /dev/null "${temp_cxx}"
145 }
146
147 ignore ()
148 {
149         file="$1"
150         shift
151         while [ $# -ne 0 ]; do
152                 case "$file" in
153                 $1)
154                         return 0
155                         ;;
156                 esac
157                 shift
158         done
159         return 1
160 }
161
162 # Check C/C++ compilation for each header file.
163
164 while read -r path
165 do
166         file=${path#$include_dir}
167         file=${file##/}
168         if ignore "$file" $IGNORE; then
169                 output "SKIP $file" :
170                 continue
171         fi
172         if printf "\
173 #include <%s>
174
175 int main(void)
176 {
177         return 0;
178 }
179 " "$file" > "$temp_cc" &&
180                 output "CC $file" compile_cc
181         then
182                 pass_cc="$pass_cc $file"
183         else
184                 failures_cc=$(($failures_cc + 1))
185         fi
186         if ignore "$file" $IGNORE_CXX; then
187                 output "SKIP CXX $file" :
188                 continue
189         fi
190         if printf "\
191 #include <%s>
192
193 int main()
194 {
195 }
196 " "$file" > "$temp_cxx" &&
197                 output "CXX $file" compile_cxx
198         then
199                 pass_cxx="$pass_cxx $file"
200         else
201                 failures_cxx=$(($failures_cxx + 1))
202         fi
203 done <<EOF
204 $(find "$include_dir" -name '*.h')
205 EOF
206
207 # Check C compilation with all includes.
208
209 : > "$temp_cc" &&
210 for file in $pass_cc; do
211         printf "\
212 #include <%s>
213 " "$file" >> $temp_cc
214 done
215 if printf "\
216 int main(void)
217 {
218         return 0;
219 }
220 " >> "$temp_cc" &&
221         output "CC (all includes that did not fail)" compile_cc
222 then
223         :
224 else
225         failures_cc=$(($failures_cc + 1))
226 fi
227
228 # Check C++ compilation with all includes.
229
230 : > "$temp_cxx" &&
231 for file in $pass_cxx; do
232         printf "\
233 #include <%s>
234 " "$file" >> $temp_cxx
235 done
236 if printf "\
237 int main()
238 {
239 }
240 " >> "$temp_cxx" &&
241         output "CXX (all includes that did not fail)" compile_cxx
242 then
243         :
244 else
245         failures_cxx=$(($failures_cxx + 1))
246 fi
247
248 # Report results.
249
250 if [ "$SUMMARY" = 1 ]; then
251         printf "\
252 Summary:
253  %u failure(s) for C using '%s'.
254  %u failure(s) for C++ using '%s'.
255 " $failures_cc "$CC" $failures_cxx "$CXX" 1>&2
256 fi
257
258 # Exit with nonzero status if there are failures.
259
260 [ $failures_cc -eq 0 ] &&
261 [ $failures_cxx -eq 0 ]