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