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