xref: /spdk/configure (revision 18c8b52afa69f39481ebb75711b2f30b11693f9d)
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[=DIR]         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			CONFIG[DAOS_DIR]=""
492			;;
493		--with-daos=*)
494			CONFIG[DAOS]=y
495			check_dir "$i"
496			CONFIG[DAOS_DIR]=$(readlink -f ${i#*=})
497			;;
498		--without-daos)
499			CONFIG[DAOS]=n
500			;;
501		--with-shared)
502			CONFIG[SHARED]=y
503			;;
504		--without-shared)
505			CONFIG[SHARED]=n
506			;;
507		--with-iscsi-initiator)
508			CONFIG[ISCSI_INITIATOR]=y
509			;;
510		--without-iscsi-initiator)
511			CONFIG[ISCSI_INITIATOR]=n
512			;;
513		--with-crypto)
514			CONFIG[CRYPTO]=y
515			;;
516		--without-crypto)
517			CONFIG[CRYPTO]=n
518			;;
519		--with-vhost)
520			CONFIG[VHOST]=y
521			;;
522		--without-vhost)
523			CONFIG[VHOST]=n
524			;;
525		--with-virtio)
526			CONFIG[VIRTIO]=y
527			;;
528		--without-virtio)
529			CONFIG[VIRTIO]=n
530			;;
531		--with-vfio-user)
532			CONFIG[VFIO_USER]=y
533			CONFIG[VFIO_USER_DIR]=""
534			;;
535		--with-vfio-user=*)
536			CONFIG[VFIO_USER]=y
537			check_dir "$i"
538			CONFIG[VFIO_USER_DIR]=$(readlink -f ${i#*=})
539			;;
540		--without-vfio-user)
541			CONFIG[VFIO_USER]=n
542			;;
543		--with-pmdk)
544			CONFIG[PMDK]=y
545			CONFIG[PMDK_DIR]=""
546			;;
547		--with-pmdk=*)
548			CONFIG[PMDK]=y
549			check_dir "$i"
550			CONFIG[PMDK_DIR]=$(readlink -f ${i#*=})
551			;;
552		--without-pmdk)
553			CONFIG[PMDK]=n
554			;;
555		--with-reduce)
556			CONFIG[REDUCE]=y
557			;;
558		--without-reduce)
559			CONFIG[REDUCE]=n
560			;;
561		--with-xnvme)
562			CONFIG[XNVME]=y
563			;;
564		--without-xnvme)
565			CONFIG[XNVME]=n
566			;;
567		--with-fio) ;&
568		--with-fio=*)
569			if [[ ${i#*=} != "$i" ]]; then
570				CONFIG[FIO_SOURCE_DIR]=${i#*=}
571			fi
572			check_dir "--with-fio=${CONFIG[FIO_SOURCE_DIR]}"
573			CONFIG[FIO_SOURCE_DIR]=$(readlink -f "${CONFIG[FIO_SOURCE_DIR]}")
574			CONFIG[FIO_PLUGIN]=y
575			;;
576		--without-fio)
577			CONFIG[FIO_PLUGIN]=n
578			;;
579		--with-vtune=*)
580			check_dir "$i"
581			CONFIG[VTUNE_DIR]="${i#*=}"
582			CONFIG[VTUNE]=y
583			;;
584		--without-vtune)
585			CONFIG[VTUNE_DIR]=
586			CONFIG[VTUNE]=n
587			;;
588		--with-ocf)
589			CONFIG[OCF]=y
590			CONFIG[OCF_PATH]=$(readlink -f "./ocf")
591			;;
592		--with-ocf=*)
593			CONFIG[OCF]=y
594			CONFIG[OCF_PATH]=$(readlink -f ${i#*=})
595			;;
596		--without-ocf)
597			CONFIG[OCF]=n
598			CONFIG[OCF_PATH]=
599			;;
600		--with-isal)
601			CONFIG[ISAL]=y
602			;;
603		--without-isal)
604			CONFIG[ISAL]=n
605			;;
606		--with-uring=*)
607			CONFIG[URING]=y
608			CONFIG[URING_PATH]=$(readlink -f ${i#*=})
609			;;
610		--with-uring)
611			CONFIG[URING]=y
612			CONFIG[URING_PATH]=
613			;;
614		--without-uring)
615			CONFIG[URING]=n
616			CONFIG[URING_PATH]=
617			;;
618		--with-uring-zns)
619			CONFIG[URING_ZNS]=y
620			;;
621		--with-openssl=*)
622			check_dir "$i"
623			CONFIG[OPENSSL_PATH]=$(readlink -f ${i#*=})
624			;;
625		--with-fuse)
626			CONFIG[FUSE]=y
627			;;
628		--without-fuse)
629			CONFIG[FUSE]=n
630			;;
631		--with-nvme-cuse)
632			CONFIG[NVME_CUSE]=y
633			;;
634		--without-nvme-cuse)
635			CONFIG[NVME_CUSE]=n
636			;;
637		--with-raid5f)
638			CONFIG[RAID5F]=y
639			;;
640		--without-raid5f)
641			CONFIG[RAID5F]=n
642			;;
643		--with-idxd)
644			CONFIG[IDXD]=y
645			CONFIG[IDXD_KERNEL]=n
646			;;
647		--without-idxd)
648			CONFIG[IDXD]=n
649			;;
650		--with-usdt)
651			CONFIG[USDT]=y
652			;;
653		--without-usdt)
654			CONFIG[USDT]=n
655			;;
656		--with-fuzzer)
657			echo "Must specify fuzzer library path with --with-fuzzer"
658			usage
659			exit 1
660			;;
661		--with-fuzzer=*)
662			CONFIG[FUZZER]=y
663			CONFIG[FUZZER_LIB]=$(readlink -f ${i#*=})
664			;;
665		--without-fuzzer)
666			CONFIG[FUZZER]=n
667			CONFIG[FUZZER_LIB]=
668			;;
669		--with-sma)
670			CONFIG[SMA]=y
671			;;
672		--without-sma)
673			CONFIG[SMA]=n
674			;;
675		--)
676			break
677			;;
678		*)
679			echo "Unrecognized option $i"
680			usage
681			exit 1
682			;;
683	esac
684done
685
686if [[ $arch == x86_64* ]]; then
687	BUILD_CMD=($CC -o /dev/null -x c $CPPFLAGS $CFLAGS $LDFLAGS "-march=native")
688else
689	BUILD_CMD=($CC -o /dev/null -x c $CPPFLAGS $CFLAGS $LDFLAGS)
690fi
691BUILD_CMD+=(-I/usr/local/include -L/usr/local/lib)
692
693if [[ "${CONFIG[VFIO_USER]}" = "y" ]]; then
694	if ! echo -e '#include <json-c/json.h>' \
695		| "${BUILD_CMD[@]}" -E - 2> /dev/null; then
696		echo "ERROR: --with-vfio-user requires json-c-devel"
697		echo "Please install then re-run this script"
698		exit 1
699	fi
700	if ! echo -e '#include <cmocka.h>' \
701		| "${BUILD_CMD[@]}" -E - 2> /dev/null; then
702		echo "ERROR: --with-vfio-user requires libcmocka-devel"
703		echo "Please install then re-run this script"
704		exit 1
705	fi
706fi
707
708# IDXD uses Intel specific instructions.
709if [[ "${CONFIG[IDXD]}" = "y" ]]; then
710	if [ $(uname -s) == "FreeBSD" ]; then
711		intel="hw.model: Intel"
712		cpu_vendor=$(sysctl -a | grep hw.model | cut -c 1-15)
713	else
714		intel="GenuineIntel"
715		cpu_vendor=$(grep -i 'vendor' /proc/cpuinfo --max-count=1)
716	fi
717	if [[ "$cpu_vendor" != *"$intel"* ]]; then
718		echo "ERROR: IDXD cannot be used due to CPU incompatibility."
719		exit 1
720	fi
721	if [ -e /usr/include/accel-config/libaccel_config.h ]; then
722		CONFIG[IDXD_KERNEL]=y
723	fi
724
725fi
726
727# Detect architecture and force no ISA-L if non-x86 or non-aarch64 architecture
728if [[ "${CONFIG[ISAL]}" = "y" ]]; then
729	if [[ $arch != x86_64* ]] && [[ $arch != aarch64* ]]; then
730		echo "ERROR: ISA-L cannot be used due to CPU incompatibility."
731		exit 1
732	fi
733fi
734
735if [[ "${CONFIG[ISAL]}" = "n" ]] && [[ "${CONFIG[REDUCE]}" = "y" ]]; then
736	echo "ERROR Conflicting options: --with-reduce is not compatible with --without-isal."
737	exit 1
738fi
739
740if [ -z "${CONFIG[ENV]}" ]; then
741	CONFIG[ENV]=$rootdir/lib/env_dpdk
742	echo "Using default SPDK env in ${CONFIG[ENV]}"
743	if [[ -z "${CONFIG[DPDK_DIR]}" && "${CONFIG[DPDK_PKG_CONFIG]}" == n ]]; then
744		if [ ! -f "$rootdir"/dpdk/config/meson.build ]; then
745			echo "DPDK not found; please specify --with-dpdk=<path> or run:"
746			echo
747			echo "  git submodule update --init"
748			exit 1
749		else
750			CONFIG[DPDK_DIR]="${rootdir}/dpdk/build"
751			# Default ipsec libs
752			if [[ "${CONFIG[CRYPTO]}" = "y" ]] && [[ $arch = x86_64* ]]; then
753				CONFIG[IPSEC_MB]=y
754				CONFIG[IPSEC_MB_DIR]="${rootdir}/intel-ipsec-mb/lib"
755			fi
756			echo "Using default DPDK in ${CONFIG[DPDK_DIR]}"
757		fi
758	fi
759else
760	if [[ -n "${CONFIG[DPDK_DIR]}" || "${CONFIG[DPDK_PKG_CONFIG]}" == y ]]; then
761		echo "--with-env and --with-dpdk are mutually exclusive."
762		exit 1
763	fi
764
765	if [ "${CONFIG[VHOST]}" = "y" ]; then
766		echo "Vhost is only supported when using the default DPDK environment. Disabling it."
767	fi
768	# Always disable vhost, but only print the error message if the user explicitly turned it on.
769	CONFIG[VHOST]="n"
770	if [ "${CONFIG[VIRTIO]}" = "y" ]; then
771		echo "Virtio is only supported when using the default DPDK environment. Disabling it."
772	fi
773	# Always disable virtio, but only print the error message if the user explicitly turned it on.
774	CONFIG[VIRTIO]="n"
775fi
776
777if [[ "${CONFIG[DPDK_PKG_CONFIG]}" == y ]]; then
778	if [[ "${CONFIG[SHARED]}" == n ]]; then
779		# dpdk-devel doesn't provide static libs
780		echo "Build against packaged DPDK requested, enabling shared libraries"
781		CONFIG[SHARED]=y
782	fi
783fi
784
785if [[ $sys_name == "Windows" ]]; then
786	if [ -z "${CONFIG[WPDK_DIR]}" ]; then
787		if [ ! -f "$rootdir"/wpdk/Makefile ]; then
788			echo "WPDK not found; please specify --with-wpdk=<path>. See https://wpdk.github.io."
789			exit 1
790		else
791			CONFIG[WPDK_DIR]="${rootdir}/wpdk/build"
792			echo "Using default WPDK in ${CONFIG[WPDK_DIR]}"
793		fi
794	fi
795else
796	if [ -n "${CONFIG[WPDK_DIR]}" ]; then
797		echo "ERROR: --with-wpdk is only supported for Windows"
798		exit 1
799	fi
800fi
801
802if [ "${CONFIG[VTUNE]}" = "y" ]; then
803	if [ -z "${CONFIG[VTUNE_DIR]}" ]; then
804		echo "When VTune is enabled, you must specify the VTune directory using --with-vtune=path"
805		exit 1
806	fi
807fi
808
809if [[ "${CONFIG[ASAN]}" = "y" && "${CONFIG[TSAN]}" = "y" ]]; then
810	echo "ERROR: ASAN and TSAN cannot be enabled at the same time."
811	exit 1
812fi
813
814if [[ "${CONFIG[FIO_PLUGIN]}" = "y" && "${CONFIG[EXAMPLES]}" = "n" ]]; then
815	echo "ERROR: --with-fio and --disable-examples are mutually exclusive."
816	exit 1
817fi
818
819if [[ $sys_name == "FreeBSD" ]]; then
820	# FreeBSD doesn't support all configurations
821	if [[ "${CONFIG[COVERAGE]}" == "y" ]]; then
822		echo "ERROR: CONFIG_COVERAGE not available on FreeBSD"
823		exit 1
824	fi
825fi
826
827if [[ $sys_name != "Linux" ]]; then
828	if [[ "${CONFIG[VHOST]}" == "y" ]]; then
829		echo "Vhost is only supported on Linux."
830		exit 1
831	fi
832	if [[ "${CONFIG[VIRTIO]}" == "y" ]]; then
833		echo "Virtio is only supported on Linux."
834		exit 1
835	fi
836fi
837
838if [ "${CONFIG[RDMA]}" = "y" ]; then
839	if [[ ! "${CONFIG[RDMA_PROV]}" == "verbs" ]] && [[ ! "${CONFIG[RDMA_PROV]}" == "mlx5_dv" ]]; then
840		echo "Invalid RDMA provider specified, must be \"verbs\" or \"mlx5_dv\""
841		exit 1
842	fi
843
844	if ! echo -e '#include <infiniband/verbs.h>\n#include <rdma/rdma_verbs.h>\n' \
845		'int main(void) { return 0; }\n' \
846		| "${BUILD_CMD[@]}" -libverbs -lrdmacm - 2> /dev/null; then
847		echo "--with-rdma requires libverbs and librdmacm."
848		echo "Please install then re-run this script."
849		exit 1
850	fi
851
852	if echo -e '#include <infiniband/verbs.h>\n' \
853		'int main(void) { return !!IBV_WR_SEND_WITH_INV; }\n' \
854		| "${BUILD_CMD[@]}" -c - 2> /dev/null; then
855		CONFIG[RDMA_SEND_WITH_INVAL]="y"
856	else
857		CONFIG[RDMA_SEND_WITH_INVAL]="n"
858		echo "
859*******************************************************************************
860WARNING: The Infiniband Verbs opcode Send With Invalidate is either not
861supported or is not functional with the current version of libibverbs installed
862on this system. Please upgrade to at least version 1.1.
863
864Beginning with Linux kernel 4.14, the kernel NVMe-oF initiator leverages Send
865With Invalidate RDMA operations to improve performance. Failing to use the
866Send With Invalidate operation on the NVMe-oF target side results in full
867functionality, but greatly reduced performance. The SPDK NVMe-oF target will
868be unable to leverage that operation using the currently installed version
869of libibverbs, so Linux kernel NVMe-oF initiators based on kernels greater
870than or equal to 4.14 will see significantly reduced performance.
871*******************************************************************************"
872	fi
873
874	if echo -e '#include <rdma/rdma_cma.h>\n' \
875		'int main(void) { return !!RDMA_OPTION_ID_ACK_TIMEOUT; }\n' \
876		| "${BUILD_CMD[@]}" -c - 2> /dev/null; then
877		CONFIG[RDMA_SET_ACK_TIMEOUT]="y"
878	else
879		CONFIG[RDMA_SET_ACK_TIMEOUT]="n"
880		echo "RDMA_OPTION_ID_ACK_TIMEOUT is not supported"
881	fi
882
883	if [ "${CONFIG[RDMA_PROV]}" == "mlx5_dv" ]; then
884		if ! echo -e '#include <spdk/stdinc.h>\n' \
885			'#include <infiniband/mlx5dv.h>\n' \
886			'#include <rdma/rdma_cma.h>\n' \
887			'int main(void) { return rdma_establish(NULL) || ' \
888			'!!IBV_QP_INIT_ATTR_SEND_OPS_FLAGS || !!MLX5_OPCODE_RDMA_WRITE; }\n' \
889			| "${BUILD_CMD[@]}" -lmlx5 -I${rootdir}/include -c - 2> /dev/null; then
890			echo "mlx5_dv provider is not supported"
891			exit 1
892		fi
893	fi
894
895	echo "Using '${CONFIG[RDMA_PROV]}' RDMA provider"
896fi
897
898if [[ "${CONFIG[FC]}" = "y" ]]; then
899	if [[ -n "${CONFIG[FC_PATH]}" ]]; then
900		if [ ! -d "${CONFIG[FC_PATH]}" ]; then
901			echo "${CONFIG[FC_PATH]}: directory not found"
902			exit 1
903		fi
904	fi
905fi
906
907if [[ "${CONFIG[ISAL]}" = "y" ]] || [[ "${CONFIG[CRYPTO]}" = "y" ]]; then
908	if [[ "${HAVE_NASM}" = "n" ]] && [[ $arch == x86_64* ]]; then
909		echo "ERROR: ISA-L, compression & crypto require NASM version 2.14 or newer."
910		echo "Please install or upgrade them re-run this script."
911		exit 1
912	fi
913fi
914
915if [[ "${CONFIG[PMDK]}" = "y" ]]; then
916	if ! echo -e '#include <libpmemblk.h>\nint main(void) { return 0; }\n' \
917		| "${BUILD_CMD[@]}" -lpmemblk - 2> /dev/null; then
918		echo "--with-pmdk requires libpmemblk."
919		echo "Please install then re-run this script."
920		exit 1
921	fi
922fi
923
924function dpdk_version() {
925	# Check DPDK version to determine if mlx5_pci driver is supported
926	local dpdk_ver="none"
927	if [[ "${CONFIG[DPDK_DIR]}" == "$rootdir/dpdk/build" ]]; then
928		# DPDK_DIR points at our submodule so ./build may not exist yet. Use
929		# absolute path to lookup the version.
930		dpdk_ver=$(< "$rootdir/dpdk/VERSION")
931	elif [[ -f "${CONFIG[DPDK_DIR]}"/../VERSION ]]; then
932		dpdk_ver=$(< "${CONFIG[DPDK_DIR]}"/../VERSION)
933	fi
934	echo $dpdk_ver
935}
936
937function mlx5_build() {
938	# Check if libmlx5 exists to enable mlx5_pci compress/crypto PMD
939	if ! echo -e '#include <spdk/stdinc.h>\n' \
940		'#include <infiniband/mlx5dv.h>\n' \
941		'#include <infiniband/verbs.h>\n' \
942		'int main(void) { return 0; }\n' \
943		| "${BUILD_CMD[@]}" -lmlx5 -libverbs -I${rootdir}/include -c - 2> /dev/null; then
944		return 1
945	fi
946	return 0
947}
948
949if [[ "${CONFIG[REDUCE]}" = "y" ]]; then
950	if ! echo -e '#include <libpmem.h>\nint main(void) { return 0; }\n' \
951		| "${BUILD_CMD[@]}" -lpmem - 2> /dev/null; then
952		echo "--with-reduce requires libpmem."
953		echo "Please install then re-run this script."
954		exit 1
955	fi
956	# Try to enable mlx5 compress
957	CONFIG[REDUCE_MLX5]="y"
958
959	# Check if libmlx5 exists to enable mlx5_pci compress PMD
960	if ! mlx5_build; then
961		echo "libmlx5 is not found, so disabling DPDK mlx5_pci compress PMD"
962		CONFIG[REDUCE_MLX5]="n"
963	else
964		if [[ "${CONFIG[DPDK_PKG_CONFIG]}" = "y" ]]; then
965			# Check if librte_compress_mlx5 exists in DPDK package
966			if [ ! -f "${CONFIG[DPDK_LIB_DIR]}"/librte_compress_mlx5.so ]; then
967				echo "librte_compress_mlx5 is not found, so disabling DPDK mlx5_pci compress PMD"
968				CONFIG[REDUCE_MLX5]="n"
969			fi
970		else
971			# Check DPDK version to determine if mlx5_pci driver is supported
972			dpdk_ver=$(dpdk_version)
973			if [[ $dpdk_ver = "none" ]]; then
974				echo "Cannot get DPDK version, so disabling DPDK mlx5_pci compress PMD"
975				CONFIG[REDUCE_MLX5]="n"
976			elif [[ -n $dpdk_ver ]] && lt "$dpdk_ver" 21.02.0; then
977				# mlx5_pci for compress is supported by DPDK >- 21.02.0
978				echo "DPDK version ${dpdk_ver} doesn't support mlx5_pci compress PMD"
979				CONFIG[REDUCE_MLX5]="n"
980			elif [[ -n ${CONFIG[DPDK_LIB_DIR]} ]] && [ ! -f "${CONFIG[DPDK_LIB_DIR]}"/librte_compress_mlx5.so ]; then
981				# This is only checked when --with-dpdk or --with-dpdk=* is used
982				echo "librte_compress_mlx5 is not found, so disabling DPDK mlx5_pci compress PMD"
983				CONFIG[REDUCE_MLX5]="n"
984			fi
985		fi
986	fi
987fi
988
989if [[ "${CONFIG[CRYPTO]}" = "y" ]]; then
990	# Try to enable mlx5 crypto
991	CONFIG[CRYPTO_MLX5]="y"
992
993	# Check if libmlx5 exists to enable mlx5_pci compress PMD
994	if ! mlx5_build; then
995		echo "libmlx5 is not found, so disabling DPDK mlx5_pci crypto PMD"
996		CONFIG[CRYPTO_MLX5]="n"
997	else
998		if [[ "${CONFIG[DPDK_PKG_CONFIG]}" = "y" ]]; then
999			# Check if librte_crypto_mlx5 exists in DPDK package
1000			if [ ! -f "${CONFIG[DPDK_LIB_DIR]}"/librte_crypto_mlx5.so ]; then
1001				echo "librte_crypto_mlx5 is not found, so disabling DPDK mlx5_pci crypto PMD"
1002				CONFIG[CRYPTO_MLX5]="n"
1003			fi
1004		else
1005			# Check DPDK version to determine if mlx5_pci driver is supported
1006			dpdk_ver=$(dpdk_version)
1007			if [[ $dpdk_ver = "none" ]]; then
1008				echo "Cannot get DPDK version, so disabling DPDK mlx5_pci crypto PMD"
1009				CONFIG[CRYPTO_MLX5]="n"
1010			elif [[ -n $dpdk_ver ]] && lt "$dpdk_ver" 21.11.0; then
1011				# mlx5_pci for crypto is supported by DPDK >- 21.11.0
1012				echo "DPDK version ${dpdk_ver} doesn't support mlx5_pci crypto PMD"
1013				CONFIG[CRYPTO_MLX5]="n"
1014			elif [[ -n ${CONFIG[DPDK_LIB_DIR]} ]] && [ ! -f "${CONFIG[DPDK_LIB_DIR]}"/librte_crypto_mlx5.so ]; then
1015				# This is only checked when --with-dpdk or --with-dpdk=* is used
1016				echo "librte_crypto_mlx5 is not found, so disabling DPDK mlx5_pci crypto PMD"
1017				CONFIG[CRYPTO_MLX5]="n"
1018			fi
1019		fi
1020	fi
1021fi
1022
1023if [[ "${CONFIG[NVME_CUSE]}" = "y" ]]; then
1024	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' \
1025		| "${BUILD_CMD[@]}" -lfuse3 -D_FILE_OFFSET_BITS=64 - 2> /dev/null; then
1026		echo "--with-cuse requires libfuse3."
1027		echo "Please install then re-run this script."
1028		exit 1
1029	fi
1030fi
1031
1032if [[ "${CONFIG[RBD]}" = "y" ]]; then
1033	if ! echo -e '#include <rbd/librbd.h>\n#include <rados/librados.h>\n' \
1034		'int main(void) { return 0; }\n' \
1035		| "${BUILD_CMD[@]}" -lrados -lrbd - 2> /dev/null; then
1036		echo "--with-rbd requires librados and librbd."
1037		echo "Please install then re-run this script."
1038		exit 1
1039	fi
1040fi
1041
1042if [[ "${CONFIG[ISCSI_INITIATOR]}" = "y" ]]; then
1043	# Fedora installs libiscsi to /usr/lib64/iscsi for some reason.
1044	if ! echo -e '#include <iscsi/iscsi.h>\n#include <iscsi/scsi-lowlevel.h>\n' \
1045		'#if LIBISCSI_API_VERSION < 20150621\n' \
1046		'#error\n' \
1047		'#endif\n' \
1048		'int main(void) { return 0; }\n' \
1049		| "${BUILD_CMD[@]}" -L/usr/lib64/iscsi -liscsi - 2> /dev/null; then
1050		echo "--with-iscsi-initiator requires libiscsi with"
1051		echo "LIBISCSI_API_VERSION >= 20150621."
1052		echo "Please install then re-run this script."
1053		exit 1
1054	fi
1055fi
1056
1057if [[ "${CONFIG[DAOS]}" = "y" ]]; then
1058	daos_build_cmd=("${BUILD_CMD[@]}")
1059	if [[ -n "${CONFIG[DAOS_DIR]}" ]]; then
1060		daos_build_cmd+=(-I"${CONFIG[DAOS_DIR]}"/include -L"${CONFIG[DAOS_DIR]}"/lib64)
1061	fi
1062	if ! echo -e '#include <daos.h>\n#include <daos_fs.h>\n' \
1063		'int main(void) { return 0; }\n' \
1064		| "${daos_build_cmd[@]}" -lgurt -ldaos -ldaos_common -ldfs - 2> /dev/null; then
1065		echo "--with-daos requires libdaos, libdaos_common, libdfs and libgurt"
1066		echo "Please install then re-run this script."
1067		exit 1
1068	fi
1069fi
1070
1071if [[ "${CONFIG[ASAN]}" = "y" ]]; then
1072	if ! echo -e 'int main(void) { return 0; }\n' \
1073		| "${BUILD_CMD[@]}" -fsanitize=address - 2> /dev/null; then
1074		echo "--enable-asan requires libasan."
1075		echo "Please install then re-run this script."
1076		exit 1
1077	fi
1078fi
1079
1080if [[ "${CONFIG[UBSAN]}" = "y" ]]; then
1081	if ! echo -e 'int main(void) { return 0; }\n' \
1082		| "${BUILD_CMD[@]}" -fsanitize=undefined - 2> /dev/null; then
1083		echo "--enable-ubsan requires libubsan."
1084		echo "Please install then re-run this script."
1085		echo "If installed, please check that the GCC version is at least 6.4"
1086		echo "and synchronize CC accordingly."
1087		exit 1
1088	fi
1089fi
1090
1091if [[ "${CONFIG[TSAN]}" = "y" ]]; then
1092	if ! echo -e 'int main(void) { return 0; }\n' \
1093		| "${BUILD_CMD[@]}" -fsanitize=thread - 2> /dev/null; then
1094		echo "--enable-tsan requires libtsan."
1095		echo "Please install then re-run this script."
1096		exit 1
1097	fi
1098fi
1099
1100if echo -e '#include <stdlib.h>\nint main(void) { arc4random(); return 0; }\n' \
1101	| "${BUILD_CMD[@]}" - 2> /dev/null; then
1102	CONFIG[HAVE_ARC4RANDOM]="y"
1103fi
1104
1105if [[ "${CONFIG[OCF]}" = "y" ]]; then
1106	# If OCF_PATH is a file, assume it is a library and use it to compile with
1107	if [ -f ${CONFIG[OCF_PATH]} ]; then
1108		CONFIG[CUSTOMOCF]=y
1109	else
1110		CONFIG[CUSTOMOCF]=n
1111	fi
1112fi
1113
1114if [[ "${CONFIG[PGO_CAPTURE]}" = "y" && "${CONFIG[PGO_USE]}" = "y" ]]; then
1115	echo "ERROR: --enable-pgo-capture and --enable-pgo-use are mutually exclusive."
1116	exit 1
1117elif [[ "${CONFIG[PGO_USE]}" = "y" ]]; then
1118	if [[ "$CC_TYPE" = "clang" ]]; then
1119		# For clang we need to run an extra step on gathered profiling data.
1120		echo "Generating suitable profile data"
1121		llvm-profdata merge -output=build/pgo/default.profdata build/pgo
1122	fi
1123fi
1124
1125if [[ "${CONFIG[URING]}" = "y" ]]; then
1126	if [[ -n "${CONFIG[URING_PATH]}" ]]; then
1127		if [ ! -d "${CONFIG[URING_PATH]}" ]; then
1128			echo "${CONFIG[URING_PATH]}: directory not found"
1129			exit 1
1130		fi
1131	elif ! echo -e '#include <liburing.h>\nint main(void) { return 0; }\n' \
1132		| "${BUILD_CMD[@]}" -luring - 2> /dev/null; then
1133		echo "--with-uring requires liburing."
1134		echo "Please build and install then re-run this script."
1135		exit 1
1136	fi
1137fi
1138
1139if [[ "${CONFIG[URING_ZNS]}" = "y" ]]; then
1140	if [[ "${CONFIG[URING]}" = "n" ]]; then
1141		echo "--with-uring-zns requires --with-uring."
1142		exit 1
1143	fi
1144	if ! echo -e '#include<linux/blkzoned.h>\nint main(void) { return BLK_ZONE_REP_CAPACITY; }\n' \
1145		| "${BUILD_CMD[@]}" -c - 2> /dev/null; then
1146		echo "--with-uring-zns requires blkzoned.h (from kernel >= linux-5.9)."
1147		exit 1
1148	fi
1149fi
1150
1151if [[ "${CONFIG[FUSE]}" = "y" ]]; then
1152	if [[ ! -d /usr/include/fuse3 ]] && [[ ! -d /usr/local/include/fuse3 ]]; then
1153		echo "--with-fuse requires libfuse3."
1154		echo "Please install then re-run this script."
1155		exit 1
1156	fi
1157fi
1158
1159if [ "${CONFIG[CET]}" = "y" ]; then
1160	if ! echo -e 'int main(void) { return 0; }\n' | "${BUILD_CMD[@]}" -fcf-protection - 2> /dev/null; then
1161		echo "--enable-cet requires compiler/linker that supports CET."
1162		echo "Please install then re-run this script."
1163		exit 1
1164	fi
1165fi
1166
1167if [[ "${CONFIG[FUZZER]}" = "y" && "$CC_TYPE" != "clang" ]]; then
1168	echo "--with-fuzzer requires setting CC and CXX to clang."
1169	exit 1
1170fi
1171
1172if [[ "${CONFIG[ISAL]}" = "y" ]]; then
1173	if [ ! -f "$rootdir"/isa-l/autogen.sh ]; then
1174		echo "ISA-L was not found; To install ISA-L run:"
1175		echo "  git submodule update --init"
1176		exit 1
1177	fi
1178
1179	cd $rootdir/isa-l
1180	ISAL_LOG=$rootdir/isa-l/spdk-isal.log
1181	if [[ -n "${CONFIG[CROSS_PREFIX]}" ]]; then
1182		ISAL_OPTS=("--host=${CONFIG[CROSS_PREFIX]}")
1183	else
1184		ISAL_OPTS=()
1185	fi
1186	echo -n "Configuring ISA-L (logfile: $ISAL_LOG)..."
1187	./autogen.sh &> $ISAL_LOG
1188	./configure CFLAGS="-fPIC -g -O2" "${ISAL_OPTS[@]}" --enable-shared=no >> $ISAL_LOG 2>&1
1189	echo "done."
1190	cd $rootdir
1191fi
1192
1193if [[ "${CONFIG[SMA]}" = "y" ]]; then
1194	if ! python3 -c 'import grpc; import grpc_tools' 2> /dev/null; then
1195		echo "--with-sma requires grpcio and grpcio-tools python packages."
1196		echo "Please install then re-run this script."
1197		exit 1
1198	fi
1199fi
1200
1201# For ARM Neoverse-N1 platform, debug build needs gcc version newer than 8.4
1202if [[ "${CONFIG[DEBUG]}" = "y" && $arch = aarch64* && "$CC_TYPE" = "gcc" ]]; then
1203	GCC_VERSION=$($CC -dumpfullversion)
1204	PART_NUM=$(grep -i -m 1 "CPU part" /proc/cpuinfo | awk '{print $4}')
1205
1206	if [[ "$(printf '%s\n' "8.4.0" "$GCC_VERSION" | sort -V | head -n1)" != "8.4.0" ]]; then
1207		if [[ $PART_NUM = 0xd0c ]]; then
1208			echo "WARNING: For ARM Neoverse-N1 platform, debug build needs GCC version newer than 8.4."
1209			echo "         Will work around this by using armv8.2-a+crypto as target architecture for now."
1210			CONFIG[ARCH]=armv8.2-a+crypto
1211		fi
1212	fi
1213fi
1214
1215# We are now ready to generate final configuration. But first do sanity
1216# check to see if all keys in CONFIG array have its reflection in CONFIG file.
1217if (($(grep -cE "^\s*CONFIG_[[:alnum:]_]+=" "$rootdir/CONFIG") != ${#CONFIG[@]})); then
1218	echo ""
1219	echo "BUG: Some configuration options are not present in CONFIG file. Please update this file."
1220	echo "Missing options in CONFIG (+) file and in current config (-): "
1221	diff -u --label "CONFIG file" --label "CONFIG[@]" \
1222		<(sed -r -e '/^[[:space:]]*$/d; /^[[:space:]]*#.*/d; s/(CONFIG_[[:alnum:]_]+)=.*/\1/g' CONFIG | sort) \
1223		<(printf "CONFIG_%s\n" "${!CONFIG[@]}" | sort)
1224	exit 1
1225fi
1226
1227echo -n "Creating mk/config.mk..."
1228cp -f $rootdir/CONFIG $rootdir/mk/config.mk
1229for key in "${!CONFIG[@]}"; do
1230	sed -i.bak -r "s#[[:space:]]*CONFIG_${key}=.*#CONFIG_${key}\?=${CONFIG[$key]}#g" $rootdir/mk/config.mk
1231done
1232# On FreeBSD sed -i 'SUFFIX' - SUFFIX is mandatory. So no way but to delete the backed file.
1233rm -f $rootdir/mk/config.mk.bak
1234echo "done."
1235
1236# Environment variables
1237echo -n "Creating mk/cc.flags.mk..."
1238rm -f $rootdir/mk/cc.flags.mk
1239[ -n "$CFLAGS" ] && echo "CFLAGS?=$CFLAGS" > $rootdir/mk/cc.flags.mk
1240[ -n "$CXXFLAGS" ] && echo "CXXFLAGS?=$CXXFLAGS" >> $rootdir/mk/cc.flags.mk
1241[ -n "$LDFLAGS" ] && echo "LDFLAGS?=$LDFLAGS" >> $rootdir/mk/cc.flags.mk
1242[ -n "$DESTDIR" ] && echo "DESTDIR?=$DESTDIR" >> $rootdir/mk/cc.flags.mk
1243echo "done."
1244
1245# Create .sh with build config for easy sourcing|lookup during the tests.
1246for conf in "${!CONFIG[@]}"; do
1247	echo "CONFIG_$conf=${CONFIG[$conf]}"
1248done > "$rootdir/test/common/build_config.sh"
1249
1250if [[ $sys_name == "FreeBSD" ]]; then
1251	echo "Type 'gmake' to build."
1252else
1253	echo "Type 'make' to build."
1254fi
1255
1256exit 0
1257