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