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