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