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