xref: /f-stack/dpdk/devtools/check-includes.sh (revision 9bd490e8)
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
60while getopts hqvs arg; do
61	case $arg in
62	h)
63		cat <<EOF
64usage: $0 [-h] [-q] [-v] [-s] [DIR]
65
66This script checks that header files in a given directory do not miss
67dependencies when included on their own, do not conflict and accept being
68compiled 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
75With no DIR, default to build/include.
76
77Any failed header check yields a nonzero exit status.
78EOF
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
94done
95
96shift $(($OPTIND - 1))
97
98include_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}
115: ${IGNORE_CXX= \
116	'rte_vhost.h' \
117	'rte_eth_vhost.h' \
118}
119
120temp_cc=/tmp/${0##*/}.$$.c
121pass_cc=
122failures_cc=0
123
124temp_cxx=/tmp/${0##*/}.$$.cc
125pass_cxx=
126failures_cxx=0
127
128# Process output parameters.
129
130[ "$QUIET" = 1 ] &&
131exec 1> /dev/null
132
133[ "$VERBOSE" = 1 ] &&
134output ()
135{
136	local CCV
137	local CXXV
138
139	shift
140	CCV=$CC
141	CXXV=$CXX
142	CC="echo $CC" CXX="echo $CXX" "$@"
143	CC=$CCV
144	CXX=$CXXV
145
146	"$@"
147} ||
148output ()
149{
150
151	printf '  %s\n' "$1"
152	shift
153	"$@"
154}
155
156trap 'rm -f "$temp_cc" "$temp_cxx"' EXIT
157
158compile_cc ()
159{
160	${CC} -I"$include_dir" \
161		${PEDANTIC_CPPFLAGS} ${CPPFLAGS} ${EXTRA_CPPFLAGS} \
162		${PEDANTIC_CFLAGS} ${CFLAGS} ${EXTRA_CFLAGS} \
163		-c -o /dev/null "${temp_cc}"
164}
165
166compile_cxx ()
167{
168	${CXX} -I"$include_dir" \
169		${PEDANTIC_CPPFLAGS} ${CPPFLAGS} ${EXTRA_CPPFLAGS} \
170		${PEDANTIC_CXXFLAGS} ${CXXFLAGS} ${EXTRA_CXXFLAGS} \
171		-c -o /dev/null "${temp_cxx}"
172}
173
174ignore ()
175{
176	file="$1"
177	shift
178	while [ $# -ne 0 ]; do
179		case "$file" in
180		$1)
181			return 0
182			;;
183		esac
184		shift
185	done
186	return 1
187}
188
189# Check C/C++ compilation for each header file.
190
191while read -r path
192do
193	file=${path#$include_dir}
194	file=${file##/}
195	if ignore "$file" $IGNORE; then
196		output "SKIP $file" :
197		continue
198	fi
199	if printf "\
200#include <%s>
201
202int main(void)
203{
204	return 0;
205}
206" "$file" > "$temp_cc" &&
207		output "CC $file" compile_cc
208	then
209		pass_cc="$pass_cc $file"
210	else
211		failures_cc=$(($failures_cc + 1))
212	fi
213	if ignore "$file" $IGNORE_CXX; then
214		output "SKIP CXX $file" :
215		continue
216	fi
217	if printf "\
218#include <%s>
219
220int main()
221{
222}
223" "$file" > "$temp_cxx" &&
224		output "CXX $file" compile_cxx
225	then
226		pass_cxx="$pass_cxx $file"
227	else
228		failures_cxx=$(($failures_cxx + 1))
229	fi
230done <<EOF
231$(find "$include_dir" -name '*.h')
232EOF
233
234# Check C compilation with all includes.
235
236: > "$temp_cc" &&
237for file in $pass_cc; do
238	printf "\
239#include <%s>
240" "$file" >> $temp_cc
241done
242if printf "\
243int main(void)
244{
245	return 0;
246}
247" >> "$temp_cc" &&
248	output "CC (all includes that did not fail)" compile_cc
249then
250	:
251else
252	failures_cc=$(($failures_cc + 1))
253fi
254
255# Check C++ compilation with all includes.
256
257: > "$temp_cxx" &&
258for file in $pass_cxx; do
259	printf "\
260#include <%s>
261" "$file" >> $temp_cxx
262done
263if printf "\
264int main()
265{
266}
267" >> "$temp_cxx" &&
268	output "CXX (all includes that did not fail)" compile_cxx
269then
270	:
271else
272	failures_cxx=$(($failures_cxx + 1))
273fi
274
275# Report results.
276
277if [ "$SUMMARY" = 1 ]; then
278	printf "\
279Summary:
280 %u failure(s) for C using '%s'.
281 %u failure(s) for C++ using '%s'.
282" $failures_cc "$CC" $failures_cxx "$CXX" 1>&2
283fi
284
285# Exit with nonzero status if there are failures.
286
287[ $failures_cc -eq 0 ] &&
288[ $failures_cxx -eq 0 ]
289