xref: /spdk/autobuild.sh (revision 06b537bfdb4393dea857e204b85d8df46a351d8a)
1#!/usr/bin/env bash
2
3set -e
4
5# If the configuration of tests is not provided, no tests will be carried out.
6if [[ ! -f $1 ]]; then
7	echo "ERROR: SPDK test configuration not specified"
8	exit 1
9fi
10
11rootdir=$(readlink -f $(dirname $0))
12
13source "$1"
14source "$rootdir/test/common/autotest_common.sh"
15
16out=$output_dir
17scanbuild="scan-build -o $output_dir/scan-build-tmp --exclude $rootdir/dpdk/ --status-bugs"
18config_params=$(get_config_params)
19
20trap '[[ -d $SPDK_WORKSPACE ]] && rm -rf "$SPDK_WORKSPACE"' 0
21
22SPDK_WORKSPACE=$(mktemp -dt "spdk_$(date +%s).XXXXXX")
23export SPDK_WORKSPACE
24
25umask 022
26cd $rootdir
27
28# Print some test system info out for the log
29date -u
30git describe --tags
31
32function ocf_precompile() {
33	# We compile OCF sources ourselves
34	# They don't need to be checked with scanbuild and code coverage is not applicable
35	# So we precompile OCF now for further use as standalone static library
36	./configure $(echo $config_params | sed 's/--enable-coverage//g')
37	$MAKE $MAKEFLAGS include/spdk/config.h
38	CC=gcc CCAR=ar $MAKE $MAKEFLAGS -C lib/env_ocf exportlib O=$rootdir/build/ocf.a
39	# Set config to use precompiled library
40	config_params="$config_params --with-ocf=/$rootdir/build/ocf.a"
41	# need to reconfigure to avoid clearing ocf related files on future make clean.
42	./configure $config_params
43}
44
45function build_native_dpdk() {
46	local external_dpdk_dir
47	local external_dpdk_base_dir
48
49	external_dpdk_dir="$SPDK_RUN_EXTERNAL_DPDK"
50	external_dpdk_base_dir="$(dirname $external_dpdk_dir)"
51
52	if [[ ! -d "$external_dpdk_base_dir" ]]; then
53		sudo mkdir -p "$external_dpdk_base_dir"
54		sudo chown -R $(whoami) "$external_dpdk_base_dir"/..
55	fi
56	orgdir=$PWD
57
58	rm -rf "$external_dpdk_base_dir"
59	git clone --branch $SPDK_TEST_NATIVE_DPDK --depth 1 http://dpdk.org/git/dpdk "$external_dpdk_base_dir"
60	dpdk_cflags="-fPIC -g -Werror -fcommon"
61	dpdk_ldflags=""
62
63	# the drivers we use
64	DPDK_DRIVERS=("bus" "bus/pci" "bus/vdev" "mempool/ring")
65	# all possible DPDK drivers
66	DPDK_ALL_DRIVERS=($(find "$external_dpdk_base_dir/drivers" -mindepth 1 -type d | sed -n "s#^$external_dpdk_base_dir/drivers/##p"))
67
68	if [[ "$SPDK_TEST_CRYPTO" -eq 1 ]]; then
69		git clone --branch v0.54 --depth 1 https://github.com/intel/intel-ipsec-mb.git "$external_dpdk_base_dir/intel-ipsec-mb"
70		cd "$external_dpdk_base_dir/intel-ipsec-mb"
71		$MAKE $MAKEFLAGS all SHARED=n EXTRA_CFLAGS=-fPIC
72		DPDK_DRIVERS+=("crypto")
73		DPDK_DRIVERS+=("crypto/aesni_mb")
74		DPDK_DRIVERS+=("crypto/qat")
75		DPDK_DRIVERS+=("compress/qat")
76		DPDK_DRIVERS+=("common/qat")
77		dpdk_cflags+=" -I$external_dpdk_base_dir/intel-ipsec-mb"
78		dpdk_ldflags+=" -L$external_dpdk_base_dir/intel-ipsec-mb"
79	fi
80
81	if [[ "$SPDK_TEST_REDUCE" -eq 1 ]]; then
82		git clone --branch v2.29.0 --depth 1 https://github.com/intel/isa-l.git "$external_dpdk_base_dir/isa-l"
83		cd "$external_dpdk_base_dir/isa-l"
84		./autogen.sh
85		./configure CFLAGS="-fPIC -g -O2" --enable-shared=no
86		ln -s $PWD/include $PWD/isa-l
87		$MAKE $MAKEFLAGS all
88		DPDK_DRIVERS+=("compress")
89		DPDK_DRIVERS+=("compress/isal")
90		DPDK_DRIVERS+=("compress/qat")
91		DPDK_DRIVERS+=("common/qat")
92		dpdk_cflags+=" -I$external_dpdk_base_dir/isa-l"
93		dpdk_ldflags+=" -L$external_dpdk_base_dir/isa-l/.libs"
94	fi
95
96	# Use difference between DPDK_ALL_DRIVERS and DPDK_DRIVERS as a set of DPDK drivers we don't want or
97	# don't need to build.
98	DPDK_DISABLED_DRIVERS=($(sort <(printf "%s\n" "${DPDK_DRIVERS[@]}") <(printf "%s\n" "${DPDK_ALL_DRIVERS[@]}") | uniq -u))
99
100	cd $external_dpdk_base_dir
101	if [ "$(uname -s)" = "Linux" ]; then
102		dpdk_cflags+=" -Wno-stringop-overflow"
103	fi
104
105	meson build-tmp --prefix="$external_dpdk_dir" --libdir lib \
106		-Denable_docs=false -Denable_kmods=false -Dtests=false \
107		-Dc_args="$dpdk_cflags $dpdk_ldflags" \
108		-Dmachine=native -Ddisable_drivers=$(printf "%s," "${DPDK_DISABLED_DRIVERS[@]}")
109	ninja -C "$external_dpdk_base_dir/build-tmp" $MAKEFLAGS
110	ninja -C "$external_dpdk_base_dir/build-tmp" $MAKEFLAGS install
111
112	cd "$orgdir"
113}
114
115function make_fail_cleanup() {
116	if [ -d $out/scan-build-tmp ]; then
117		scanoutput=$(ls -1 $out/scan-build-tmp/)
118		mv $out/scan-build-tmp/$scanoutput $out/scan-build
119		rm -rf $out/scan-build-tmp
120		chmod -R a+rX $out/scan-build
121	fi
122	false
123}
124
125function scanbuild_make() {
126	pass=true
127	$scanbuild $MAKE $MAKEFLAGS > $out/build_output.txt && rm -rf $out/scan-build-tmp || make_fail_cleanup
128	xtrace_disable
129
130	rm -f $out/*files.txt
131	for ent in $(find app examples lib module test -type f | grep -vF ".h"); do
132		if [[ $ent == lib/env_ocf* ]]; then continue; fi
133		if file -bi $ent | grep -q 'text/x-c'; then
134			echo $ent | sed 's/\.cp\{0,2\}$//g' >> $out/all_c_files.txt
135		fi
136	done
137	xtrace_restore
138
139	grep -E "CC|CXX" $out/build_output.txt | sed 's/\s\s\(CC\|CXX\)\s//g' | sed 's/\.o//g' > $out/built_c_files.txt
140	cat $rootdir/test/common/skipped_build_files.txt >> $out/built_c_files.txt
141
142	sort -o $out/all_c_files.txt $out/all_c_files.txt
143	sort -o $out/built_c_files.txt $out/built_c_files.txt
144	# from comm manual:
145	#   -2 suppress column 2 (lines unique to FILE2)
146	#   -3 suppress column 3 (lines that appear in both files)
147	# comm may exit 1 if no lines were printed (undocumented, unreliable)
148	comm -2 -3 $out/all_c_files.txt $out/built_c_files.txt > $out/unbuilt_c_files.txt || true
149
150	if [ $(wc -l < $out/unbuilt_c_files.txt) -ge 1 ]; then
151		echo "missing files"
152		cat $out/unbuilt_c_files.txt
153		pass=false
154	fi
155
156	$pass
157}
158
159function porcelain_check() {
160	if [ $(git status --porcelain --ignore-submodules | wc -l) -ne 0 ]; then
161		echo "Generated files missing from .gitignore:"
162		git status --porcelain --ignore-submodules
163		exit 1
164	fi
165}
166
167# Check that header file dependencies are working correctly by
168#  capturing a binary's stat data before and after touching a
169#  header file and re-making.
170function header_dependency_check() {
171	STAT1=$(stat $SPDK_BIN_DIR/spdk_tgt)
172	sleep 1
173	touch lib/nvme/nvme_internal.h
174	$MAKE $MAKEFLAGS
175	STAT2=$(stat $SPDK_BIN_DIR/spdk_tgt)
176
177	if [ "$STAT1" == "$STAT2" ]; then
178		echo "Header dependency check failed"
179		false
180	fi
181}
182
183function test_make_uninstall() {
184	# Create empty file to check if it is not deleted by target uninstall
185	touch "$SPDK_WORKSPACE/usr/lib/sample_xyz.a"
186	$MAKE $MAKEFLAGS uninstall DESTDIR="$SPDK_WORKSPACE" prefix=/usr
187	if [[ $(find "$SPDK_WORKSPACE/usr" -maxdepth 1 -mindepth 1 | wc -l) -ne 2 ]] || [[ $(find "$SPDK_WORKSPACE/usr/lib/" -maxdepth 1 -mindepth 1 | wc -l) -ne 1 ]]; then
188		ls -lR "$SPDK_WORKSPACE"
189		echo "Make uninstall failed"
190		exit 1
191	fi
192}
193
194function build_doc() {
195	$MAKE -C "$rootdir"/doc --no-print-directory $MAKEFLAGS &> "$out"/doxygen.log
196	if [ -s "$out"/doxygen.log ]; then
197		cat "$out"/doxygen.log
198		echo "Doxygen errors found!"
199		exit 1
200	fi
201	if hash pdflatex 2> /dev/null; then
202		$MAKE -C "$rootdir"/doc/output/latex --no-print-directory $MAKEFLAGS &>> "$out"/doxygen.log
203	fi
204	mkdir -p "$out"/doc
205	mv "$rootdir"/doc/output/html "$out"/doc
206	if [ -f "$rootdir"/doc/output/latex/refman.pdf ]; then
207		mv "$rootdir"/doc/output/latex/refman.pdf "$out"/doc/spdk.pdf
208	fi
209	$MAKE -C "$rootdir"/doc --no-print-directory $MAKEFLAGS clean &>> "$out"/doxygen.log
210	if [ -s "$out"/doxygen.log ]; then
211		rm "$out"/doxygen.log
212	fi
213	rm -rf "$rootdir"/doc/output
214}
215
216function autobuild_test_suite() {
217	run_test "autobuild_check_format" ./scripts/check_format.sh
218	run_test "autobuild_external_code" sudo -E --preserve-env=PATH $rootdir/test/external_code/test_make.sh $rootdir
219	if [ "$SPDK_TEST_OCF" -eq 1 ]; then
220		run_test "autobuild_ocf_precompile" ocf_precompile
221	fi
222	run_test "autobuild_check_so_deps" $rootdir/test/make/check_so_deps.sh $1
223	./configure $config_params --without-shared
224	run_test "scanbuild_make" scanbuild_make
225	run_test "autobuild_generated_files_check" porcelain_check
226	run_test "autobuild_header_dependency_check" header_dependency_check
227	run_test "autobuild_make_install" $MAKE $MAKEFLAGS install DESTDIR="$SPDK_WORKSPACE" prefix=/usr
228	run_test "autobuild_make_uninstall" test_make_uninstall
229	run_test "autobuild_build_doc" build_doc
230}
231
232if [ $SPDK_RUN_VALGRIND -eq 1 ]; then
233	run_test "valgrind" echo "using valgrind"
234fi
235
236if [ $SPDK_RUN_ASAN -eq 1 ]; then
237	run_test "asan" echo "using asan"
238fi
239
240if [ $SPDK_RUN_UBSAN -eq 1 ]; then
241	run_test "ubsan" echo "using ubsan"
242fi
243
244if [ -n "$SPDK_TEST_NATIVE_DPDK" ]; then
245	run_test "build_native_dpdk" build_native_dpdk
246fi
247
248./configure $config_params
249echo "** START ** Info for Hostname: $HOSTNAME"
250uname -a
251$MAKE cc_version
252$MAKE cxx_version
253echo "** END ** Info for Hostname: $HOSTNAME"
254
255if [ "$SPDK_TEST_AUTOBUILD" -eq 1 ]; then
256	run_test "autobuild" autobuild_test_suite $1
257else
258	if [ "$SPDK_TEST_OCF" -eq 1 ]; then
259		run_test "autobuild_ocf_precompile" ocf_precompile
260	fi
261	# if we aren't testing the unittests, build with shared objects.
262	./configure $config_params --with-shared
263	run_test "make" $MAKE $MAKEFLAGS
264fi
265