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