1#!/bin/bash
2# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
3
4ERROR=0
5TMPDIR=
6
7# If one build fails, continue but return non-0 on exit.
8return_value() {
9	if [ -d "$TMPDIR" ] ; then
10		rm -rf -- $TMPDIR
11	fi
12	exit $ERROR
13}
14trap return_value EXIT
15
16case $1 in
17	-h|--help)
18		echo -e "$0 [-j <n>]"
19		echo -e "\tTest the different ways of building bpftool."
20		echo -e ""
21		echo -e "\tOptions:"
22		echo -e "\t\t-j <n>:\tPass -j flag to 'make'."
23		exit
24		;;
25esac
26
27J=$*
28
29# Assume script is located under tools/testing/selftests/bpf/. We want to start
30# build attempts from the top of kernel repository.
31SCRIPT_REL_PATH=$(realpath --relative-to=$PWD $0)
32SCRIPT_REL_DIR=$(dirname $SCRIPT_REL_PATH)
33KDIR_ROOT_DIR=$(realpath $PWD/$SCRIPT_REL_DIR/../../../../)
34cd $KDIR_ROOT_DIR
35
36check() {
37	local dir=$(realpath $1)
38
39	echo -n "binary:  "
40	# Returns non-null if file is found (and "false" is run)
41	find $dir -type f -executable -name bpftool -print -exec false {} + && \
42		ERROR=1 && printf "FAILURE: Did not find bpftool\n"
43}
44
45make_and_clean() {
46	echo -e "\$PWD:    $PWD"
47	echo -e "command: make -s $* >/dev/null"
48	make $J -s $* >/dev/null
49	if [ $? -ne 0 ] ; then
50		ERROR=1
51	fi
52	if [ $# -ge 1 ] ; then
53		check ${@: -1}
54	else
55		check .
56	fi
57	(
58		if [ $# -ge 1 ] ; then
59			cd ${@: -1}
60		fi
61		make -s clean
62	)
63	echo
64}
65
66make_with_tmpdir() {
67	local ARGS
68
69	TMPDIR=$(mktemp -d)
70	if [ $# -ge 2 ] ; then
71		ARGS=${@:1:(($# - 1))}
72	fi
73	echo -e "\$PWD:    $PWD"
74	echo -e "command: make -s $ARGS ${@: -1}=$TMPDIR/ >/dev/null"
75	make $J -s $ARGS ${@: -1}=$TMPDIR/ >/dev/null
76	if [ $? -ne 0 ] ; then
77		ERROR=1
78	fi
79	check $TMPDIR
80	rm -rf -- $TMPDIR
81	echo
82}
83
84echo "Trying to build bpftool"
85echo -e "... through kbuild\n"
86
87if [ -f ".config" ] ; then
88	make_and_clean tools/bpf
89
90	## $OUTPUT is overwritten in kbuild Makefile, and thus cannot be passed
91	## down from toplevel Makefile to bpftool's Makefile.
92
93	# make_with_tmpdir tools/bpf OUTPUT
94	echo -e "skip:    make tools/bpf OUTPUT=<dir> (not supported)\n"
95
96	make_with_tmpdir tools/bpf O
97else
98	echo -e "skip:    make tools/bpf (no .config found)\n"
99	echo -e "skip:    make tools/bpf OUTPUT=<dir> (not supported)\n"
100	echo -e "skip:    make tools/bpf O=<dir> (no .config found)\n"
101fi
102
103echo -e "... from kernel source tree\n"
104
105make_and_clean -C tools/bpf/bpftool
106
107make_with_tmpdir -C tools/bpf/bpftool OUTPUT
108
109make_with_tmpdir -C tools/bpf/bpftool O
110
111echo -e "... from tools/\n"
112cd tools/
113
114make_and_clean bpf
115
116## In tools/bpf/Makefile, function "descend" is called and passes $(O) and
117## $(OUTPUT). We would like $(OUTPUT) to have "bpf/bpftool/" appended before
118## calling bpftool's Makefile, but this is not the case as the "descend"
119## function focuses on $(O)/$(subdir). However, in the present case, updating
120## $(O) to have $(OUTPUT) recomputed from it in bpftool's Makefile does not
121## work, because $(O) is not defined from command line and $(OUTPUT) is not
122## updated in tools/scripts/Makefile.include.
123##
124## Workarounds would require to a) edit "descend" or use an alternative way to
125## call bpftool's Makefile, b) modify the conditions to update $(OUTPUT) and
126## other variables in tools/scripts/Makefile.include (at the risk of breaking
127## the build of other tools), or c) append manually the "bpf/bpftool" suffix to
128## $(OUTPUT) in bpf's Makefile, which may break if targets for other directories
129## use "descend" in the future.
130
131# make_with_tmpdir bpf OUTPUT
132echo -e "skip:    make bpf OUTPUT=<dir> (not supported)\n"
133
134make_with_tmpdir bpf O
135
136echo -e "... from bpftool's dir\n"
137cd bpf/bpftool
138
139make_and_clean
140
141make_with_tmpdir OUTPUT
142
143make_with_tmpdir O
144