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