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