xref: /spdk/configure (revision 6f338d4bf3a8a91b7abe377a605a321ea2b05bf7)
1#!/usr/bin/env bash
2
3set -e
4
5trap 'echo -e "\n\nConfiguration failed\n\n" >&2' ERR
6
7rootdir=$(readlink -f $(dirname $0))
8source "$rootdir/scripts/common.sh"
9
10function usage() {
11	echo "'configure' configures SPDK to compile on supported platforms."
12	echo ""
13	echo "Usage: ./configure [OPTION]..."
14	echo ""
15	echo "Defaults for the options are specified in brackets."
16	echo ""
17	echo "General:"
18	echo " -h, --help                Display this help and exit"
19	echo ""
20	echo " --prefix=path             Configure installation prefix (default: /usr/local)"
21	echo " --target-arch=arch        Target build architecture. Must be a valid GNU arch. Default: native"
22	echo ""
23	echo " --cross-prefix=prefix     Prefix for cross compilation (default: none)"
24	echo "                           example: aarch64-linux-gnu"
25	echo " --libdir=path             Configure installation path for the libraries (default: \$prefix/lib)"
26	echo ""
27	echo " --enable-debug            Configure for debug builds"
28	echo " --enable-werror           Treat compiler warnings as errors"
29	echo " --enable-asan             Enable address sanitizer"
30	echo " --enable-ubsan            Enable undefined behavior sanitizer"
31	echo " --enable-coverage         Enable code coverage tracking"
32	echo " --enable-lto              Enable link-time optimization"
33	echo " --enable-pgo-capture      Enable generation of profile guided optimization data"
34	echo " --enable-pgo-use          Use previously captured profile guided optimization data"
35	echo " --enable-cet              Enable Intel Control-flow Enforcement Technology (CET)"
36	echo " --disable-tests           Disable building of functional tests"
37	echo " --disable-unit-tests      Disable building of unit tests"
38	echo " --disable-examples        Disable building of examples"
39	echo " --disable-apps            Disable building of apps"
40	echo ""
41	echo "Specifying Dependencies:"
42	echo "--with-DEPENDENCY[=path]   Use the given dependency. Optionally, provide the"
43	echo "                           path."
44	echo "--without-DEPENDENCY       Do not link to the given dependency. This may"
45	echo "                           disable features and components."
46	echo ""
47	echo "Valid dependencies are listed below."
48	echo " --with-dpdk[=DIR]         Build against a custom dpdk version. By default, the dpdk"
49	echo " --without-dpdk            submodule in spdk tree will be used."
50	echo "                           example: /usr/share/dpdk/x86_64-default-linuxapp-gcc"
51	echo " --with-env=DIR            Use an alternate environment implementation instead of DPDK."
52	echo "                           Implies --without-dpdk."
53	echo " --with-idxd               Build the IDXD library and accel framework plug-in module."
54	echo " --without-idxd            Disabled while experimental. Only built for x86 when enabled."
55	echo " --with-crypto             Build vbdev crypto module."
56	echo " --without-crypto          No path required."
57	echo " --with-fio[=DIR]          Build fio_plugin."
58	echo " --without-fio             default: /usr/src/fio"
59	echo " --with-xnvme              Build xNVMe bdev module."
60	echo " --without-xnvme           No path required."
61	echo " --with-vhost              Build vhost target. Enabled by default."
62	echo " --without-vhost           No path required."
63	echo " --with-virtio             Build vhost initiator and virtio-pci bdev modules."
64	echo " --without-virtio          No path required."
65	echo " --with-vfio-user[=DIR]    Build custom vfio-user transport for NVMf target and NVMe initiator."
66	echo " --without-vfio-user       example: /usr/src/libvfio-user"
67	echo " --with-pmdk[=DIR]         Build persistent memory bdev.
68					 example: /usr/share/pmdk"
69	echo " --without-pmdk		 No path required."
70	echo " --with-reduce             Build vbdev compression module."
71	echo " --without-reduce          No path required."
72	echo " --with-rbd                Build Ceph RBD bdev module."
73	echo " --without-rbd             No path required."
74	echo " --with-rdma[=DIR]         Build RDMA transport for NVMf target and initiator."
75	echo " --without-rdma            Accepts optional RDMA provider name. Can be \"verbs\" or \"mlx5_dv\"."
76	echo "                           If no provider specified, \"verbs\" provider is used by default."
77	echo " --with-fc[=DIR]           Build FC transport for NVMf target."
78	echo " --without-fc              If an argument is provided, it is considered a directory containing"
79	echo "                           libufc.a and fc_lld.h. Otherwise the regular system paths will"
80	echo "                           be searched."
81	echo " --with-shared             Build spdk shared libraries."
82	echo " --without-shared          No path required."
83	echo " --with-iscsi-initiator    Build with iscsi bdev module."
84	echo " --without-iscsi-initiator No path required."
85	echo " --with-vtune=DIR          Required to profile I/O under Intel VTune Amplifier XE."
86	echo " --without-vtune           example: /opt/intel/vtune_amplifier_xe_version"
87	echo " --with-ocf[=DIR]          Build OCF library and bdev module."
88	echo " --without-ocf             If argument is directory, interpret it as root of OCF repo"
89	echo "                           If argument is file, interpret it as compiled OCF lib"
90	echo "                           If no argument is specified, OCF git submodule is used by default"
91	echo "                           example: /usr/src/ocf/"
92	echo " --with-isal               Build with ISA-L. Enabled by default on x86 and aarch64 architectures."
93	echo " --without-isal            No path required."
94	echo " --with-uring[=DIR]        Build I/O uring bdev or socket module."
95	echo " --without-uring           If an argument is provided, it is considered a directory containing"
96	echo "                           liburing.a and io_uring.h. Otherwise the regular system paths will"
97	echo "                           be searched."
98	echo " --with-openssl[=DIR]      Build OPENSSL with custom path. Otherwise the regular system paths will"
99	echo "                           be searched."
100	echo " --with-fuse               Build FUSE components for mounting a blobfs filesystem."
101	echo " --without-fuse            No path required."
102	echo " --with-nvme-cuse          Build NVMe driver with support for CUSE-based character devices."
103	echo " --without-nvme-cuse       No path required."
104	echo " --with-raid5              Build with bdev_raid module RAID5 support."
105	echo " --without-raid5           No path required."
106	echo " --with-wpdk=DIR           Build using WPDK to provide support for Windows (experimental)."
107	echo " --without-wpdk            The argument must be a directory containing lib and include."
108	echo " --with-usdt               Build with userspace DTrace probes enabled."
109	echo " --without-usdt            No path required."
110	echo " --with-fuzzer             Build with LLVM fuzzing enabled."
111	echo "                           Path to clang_rt.fuzzer_no_main library required."
112	echo "                           Requires setting CC and CXX to clang."
113	echo "                           (Typically /usr/lib/llvm-VER/lib/clang/VER/lib/linux/libclang_rt.fuzzer_no_main-ARCH.a)"
114	echo " --with-sma                Generate Storage Management Agent's protobuf interface"
115	echo " --without-sma             No path required."
116	echo ""
117	echo "Environment variables:"
118	echo ""
119	echo "CC                         C compiler"
120	echo "CFLAGS                     C compiler flags"
121	echo "CXX                        C++ compiler"
122	echo "CXXFLAGS                   C++ compiler flags"
123	echo "LD                         Linker"
124	echo "LDFLAGS                    Linker flags"
125	echo "DESTDIR                    Destination for 'make install'"
126	echo ""
127}
128
129# Load default values
130# Convert config to sourceable configuration file
131sed -r 's/CONFIG_([[:alnum:]_]+)=(.*)/CONFIG[\1]=\2/g' $rootdir/CONFIG > $rootdir/CONFIG.sh
132declare -A CONFIG
133source $rootdir/CONFIG.sh
134rm $rootdir/CONFIG.sh
135
136# Try to expand literal ~ that might have been passed as an option via --long-opt=~/dir.
137set -- "${@//\~/~}"
138
139for i in "$@"; do
140	case "$i" in
141		--cross-prefix=*)
142			CONFIG[CROSS_PREFIX]="${i#*=}"
143			;;
144		--enable-lto)
145			CONFIG[LTO]=y
146			;;
147		--disable-lto)
148			CONFIG[LTO]=n
149			;;
150	esac
151done
152
153# Detect the compiler toolchain
154$rootdir/scripts/detect_cc.sh --cc="$CC" --cxx="$CXX" --lto="${CONFIG[LTO]}" --ld="$LD" --cross-prefix="${CONFIG[CROSS_PREFIX]}" > $rootdir/mk/cc.mk
155
156CC=$(grep "DEFAULT_CC=" "$rootdir/mk/cc.mk" | sed s/DEFAULT_CC=//)
157CC_TYPE=$(grep "CC_TYPE=" "$rootdir/mk/cc.mk" | cut -d "=" -f 2)
158
159arch=$($CC -dumpmachine)
160sys_name=$(uname -s)
161
162if [[ $arch == *mingw* ]] || [[ $arch == *windows* ]]; then
163	sys_name=Windows
164fi
165
166# Sanitize default configuration. All parameters set by user explicit should fail
167# Force no ISA-L if non-x86 or non-aarch64 architecture
168if [[ "${CONFIG[ISAL]}" = "y" ]]; then
169	if [[ $arch != x86_64* ]] && [[ $arch != aarch64* ]]; then
170		CONFIG[ISAL]=n
171		echo "Notice: ISA-L not supported for ${arch}. Turning off default feature."
172	fi
173fi
174
175if [[ $sys_name != "Linux" ]]; then
176	# Vhost, rte_vhost library and virtio are only supported on Linux.
177	CONFIG[VHOST]="n"
178	CONFIG[VIRTIO]="n"
179	echo "Notice: Vhost, rte_vhost library and virtio are only supported on Linux. Turning off default feature."
180fi
181
182#check nasm only on x86
183if [[ $arch == x86_64* ]]; then
184	ver=$(nasm -v 2> /dev/null | awk '{print $3}' | awk -Fr '{print $1}')
185	if lt "$ver" 2.14; then
186		# ISA-L, compression & crypto require NASM version 2.14 or newer.
187		CONFIG[ISAL]=n
188		CONFIG[CRYPTO]=n
189		CONFIG[IPSEC_MB]=n
190		CONFIG[REDUCE]=n
191		HAVE_NASM=n
192		echo "Notice: ISA-L, compression & crypto require NASM version 2.14 or newer. Turning off default ISA-L and crypto features."
193	else
194		HAVE_NASM=y
195	fi
196fi
197
198function check_dir() {
199	arg="$1"
200	dir="${arg#*=}"
201	if [ ! -d "$dir" ]; then
202		echo "$arg: directory not found"
203		exit 1
204	fi
205}
206
207# On x86_64 'clang -dumpmachine' produces x86_64-pc-linux-gnu
208# whereas the dpdk might be built with gcc and its libs lie in
209# x86_64-linux-gnu. Let's find the right libdir for dpdkd libs.
210function find_dpdk_arch_libdir() {
211	local dpdk_dir=$1
212
213	# Checking first what we have with $arch, then clang
214	# variant of arch.
215	arches=("$arch" "$(echo $arch | sed 's/-pc//g')")
216	for a in "${arches[@]}"; do
217		local libdir="$dpdk_dir/lib/$a"
218		if [[ -d $libdir ]]; then
219			echo $libdir
220			return
221		fi
222	done
223
224	# Fallback to the libdir without arch component
225	echo "$dpdk_dir/lib"
226}
227
228function check_IPSec_mb() {
229	local mode=$1
230	local dpdk_libdir=$2
231	local dpdk_incdir=$3
232	local have_ipsec_mb=n
233
234	if [[ $mode = "pkg-config" ]]; then
235		local dpdk_libs
236
237		# Request libdpdk pkg-config settings to figure out if the IPSec_MB is used
238		# as a dependency.
239		# Due to some reason pkg-config shows -lIPSec_MB only with --static option
240		dpdk_libs=$(PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$dpdk_libdir/pkgconfig" pkg-config --libs --static libdpdk)
241		if echo "$dpdk_libs" | grep "\-lIPSec_MB" > /dev/null 2>&1; then
242			have_ipsec_mb=y
243		fi
244	elif [[ $mode = "build-config" ]]; then
245		# Use dpdk build config header to check if the IPSec_MB was used.
246		if grep -F "define RTE_CRYPTO_IPSEC_MB 1" "$dpdk_incdir/rte_build_config.h" > /dev/null 2>&1; then
247			have_ipsec_mb=y
248		fi
249	else
250		echo "ERROR: Invalid IPSec_MB checking mode $mode."
251		echo "ERROR: Only \"pkg-config\" and \"build-config\" available."
252		exit 1
253	fi
254	if [[ $have_ipsec_mb = "n" ]]; then
255		CONFIG[IPSEC_MB]=n
256		return
257	fi
258
259	# Since we don't know the library path where the IPSec_MB is located
260	# let's find it out with the ldd utility. This can be a standard location
261	# or a custom build.
262	local librte_crypto_ipsec_mb="$dpdk_libdir/librte_crypto_ipsec_mb.so"
263	if [[ -f "$librte_crypto_ipsec_mb" ]]; then
264		local ipsec_mb_libdir
265
266		ipsec_mb_libdir=$(ldd "$librte_crypto_ipsec_mb" | grep "libIPSec_MB.so" \
267			| sed -e 's/\s*libIPSec_MB.so.*=>\s//' -e 's/\/libIPSec_MB.so.*$//')
268		if [[ -d $ipsec_mb_libdir ]]; then
269			CONFIG[IPSEC_MB]=y
270			CONFIG[IPSEC_MB_DIR]="$ipsec_mb_libdir"
271		elif [[ $ipsec_mb_libdir = "not found" ]]; then
272			# ldconfig cache is broken, old build with refs to non-existing libs, etc.
273			echo "ERROR: Invalid IPSec_MB installation. Library is not found and/or ldconfig cache is broken!"
274			exit 1
275		else
276			# Failed to check for IPSec_MB lib path. Let's just assume it is lives
277			# in one of the standard locations (/usr/lib, etc.).
278			CONFIG[IPSEC_MB]=y
279		fi
280	else
281		# pkg-config says there is IPSec_mb and dpdk lib does not have it. Let's just
282		# assume it is installed in the system in one of the standard locations.
283		CONFIG[IPSEC_MB]=y
284	fi
285}
286
287for i in "$@"; do
288	case "$i" in
289		-h | --help)
290			usage
291			exit 0
292			;;
293		--cross-prefix=*) ;&
294		--enable-lto) ;&
295		--disable-lto)
296			# Options handled before detecting CC.
297			;;
298		--prefix=*)
299			CONFIG[PREFIX]="${i#*=}"
300			;;
301		--target-arch=*)
302			CONFIG[ARCH]="${i#*=}"
303			;;
304		--libdir=*)
305			CONFIG[LIBDIR]="${i#*=}"
306			;;
307		--enable-debug)
308			CONFIG[DEBUG]=y
309			;;
310		--disable-debug)
311			CONFIG[DEBUG]=n
312			;;
313		--enable-asan)
314			CONFIG[ASAN]=y
315			;;
316		--disable-asan)
317			CONFIG[ASAN]=n
318			;;
319		--enable-ubsan)
320			CONFIG[UBSAN]=y
321			;;
322		--disable-ubsan)
323			CONFIG[UBSAN]=n
324			;;
325		--enable-tsan)
326			CONFIG[TSAN]=y
327			;;
328		--disable-tsan)
329			CONFIG[TSAN]=n
330			;;
331		--enable-coverage)
332			CONFIG[COVERAGE]=y
333			;;
334		--disable-coverage)
335			CONFIG[COVERAGE]=n
336			;;
337		--enable-pgo-capture)
338			CONFIG[PGO_CAPTURE]=y
339			;;
340		--disable-pgo-capture)
341			CONFIG[PGO_CAPTURE]=n
342			;;
343		--enable-pgo-use)
344			CONFIG[PGO_USE]=y
345			;;
346		--disable-pgo-use)
347			CONFIG[PGO_USE]=n
348			;;
349		--enable-tests)
350			CONFIG[TESTS]=y
351			;;
352		--disable-tests)
353			CONFIG[TESTS]=n
354			;;
355		--enable-unit-tests)
356			CONFIG[UNIT_TESTS]=y
357			;;
358		--disable-unit-tests)
359			CONFIG[UNIT_TESTS]=n
360			;;
361		--enable-examples)
362			CONFIG[EXAMPLES]=y
363			;;
364		--disable-examples)
365			CONFIG[EXAMPLES]=n
366			;;
367		--enable-apps)
368			CONFIG[APPS]=y
369			;;
370		--disable-apps)
371			CONFIG[APPS]=N
372			;;
373		--enable-werror)
374			CONFIG[WERROR]=y
375			;;
376		--disable-werror)
377			CONFIG[WERROR]=n
378			;;
379		--enable-cet)
380			CONFIG[CET]=y
381			;;
382		--disable-cet)
383			CONFIG[CET]=n
384			;;
385		--with-dpdk)
386			# Can we use pkg-config?
387			if command -v "pkg-config" > /dev/null 2>&1 && pkg-config --exists libdpdk; then
388				dpdk_libdir=$(pkg-config --variable=libdir libdpdk)
389				dpdk_libdir=$(readlink -f $dpdk_libdir)
390				dpdk_incdir=$(pkg-config --variable=includedir libdpdk)
391				echo "Using DPDK lib dir $dpdk_libdir"
392				CONFIG[DPDK_LIB_DIR]=$dpdk_libdir
393				CONFIG[DPDK_INC_DIR]=$dpdk_incdir
394				CONFIG[DPDK_PKG_CONFIG]=y
395				if pkg-config --print-requires libdpdk | grep "libbsd" > /dev/null 2>&1; then
396					CONFIG[HAVE_LIBBSD]=y
397				fi
398				CFLAGS="${CFLAGS:+$CFLAGS }$(pkg-config --cflags libdpdk)"
399				check_IPSec_mb "pkg-config" "$dpdk_libdir" "$dpdk_incdir"
400			else
401				echo "libdpdk.pc not found, aborting"
402				exit 1
403			fi
404			;;
405		--with-dpdk=*)
406			check_dir "$i"
407			dpdk_dir=$(readlink -f ${i#*=})
408			dpdk_libdir=$(find_dpdk_arch_libdir $dpdk_dir)
409			dpdk_incdir="$dpdk_dir/include"
410
411			# Can we use pkg-config?
412			if command -v "pkg-config" > /dev/null 2>&1 && PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$dpdk_libdir/pkgconfig" pkg-config --exists libdpdk; then
413				echo "Using $dpdk_libdir/pkgconfig for additional libs..."
414				sysroot_dir=$(PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$dpdk_libdir/pkgconfig" pkg-config --variable=pc_sysrootdir libdpdk)
415				dpdk_libdir=$(PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$dpdk_libdir/pkgconfig" pkg-config --variable=libdir libdpdk)
416				dpdk_libdir=$(readlink -f "${sysroot_dir}$dpdk_libdir")
417				if ! echo $dpdk_libdir | grep $dpdk_dir > /dev/null 2>&1; then
418					echo "ERROR: pkg-config reported DPDK libdir $dpdk_libdir is out of the directory specified with --with-dpdk="
419					echo "ERROR: do you have another DPDK installed in the system?"
420					exit 1
421				fi
422				dpdk_reqs=$(PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$dpdk_libdir/pkgconfig" pkg-config --print-requires libdpdk)
423				if echo $dpdk_reqs | grep "libbsd" > /dev/null 2>&1; then
424					CONFIG[HAVE_LIBBSD]=y
425				fi
426				CFLAGS="${CFLAGS:+$CFLAGS }$(PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$dpdk_libdir/pkgconfig" pkg-config --cflags libdpdk)"
427				dpdk_incdir="${sysroot_dir}$(PKG_CONFIG_PATH="$PKG_CONFIG_PATH:$dpdk_libdir/pkgconfig" pkg-config --variable=includedir libdpdk)"
428				check_IPSec_mb "pkg-config" "$dpdk_libdir" "$dpdk_incdir"
429			else
430				echo "Using $dpdk_incdir/rte_build_config.h for additional libs..."
431
432				if grep -F "define RTE_USE_LIBBSD 1" $dpdk_incdir/rte_build_config.h > /dev/null 2>&1; then
433					CONFIG[HAVE_LIBBSD]=y
434				fi
435				check_IPSec_mb "build-config" "$dpdk_libdir" "$dpdk_incdir"
436			fi
437			echo "DPDK libraries: $dpdk_libdir"
438			echo "DPDK includes: $dpdk_incdir"
439			CONFIG[DPDK_DIR]=$dpdk_dir
440			CONFIG[DPDK_LIB_DIR]="$dpdk_libdir"
441			CONFIG[DPDK_INC_DIR]="$dpdk_incdir"
442			CONFIG[DPDK_PKG_CONFIG]=n
443			;;
444		--without-dpdk)
445			CONFIG[DPDK_DIR]=
446			;;
447		--with-wpdk=*)
448			check_dir "$i"
449			CONFIG[WPDK_DIR]=$(readlink -f ${i#*=})
450			;;
451		--without-wpdk)
452			CONFIG[WPDK_DIR]=
453			;;
454		--with-env=*)
455			CONFIG[ENV]="${i#*=}"
456			;;
457		--with-rbd)
458			CONFIG[RBD]=y
459			;;
460		--without-rbd)
461			CONFIG[RBD]=n
462			;;
463		--with-rdma=*)
464			CONFIG[RDMA]=y
465			CONFIG[RDMA_PROV]=${i#*=}
466			;;
467		--with-rdma)
468			CONFIG[RDMA]=y
469			CONFIG[RDMA_PROV]="verbs"
470			;;
471		--without-rdma)
472			CONFIG[RDMA]=n
473			;;
474		--with-fc=*)
475			CONFIG[FC]=y
476			CONFIG[FC_PATH]=$(readlink -f ${i#*=})
477			;;
478		--with-fc)
479			CONFIG[FC]=y
480			CONFIG[FC_PATH]=
481			;;
482		--without-fc)
483			CONFIG[FC]=n
484			CONFIG[FC_PATH]=
485			;;
486		--with-shared)
487			CONFIG[SHARED]=y
488			;;
489		--without-shared)
490			CONFIG[SHARED]=n
491			;;
492		--with-iscsi-initiator)
493			CONFIG[ISCSI_INITIATOR]=y
494			;;
495		--without-iscsi-initiator)
496			CONFIG[ISCSI_INITIATOR]=n
497			;;
498		--with-crypto)
499			CONFIG[CRYPTO]=y
500			;;
501		--without-crypto)
502			CONFIG[CRYPTO]=n
503			;;
504		--with-vhost)
505			CONFIG[VHOST]=y
506			;;
507		--without-vhost)
508			CONFIG[VHOST]=n
509			;;
510		--with-virtio)
511			CONFIG[VIRTIO]=y
512			;;
513		--without-virtio)
514			CONFIG[VIRTIO]=n
515			;;
516		--with-vfio-user)
517			CONFIG[VFIO_USER]=y
518			CONFIG[VFIO_USER_DIR]=""
519			;;
520		--with-vfio-user=*)
521			CONFIG[VFIO_USER]=y
522			check_dir "$i"
523			CONFIG[VFIO_USER_DIR]=$(readlink -f ${i#*=})
524			;;
525		--without-vfio-user)
526			CONFIG[VFIO_USER]=n
527			;;
528		--with-pmdk)
529			CONFIG[PMDK]=y
530			CONFIG[PMDK_DIR]=""
531			;;
532		--with-pmdk=*)
533			CONFIG[PMDK]=y
534			check_dir "$i"
535			CONFIG[PMDK_DIR]=$(readlink -f ${i#*=})
536			;;
537		--without-pmdk)
538			CONFIG[PMDK]=n
539			;;
540		--with-reduce)
541			CONFIG[REDUCE]=y
542			;;
543		--without-reduce)
544			CONFIG[REDUCE]=n
545			;;
546		--with-xnvme)
547			CONFIG[XNVME]=y
548			;;
549		--without-xnvme)
550			CONFIG[XNVME]=n
551			;;
552		--with-fio) ;&
553		--with-fio=*)
554			if [[ ${i#*=} != "$i" ]]; then
555				CONFIG[FIO_SOURCE_DIR]=${i#*=}
556			fi
557			check_dir "--with-fio=${CONFIG[FIO_SOURCE_DIR]}"
558			CONFIG[FIO_SOURCE_DIR]=$(readlink -f "${CONFIG[FIO_SOURCE_DIR]}")
559			CONFIG[FIO_PLUGIN]=y
560			;;
561		--without-fio)
562			CONFIG[FIO_PLUGIN]=n
563			;;
564		--with-vtune=*)
565			check_dir "$i"
566			CONFIG[VTUNE_DIR]="${i#*=}"
567			CONFIG[VTUNE]=y
568			;;
569		--without-vtune)
570			CONFIG[VTUNE_DIR]=
571			CONFIG[VTUNE]=n
572			;;
573		--with-ocf)
574			CONFIG[OCF]=y
575			CONFIG[OCF_PATH]=$(readlink -f "./ocf")
576			;;
577		--with-ocf=*)
578			CONFIG[OCF]=y
579			CONFIG[OCF_PATH]=$(readlink -f ${i#*=})
580			;;
581		--without-ocf)
582			CONFIG[OCF]=n
583			CONFIG[OCF_PATH]=
584			;;
585		--with-isal)
586			CONFIG[ISAL]=y
587			;;
588		--without-isal)
589			CONFIG[ISAL]=n
590			;;
591		--with-uring=*)
592			CONFIG[URING]=y
593			CONFIG[URING_PATH]=$(readlink -f ${i#*=})
594			;;
595		--with-uring)
596			CONFIG[URING]=y
597			CONFIG[URING_PATH]=
598			;;
599		--without-uring)
600			CONFIG[URING]=n
601			CONFIG[URING_PATH]=
602			;;
603		--with-openssl=*)
604			check_dir "$i"
605			CONFIG[OPENSSL_PATH]=$(readlink -f ${i#*=})
606			;;
607		--with-fuse)
608			CONFIG[FUSE]=y
609			;;
610		--without-fuse)
611			CONFIG[FUSE]=n
612			;;
613		--with-nvme-cuse)
614			CONFIG[NVME_CUSE]=y
615			;;
616		--without-nvme-cuse)
617			CONFIG[NVME_CUSE]=n
618			;;
619		--with-raid5)
620			CONFIG[RAID5]=y
621			;;
622		--without-raid5)
623			CONFIG[RAID5]=n
624			;;
625		--with-idxd)
626			CONFIG[IDXD]=y
627			CONFIG[IDXD_KERNEL]=n
628			;;
629		--without-idxd)
630			CONFIG[IDXD]=n
631			;;
632		--with-usdt)
633			CONFIG[USDT]=y
634			;;
635		--without-usdt)
636			CONFIG[USDT]=n
637			;;
638		--with-fuzzer)
639			echo "Must specify fuzzer library path with --with-fuzzer"
640			usage
641			exit 1
642			;;
643		--with-fuzzer=*)
644			CONFIG[FUZZER]=y
645			CONFIG[FUZZER_LIB]=$(readlink -f ${i#*=})
646			;;
647		--without-fuzzer)
648			CONFIG[FUZZER]=n
649			CONFIG[FUZZER_LIB]=
650			;;
651		--with-sma)
652			CONFIG[SMA]=y
653			;;
654		--without-sma)
655			CONFIG[SMA]=n
656			;;
657		--)
658			break
659			;;
660		*)
661			echo "Unrecognized option $i"
662			usage
663			exit 1
664			;;
665	esac
666done
667
668if [[ $arch == x86_64* ]]; then
669	BUILD_CMD=($CC -o /dev/null -x c $CPPFLAGS $CFLAGS $LDFLAGS "-march=native")
670else
671	BUILD_CMD=($CC -o /dev/null -x c $CPPFLAGS $CFLAGS $LDFLAGS)
672fi
673BUILD_CMD+=(-I/usr/local/include -L/usr/local/lib)
674
675if [[ "${CONFIG[VFIO_USER]}" = "y" ]]; then
676	if ! echo -e '#include <json-c/json.h>' \
677		| "${BUILD_CMD[@]}" -E - 2> /dev/null; then
678		echo "ERROR: --with-vfio-user requires json-c-devel"
679		echo "Please install then re-run this script"
680		exit 1
681	fi
682	if ! echo -e '#include <cmocka.h>' \
683		| "${BUILD_CMD[@]}" -E - 2> /dev/null; then
684		echo "ERROR: --with-vfio-user requires libcmocka-devel"
685		echo "Please install then re-run this script"
686		exit 1
687	fi
688fi
689
690# IDXD uses Intel specific instructions.
691if [[ "${CONFIG[IDXD]}" = "y" ]]; then
692	if [ $(uname -s) == "FreeBSD" ]; then
693		intel="hw.model: Intel"
694		cpu_vendor=$(sysctl -a | grep hw.model | cut -c 1-15)
695	else
696		intel="GenuineIntel"
697		cpu_vendor=$(grep -i 'vendor' /proc/cpuinfo --max-count=1)
698	fi
699	if [[ "$cpu_vendor" != *"$intel"* ]]; then
700		echo "ERROR: IDXD cannot be used due to CPU incompatibility."
701		exit 1
702	fi
703	if [ -e /usr/include/accel-config/libaccel_config.h ]; then
704		CONFIG[IDXD_KERNEL]=y
705	fi
706
707fi
708
709# Detect architecture and force no ISA-L if non-x86 or non-aarch64 architecture
710if [[ "${CONFIG[ISAL]}" = "y" ]]; then
711	if [[ $arch != x86_64* ]] && [[ $arch != aarch64* ]]; then
712		echo "ERROR: ISA-L cannot be used due to CPU incompatibility."
713		exit 1
714	fi
715fi
716
717if [[ "${CONFIG[ISAL]}" = "n" ]] && [[ "${CONFIG[REDUCE]}" = "y" ]]; then
718	echo "ERROR Conflicting options: --with-reduce is not compatible with --without-isal."
719	exit 1
720fi
721
722if [ -z "${CONFIG[ENV]}" ]; then
723	CONFIG[ENV]=$rootdir/lib/env_dpdk
724	echo "Using default SPDK env in ${CONFIG[ENV]}"
725	if [[ -z "${CONFIG[DPDK_DIR]}" && "${CONFIG[DPDK_PKG_CONFIG]}" == n ]]; then
726		if [ ! -f "$rootdir"/dpdk/config/meson.build ]; then
727			echo "DPDK not found; please specify --with-dpdk=<path> or run:"
728			echo
729			echo "  git submodule update --init"
730			exit 1
731		else
732			CONFIG[DPDK_DIR]="${rootdir}/dpdk/build"
733			# Default ipsec libs
734			if [[ "${CONFIG[CRYPTO]}" = "y" ]]; then
735				CONFIG[IPSEC_MB]=y
736				CONFIG[IPSEC_MB_DIR]="${rootdir}/intel-ipsec-mb/lib"
737			fi
738			echo "Using default DPDK in ${CONFIG[DPDK_DIR]}"
739		fi
740	fi
741else
742	if [[ -n "${CONFIG[DPDK_DIR]}" || "${CONFIG[DPDK_PKG_CONFIG]}" == y ]]; then
743		echo "--with-env and --with-dpdk are mutually exclusive."
744		exit 1
745	fi
746
747	if [ "${CONFIG[VHOST]}" = "y" ]; then
748		echo "Vhost is only supported when using the default DPDK environment. Disabling it."
749	fi
750	# Always disable vhost, but only print the error message if the user explicitly turned it on.
751	CONFIG[VHOST]="n"
752	if [ "${CONFIG[VIRTIO]}" = "y" ]; then
753		echo "Virtio is only supported when using the default DPDK environment. Disabling it."
754	fi
755	# Always disable virtio, but only print the error message if the user explicitly turned it on.
756	CONFIG[VIRTIO]="n"
757fi
758
759if [[ "${CONFIG[DPDK_PKG_CONFIG]}" == y ]]; then
760	if [[ "${CONFIG[SHARED]}" == n ]]; then
761		# dpdk-devel doesn't provide static libs
762		echo "Build against packaged DPDK requested, enabling shared libraries"
763		CONFIG[SHARED]=y
764	fi
765fi
766
767if [[ $sys_name == "Windows" ]]; then
768	if [ -z "${CONFIG[WPDK_DIR]}" ]; then
769		if [ ! -f "$rootdir"/wpdk/Makefile ]; then
770			echo "WPDK not found; please specify --with-wpdk=<path>. See https://wpdk.github.io."
771			exit 1
772		else
773			CONFIG[WPDK_DIR]="${rootdir}/wpdk/build"
774			echo "Using default WPDK in ${CONFIG[WPDK_DIR]}"
775		fi
776	fi
777else
778	if [ -n "${CONFIG[WPDK_DIR]}" ]; then
779		echo "ERROR: --with-wpdk is only supported for Windows"
780		exit 1
781	fi
782fi
783
784if [ "${CONFIG[VTUNE]}" = "y" ]; then
785	if [ -z "${CONFIG[VTUNE_DIR]}" ]; then
786		echo "When VTune is enabled, you must specify the VTune directory using --with-vtune=path"
787		exit 1
788	fi
789fi
790
791if [[ "${CONFIG[ASAN]}" = "y" && "${CONFIG[TSAN]}" = "y" ]]; then
792	echo "ERROR: ASAN and TSAN cannot be enabled at the same time."
793	exit 1
794fi
795
796if [[ "${CONFIG[FIO_PLUGIN]}" = "y" && "${CONFIG[EXAMPLES]}" = "n" ]]; then
797	echo "ERROR: --with-fio and --disable-examples are mutually exclusive."
798	exit 1
799fi
800
801if [[ $sys_name == "FreeBSD" ]]; then
802	# FreeBSD doesn't support all configurations
803	if [[ "${CONFIG[COVERAGE]}" == "y" ]]; then
804		echo "ERROR: CONFIG_COVERAGE not available on FreeBSD"
805		exit 1
806	fi
807fi
808
809if [[ $sys_name != "Linux" ]]; then
810	if [[ "${CONFIG[VHOST]}" == "y" ]]; then
811		echo "Vhost is only supported on Linux."
812		exit 1
813	fi
814	if [[ "${CONFIG[VIRTIO]}" == "y" ]]; then
815		echo "Virtio is only supported on Linux."
816		exit 1
817	fi
818fi
819
820if [ "${CONFIG[RDMA]}" = "y" ]; then
821	if [[ ! "${CONFIG[RDMA_PROV]}" == "verbs" ]] && [[ ! "${CONFIG[RDMA_PROV]}" == "mlx5_dv" ]]; then
822		echo "Invalid RDMA provider specified, must be \"verbs\" or \"mlx5_dv\""
823		exit 1
824	fi
825
826	if ! echo -e '#include <infiniband/verbs.h>\n#include <rdma/rdma_verbs.h>\n' \
827		'int main(void) { return 0; }\n' \
828		| "${BUILD_CMD[@]}" -libverbs -lrdmacm - 2> /dev/null; then
829		echo "--with-rdma requires libverbs and librdmacm."
830		echo "Please install then re-run this script."
831		exit 1
832	fi
833
834	if echo -e '#include <infiniband/verbs.h>\n' \
835		'int main(void) { return !!IBV_WR_SEND_WITH_INV; }\n' \
836		| "${BUILD_CMD[@]}" -c - 2> /dev/null; then
837		CONFIG[RDMA_SEND_WITH_INVAL]="y"
838	else
839		CONFIG[RDMA_SEND_WITH_INVAL]="n"
840		echo "
841*******************************************************************************
842WARNING: The Infiniband Verbs opcode Send With Invalidate is either not
843supported or is not functional with the current version of libibverbs installed
844on this system. Please upgrade to at least version 1.1.
845
846Beginning with Linux kernel 4.14, the kernel NVMe-oF initiator leverages Send
847With Invalidate RDMA operations to improve performance. Failing to use the
848Send With Invalidate operation on the NVMe-oF target side results in full
849functionality, but greatly reduced performance. The SPDK NVMe-oF target will
850be unable to leverage that operation using the currently installed version
851of libibverbs, so Linux kernel NVMe-oF initiators based on kernels greater
852than or equal to 4.14 will see significantly reduced performance.
853*******************************************************************************"
854	fi
855
856	if echo -e '#include <rdma/rdma_cma.h>\n' \
857		'int main(void) { return !!RDMA_OPTION_ID_ACK_TIMEOUT; }\n' \
858		| "${BUILD_CMD[@]}" -c - 2> /dev/null; then
859		CONFIG[RDMA_SET_ACK_TIMEOUT]="y"
860	else
861		CONFIG[RDMA_SET_ACK_TIMEOUT]="n"
862		echo "RDMA_OPTION_ID_ACK_TIMEOUT is not supported"
863	fi
864
865	if [ "${CONFIG[RDMA_PROV]}" == "mlx5_dv" ]; then
866		if ! echo -e '#include <spdk/stdinc.h>\n' \
867			'#include <infiniband/mlx5dv.h>\n' \
868			'#include <rdma/rdma_cma.h>\n' \
869			'int main(void) { return rdma_establish(NULL) || ' \
870			'!!IBV_QP_INIT_ATTR_SEND_OPS_FLAGS || !!MLX5_OPCODE_RDMA_WRITE; }\n' \
871			| "${BUILD_CMD[@]}" -lmlx5 -I${rootdir}/include -c - 2> /dev/null; then
872			echo "mlx5_dv provider is not supported"
873			exit 1
874		fi
875	fi
876
877	echo "Using '${CONFIG[RDMA_PROV]}' RDMA provider"
878fi
879
880if [[ "${CONFIG[FC]}" = "y" ]]; then
881	if [[ -n "${CONFIG[FC_PATH]}" ]]; then
882		if [ ! -d "${CONFIG[FC_PATH]}" ]; then
883			echo "${CONFIG[FC_PATH]}: directory not found"
884			exit 1
885		fi
886	fi
887fi
888
889if [[ "${CONFIG[ISAL]}" = "y" ]] || [[ "${CONFIG[CRYPTO]}" = "y" ]]; then
890	if [[ "${HAVE_NASM}" = "n" ]] && [[ $arch == x86_64* ]]; then
891		echo "ERROR: ISA-L, compression & crypto require NASM version 2.14 or newer."
892		echo "Please install or upgrade them re-run this script."
893		exit 1
894	fi
895fi
896
897if [[ "${CONFIG[PMDK]}" = "y" ]]; then
898	if ! echo -e '#include <libpmemblk.h>\nint main(void) { return 0; }\n' \
899		| "${BUILD_CMD[@]}" -lpmemblk - 2> /dev/null; then
900		echo "--with-pmdk requires libpmemblk."
901		echo "Please install then re-run this script."
902		exit 1
903	fi
904fi
905
906function dpdk_version() {
907	# Check DPDK version to determine if mlx5_pci driver is supported
908	local dpdk_ver="none"
909	if [[ "${CONFIG[DPDK_DIR]}" == "$rootdir/dpdk/build" ]]; then
910		# DPDK_DIR points at our submodule so ./build may not exist yet. Use
911		# absolute path to lookup the version.
912		dpdk_ver=$(< "$rootdir/dpdk/VERSION")
913	elif [[ -f "${CONFIG[DPDK_DIR]}"/../VERSION ]]; then
914		dpdk_ver=$(< "${CONFIG[DPDK_DIR]}"/../VERSION)
915	fi
916	echo $dpdk_ver
917}
918
919function mlx5_build() {
920	# Check if libmlx5 exists to enable mlx5_pci compress/crypto PMD
921	if ! echo -e '#include <spdk/stdinc.h>\n' \
922		'#include <infiniband/mlx5dv.h>\n' \
923		'#include <infiniband/verbs.h>\n' \
924		'int main(void) { return 0; }\n' \
925		| "${BUILD_CMD[@]}" -lmlx5 -libverbs -I${rootdir}/include -c - 2> /dev/null; then
926		return 1
927	fi
928	return 0
929}
930
931if [[ "${CONFIG[REDUCE]}" = "y" ]]; then
932	if ! echo -e '#include <libpmem.h>\nint main(void) { return 0; }\n' \
933		| "${BUILD_CMD[@]}" -lpmem - 2> /dev/null; then
934		echo "--with-reduce requires libpmem."
935		echo "Please install then re-run this script."
936		exit 1
937	fi
938	# Try to enable mlx5 compress
939	CONFIG[REDUCE_MLX5]="y"
940
941	# Check if libmlx5 exists to enable mlx5_pci compress PMD
942	if ! mlx5_build; then
943		echo "libmlx5 is not found, so disabling DPDK mlx5_pci compress PMD"
944		CONFIG[REDUCE_MLX5]="n"
945	else
946		if [[ "${CONFIG[DPDK_PKG_CONFIG]}" = "y" ]]; then
947			# Check if librte_compress_mlx5 exists in DPDK package
948			if [ ! -f "${CONFIG[DPDK_LIB_DIR]}"/librte_compress_mlx5.so ]; then
949				echo "librte_compress_mlx5 is not found, so disabling DPDK mlx5_pci compress PMD"
950				CONFIG[REDUCE_MLX5]="n"
951			fi
952		else
953			# Check DPDK version to determine if mlx5_pci driver is supported
954			dpdk_ver=$(dpdk_version)
955			if [[ $dpdk_ver = "none" ]]; then
956				echo "Cannot get DPDK version, so disabling DPDK mlx5_pci compress PMD"
957				CONFIG[REDUCE_MLX5]="n"
958			elif [[ -n $dpdk_ver ]] && lt "$dpdk_ver" 21.02.0; then
959				# mlx5_pci for compress is supported by DPDK >- 21.02.0
960				echo "DPDK version ${dpdk_ver} doesn't support mlx5_pci compress PMD"
961				CONFIG[REDUCE_MLX5]="n"
962			elif [[ -n ${CONFIG[DPDK_LIB_DIR]} ]] && [ ! -f "${CONFIG[DPDK_LIB_DIR]}"/librte_compress_mlx5.so ]; then
963				# This is only checked when --with-dpdk or --with-dpdk=* is used
964				echo "librte_compress_mlx5 is not found, so disabling DPDK mlx5_pci compress PMD"
965				CONFIG[REDUCE_MLX5]="n"
966			fi
967		fi
968	fi
969fi
970
971if [[ "${CONFIG[CRYPTO]}" = "y" ]]; then
972	# Try to enable mlx5 crypto
973	CONFIG[CRYPTO_MLX5]="y"
974
975	# Check if libmlx5 exists to enable mlx5_pci compress PMD
976	if ! mlx5_build; then
977		echo "libmlx5 is not found, so disabling DPDK mlx5_pci crypto PMD"
978		CONFIG[CRYPTO_MLX5]="n"
979	else
980		if [[ "${CONFIG[DPDK_PKG_CONFIG]}" = "y" ]]; then
981			# Check if librte_crypto_mlx5 exists in DPDK package
982			if [ ! -f "${CONFIG[DPDK_LIB_DIR]}"/librte_crypto_mlx5.so ]; then
983				echo "librte_crypto_mlx5 is not found, so disabling DPDK mlx5_pci crypto PMD"
984				CONFIG[CRYPTO_MLX5]="n"
985			fi
986		else
987			# Check DPDK version to determine if mlx5_pci driver is supported
988			dpdk_ver=$(dpdk_version)
989			if [[ $dpdk_ver = "none" ]]; then
990				echo "Cannot get DPDK version, so disabling DPDK mlx5_pci crypto PMD"
991				CONFIG[CRYPTO_MLX5]="n"
992			elif [[ -n $dpdk_ver ]] && lt "$dpdk_ver" 21.11.0; then
993				# mlx5_pci for crypto is supported by DPDK >- 21.11.0
994				echo "DPDK version ${dpdk_ver} doesn't support mlx5_pci crypto PMD"
995				CONFIG[CRYPTO_MLX5]="n"
996			elif [[ -n ${CONFIG[DPDK_LIB_DIR]} ]] && [ ! -f "${CONFIG[DPDK_LIB_DIR]}"/librte_crypto_mlx5.so ]; then
997				# This is only checked when --with-dpdk or --with-dpdk=* is used
998				echo "librte_crypto_mlx5 is not found, so disabling DPDK mlx5_pci crypto PMD"
999				CONFIG[CRYPTO_MLX5]="n"
1000			fi
1001		fi
1002	fi
1003fi
1004
1005if [[ "${CONFIG[NVME_CUSE]}" = "y" ]]; then
1006	if ! echo -e '#define FUSE_USE_VERSION 31\n#include <fuse3/cuse_lowlevel.h>\n#include <fuse3/fuse_lowlevel.h>\n#include <fuse3/fuse_opt.h>\nint main(void) { return 0; }\n' \
1007		| "${BUILD_CMD[@]}" -lfuse3 -D_FILE_OFFSET_BITS=64 - 2> /dev/null; then
1008		echo "--with-cuse requires libfuse3."
1009		echo "Please install then re-run this script."
1010		exit 1
1011	fi
1012fi
1013
1014if [[ "${CONFIG[RBD]}" = "y" ]]; then
1015	if ! echo -e '#include <rbd/librbd.h>\n#include <rados/librados.h>\n' \
1016		'int main(void) { return 0; }\n' \
1017		| "${BUILD_CMD[@]}" -lrados -lrbd - 2> /dev/null; then
1018		echo "--with-rbd requires librados and librbd."
1019		echo "Please install then re-run this script."
1020		exit 1
1021	fi
1022fi
1023
1024if [[ "${CONFIG[ISCSI_INITIATOR]}" = "y" ]]; then
1025	# Fedora installs libiscsi to /usr/lib64/iscsi for some reason.
1026	if ! echo -e '#include <iscsi/iscsi.h>\n#include <iscsi/scsi-lowlevel.h>\n' \
1027		'#if LIBISCSI_API_VERSION < 20150621\n' \
1028		'#error\n' \
1029		'#endif\n' \
1030		'int main(void) { return 0; }\n' \
1031		| "${BUILD_CMD[@]}" -L/usr/lib64/iscsi -liscsi - 2> /dev/null; then
1032		echo "--with-iscsi-initiator requires libiscsi with"
1033		echo "LIBISCSI_API_VERSION >= 20150621."
1034		echo "Please install then re-run this script."
1035		exit 1
1036	fi
1037fi
1038
1039if [[ "${CONFIG[ASAN]}" = "y" ]]; then
1040	if ! echo -e 'int main(void) { return 0; }\n' \
1041		| "${BUILD_CMD[@]}" -fsanitize=address - 2> /dev/null; then
1042		echo "--enable-asan requires libasan."
1043		echo "Please install then re-run this script."
1044		exit 1
1045	fi
1046fi
1047
1048if [[ "${CONFIG[UBSAN]}" = "y" ]]; then
1049	if ! echo -e 'int main(void) { return 0; }\n' \
1050		| "${BUILD_CMD[@]}" -fsanitize=undefined - 2> /dev/null; then
1051		echo "--enable-ubsan requires libubsan."
1052		echo "Please install then re-run this script."
1053		echo "If installed, please check that the GCC version is at least 6.4"
1054		echo "and synchronize CC accordingly."
1055		exit 1
1056	fi
1057fi
1058
1059if [[ "${CONFIG[TSAN]}" = "y" ]]; then
1060	if ! echo -e 'int main(void) { return 0; }\n' \
1061		| "${BUILD_CMD[@]}" -fsanitize=thread - 2> /dev/null; then
1062		echo "--enable-tsan requires libtsan."
1063		echo "Please install then re-run this script."
1064		exit 1
1065	fi
1066fi
1067
1068if [[ "${CONFIG[OCF]}" = "y" ]]; then
1069	# If OCF_PATH is a file, assume it is a library and use it to compile with
1070	if [ -f ${CONFIG[OCF_PATH]} ]; then
1071		CONFIG[CUSTOMOCF]=y
1072	else
1073		CONFIG[CUSTOMOCF]=n
1074	fi
1075fi
1076
1077if [[ "${CONFIG[PGO_CAPTURE]}" = "y" && "${CONFIG[PGO_USE]}" = "y" ]]; then
1078	echo "ERROR: --enable-pgo-capture and --enable-pgo-use are mutually exclusive."
1079	exit 1
1080elif [[ "${CONFIG[PGO_USE]}" = "y" ]]; then
1081	if [[ "$CC_TYPE" = "clang" ]]; then
1082		# For clang we need to run an extra step on gathered profiling data.
1083		echo "Generating suitable profile data"
1084		llvm-profdata merge -output=build/pgo/default.profdata build/pgo
1085	fi
1086fi
1087
1088if [[ "${CONFIG[URING]}" = "y" ]]; then
1089	if [[ -n "${CONFIG[URING_PATH]}" ]]; then
1090		if [ ! -d "${CONFIG[URING_PATH]}" ]; then
1091			echo "${CONFIG[URING_PATH]}: directory not found"
1092			exit 1
1093		fi
1094	elif ! echo -e '#include <liburing.h>\nint main(void) { return 0; }\n' \
1095		| "${BUILD_CMD[@]}" -luring - 2> /dev/null; then
1096		echo "--with-uring requires liburing."
1097		echo "Please build and install then re-run this script."
1098		exit 1
1099	fi
1100fi
1101
1102if [[ "${CONFIG[FUSE]}" = "y" ]]; then
1103	if [[ ! -d /usr/include/fuse3 ]] && [[ ! -d /usr/local/include/fuse3 ]]; then
1104		echo "--with-fuse requires libfuse3."
1105		echo "Please install then re-run this script."
1106		exit 1
1107	fi
1108fi
1109
1110if [ "${CONFIG[CET]}" = "y" ]; then
1111	if ! echo -e 'int main(void) { return 0; }\n' | "${BUILD_CMD[@]}" -fcf-protection - 2> /dev/null; then
1112		echo "--enable-cet requires compiler/linker that supports CET."
1113		echo "Please install then re-run this script."
1114		exit 1
1115	fi
1116fi
1117
1118if [[ "${CONFIG[FUZZER]}" = "y" && "$CC_TYPE" != "clang" ]]; then
1119	echo "--with-fuzzer requires setting CC and CXX to clang."
1120	exit 1
1121fi
1122
1123if [[ "${CONFIG[ISAL]}" = "y" ]]; then
1124	if [ ! -f "$rootdir"/isa-l/autogen.sh ]; then
1125		echo "ISA-L was not found; To install ISA-L run:"
1126		echo "  git submodule update --init"
1127		exit 1
1128	fi
1129
1130	cd $rootdir/isa-l
1131	ISAL_LOG=$rootdir/isa-l/spdk-isal.log
1132	if [[ -n "${CONFIG[CROSS_PREFIX]}" ]]; then
1133		ISAL_OPTS=("--host=${CONFIG[CROSS_PREFIX]}")
1134	else
1135		ISAL_OPTS=()
1136	fi
1137	echo -n "Configuring ISA-L (logfile: $ISAL_LOG)..."
1138	./autogen.sh &> $ISAL_LOG
1139	./configure CFLAGS="-fPIC -g -O2" "${ISAL_OPTS[@]}" --enable-shared=no >> $ISAL_LOG 2>&1
1140	echo "done."
1141	cd $rootdir
1142fi
1143
1144if [[ "${CONFIG[SMA]}" = "y" ]]; then
1145	if ! python3 -c 'import grpc; import grpc_tools' 2> /dev/null; then
1146		echo "--with-sma requires grpcio and grpcio-tools python packages."
1147		echo "Please install then re-run this script."
1148		exit 1
1149	fi
1150fi
1151
1152# For ARM Neoverse-N1 platform, debug build needs gcc version newer than 8.4
1153if [[ "${CONFIG[DEBUG]}" = "y" && $arch = aarch64* && "$CC_TYPE" = "gcc" ]]; then
1154	GCC_VERSION=$($CC -dumpfullversion)
1155	PART_NUM=$(grep -i -m 1 "CPU part" /proc/cpuinfo | awk '{print $4}')
1156
1157	if [[ "$(printf '%s\n' "8.4.0" "$GCC_VERSION" | sort -V | head -n1)" != "8.4.0" ]]; then
1158		if [[ $PART_NUM = 0xd0c ]]; then
1159			echo "WARNING: For ARM Neoverse-N1 platform, debug build needs GCC version newer than 8.4."
1160			echo "         Will work around this by using armv8.2-a+crypto as target architecture for now."
1161			CONFIG[ARCH]=armv8.2-a+crypto
1162		fi
1163	fi
1164fi
1165
1166# We are now ready to generate final configuration. But first do sanity
1167# check to see if all keys in CONFIG array have its reflection in CONFIG file.
1168if (($(grep -cE "^\s*CONFIG_[[:alnum:]_]+=" "$rootdir/CONFIG") != ${#CONFIG[@]})); then
1169	echo ""
1170	echo "BUG: Some configuration options are not present in CONFIG file. Please update this file."
1171	echo "Missing options in CONFIG (+) file and in current config (-): "
1172	diff -u --label "CONFIG file" --label "CONFIG[@]" \
1173		<(sed -r -e '/^[[:space:]]*$/d; /^[[:space:]]*#.*/d; s/(CONFIG_[[:alnum:]_]+)=.*/\1/g' CONFIG | sort) \
1174		<(printf "CONFIG_%s\n" "${!CONFIG[@]}" | sort)
1175	exit 1
1176fi
1177
1178echo -n "Creating mk/config.mk..."
1179cp -f $rootdir/CONFIG $rootdir/mk/config.mk
1180for key in "${!CONFIG[@]}"; do
1181	sed -i.bak -r "s#[[:space:]]*CONFIG_${key}=.*#CONFIG_${key}\?=${CONFIG[$key]}#g" $rootdir/mk/config.mk
1182done
1183# On FreeBSD sed -i 'SUFFIX' - SUFFIX is mandatory. So no way but to delete the backed file.
1184rm -f $rootdir/mk/config.mk.bak
1185echo "done."
1186
1187# Environment variables
1188echo -n "Creating mk/cc.flags.mk..."
1189rm -f $rootdir/mk/cc.flags.mk
1190[ -n "$CFLAGS" ] && echo "CFLAGS?=$CFLAGS" > $rootdir/mk/cc.flags.mk
1191[ -n "$CXXFLAGS" ] && echo "CXXFLAGS?=$CXXFLAGS" >> $rootdir/mk/cc.flags.mk
1192[ -n "$LDFLAGS" ] && echo "LDFLAGS?=$LDFLAGS" >> $rootdir/mk/cc.flags.mk
1193[ -n "$DESTDIR" ] && echo "DESTDIR?=$DESTDIR" >> $rootdir/mk/cc.flags.mk
1194echo "done."
1195
1196# Create .sh with build config for easy sourcing|lookup during the tests.
1197for conf in "${!CONFIG[@]}"; do
1198	echo "CONFIG_$conf=${CONFIG[$conf]}"
1199done > "$rootdir/test/common/build_config.sh"
1200
1201if [[ $sys_name == "FreeBSD" ]]; then
1202	echo "Type 'gmake' to build."
1203else
1204	echo "Type 'make' to build."
1205fi
1206
1207exit 0
1208