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