xref: /spdk/configure (revision e21c39aa707f29bcf6e1cb1989083b9cca3d9849)
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	if [[ "${CONFIG[COVERAGE]}" == "y" ]]; then
840		echo "ERROR: CONFIG_COVERAGE not available on FreeBSD"
841		exit 1
842	fi
843	CONFIG[FSDEV]=n
844fi
845
846if [[ $sys_name == "Linux" ]]; then
847	if pkg-config libbsd; then
848		CONFIG[HAVE_LIBBSD]=y
849	fi
850fi
851
852if pkg-config libarchive; then
853	CONFIG[HAVE_LIBARCHIVE]=y
854fi
855
856if [[ $sys_name != "Linux" ]]; then
857	if [[ "${CONFIG[VHOST]}" == "y" ]]; then
858		echo "Vhost is only supported on Linux."
859		exit 1
860	fi
861	if [[ "${CONFIG[VIRTIO]}" == "y" ]]; then
862		echo "Virtio is only supported on Linux."
863		exit 1
864	fi
865fi
866
867if [ "${CONFIG[RDMA]}" = "y" ]; then
868	if [[ ! "${CONFIG[RDMA_PROV]}" == "verbs" ]] && [[ ! "${CONFIG[RDMA_PROV]}" == "mlx5_dv" ]]; then
869		echo "Invalid RDMA provider specified, must be \"verbs\" or \"mlx5_dv\""
870		exit 1
871	fi
872
873	if ! echo -e '#include <infiniband/verbs.h>\n#include <rdma/rdma_verbs.h>\n' \
874		'int main(void) { return 0; }\n' \
875		| "${BUILD_CMD[@]}" -libverbs -lrdmacm - 2> /dev/null; then
876		echo "--with-rdma requires libverbs and librdmacm."
877		echo "Please install then re-run this script."
878		exit 1
879	fi
880
881	if echo -e '#include <infiniband/verbs.h>\n' \
882		'int main(void) { return !!IBV_WR_SEND_WITH_INV; }\n' \
883		| "${BUILD_CMD[@]}" -c - 2> /dev/null; then
884		CONFIG[RDMA_SEND_WITH_INVAL]="y"
885	else
886		CONFIG[RDMA_SEND_WITH_INVAL]="n"
887		echo "
888*******************************************************************************
889WARNING: The Infiniband Verbs opcode Send With Invalidate is either not
890supported or is not functional with the current version of libibverbs installed
891on this system. Please upgrade to at least version 1.1.
892
893Beginning with Linux kernel 4.14, the kernel NVMe-oF initiator leverages Send
894With Invalidate RDMA operations to improve performance. Failing to use the
895Send With Invalidate operation on the NVMe-oF target side results in full
896functionality, but greatly reduced performance. The SPDK NVMe-oF target will
897be unable to leverage that operation using the currently installed version
898of libibverbs, so Linux kernel NVMe-oF initiators based on kernels greater
899than or equal to 4.14 will see significantly reduced performance.
900*******************************************************************************"
901	fi
902
903	if echo -e '#include <rdma/rdma_cma.h>\n' \
904		'int main(void) { return !!RDMA_OPTION_ID_ACK_TIMEOUT; }\n' \
905		| "${BUILD_CMD[@]}" -c - 2> /dev/null; then
906		CONFIG[RDMA_SET_ACK_TIMEOUT]="y"
907	else
908		CONFIG[RDMA_SET_ACK_TIMEOUT]="n"
909		echo "RDMA_OPTION_ID_ACK_TIMEOUT is not supported"
910	fi
911
912	if echo -e '#include <rdma/rdma_cma.h>\n' \
913		'int main(void) { return !!RDMA_OPTION_ID_TOS; }\n' \
914		| "${BUILD_CMD[@]}" -c - 2> /dev/null; then
915		CONFIG[RDMA_SET_TOS]="y"
916	else
917		CONFIG[RDMA_SET_TOS]="n"
918		echo "RDMA_OPTION_ID_TOS is not supported"
919	fi
920
921	if [ "${CONFIG[RDMA_PROV]}" == "mlx5_dv" ]; then
922		MLX5_DV_BUILD_BUILD_CMD="
923		#include <infiniband/mlx5dv.h>\n
924		#include <rdma/rdma_cma.h>\n
925		int main(void) { return rdma_establish(NULL) ||\n
926		!!IBV_QP_INIT_ATTR_SEND_OPS_FLAGS || !!MLX5_OPCODE_RDMA_WRITE"
927		if [ "${CONFIG[CRYPTO]}" = "y" ]; then
928			MLX5_DV_BUILD_BUILD_CMD+="|| !!MLX5DV_CRYPTO_ENGINES_CAP_AES_XTS_SINGLE_BLOCK"
929		fi
930		MLX5_DV_BUILD_BUILD_CMD+=";}"
931		if ! echo -e $MLX5_DV_BUILD_BUILD_CMD | "${BUILD_CMD[@]}" -lmlx5 -I${rootdir}/include -c -; then
932			echo "mlx5_dv provider is not supported"
933			exit 1
934		fi
935	fi
936
937	echo "Using '${CONFIG[RDMA_PROV]}' RDMA provider"
938fi
939
940if [[ "${CONFIG[FC]}" = "y" ]]; then
941	if [[ -n "${CONFIG[FC_PATH]}" ]]; then
942		check_dir "${CONFIG[FC_PATH]}"
943	fi
944fi
945
946function dpdk_version() {
947	# Check DPDK version to determine if mlx5_pci driver is supported
948	local dpdk_ver="none"
949	if [[ "${CONFIG[DPDK_DIR]}" == "$rootdir/dpdk/build" ]]; then
950		# DPDK_DIR points at our submodule so ./build may not exist yet. Use
951		# absolute path to lookup the version.
952		dpdk_ver=$(< "$rootdir/dpdk/VERSION")
953	elif [[ -f "${CONFIG[DPDK_DIR]}"/../VERSION ]]; then
954		dpdk_ver=$(< "${CONFIG[DPDK_DIR]}"/../VERSION)
955	fi
956	echo $dpdk_ver
957}
958
959function mlx5_build() {
960	# Check if libmlx5 exists to enable mlx5_pci compress/crypto PMD
961	if ! echo -e '#include <spdk/stdinc.h>\n' \
962		'#include <infiniband/mlx5dv.h>\n' \
963		'#include <infiniband/verbs.h>\n' \
964		'int main(void) { return 0; }\n' \
965		| "${BUILD_CMD[@]}" -lmlx5 -libverbs -I${rootdir}/include -c - 2> /dev/null; then
966		return 1
967	fi
968	return 0
969}
970
971if [[ "${CONFIG[VBDEV_COMPRESS]}" = "y" ]]; then
972	if ! echo -e '#include <libpmem.h>\nint main(void) { return 0; }\n' \
973		| "${BUILD_CMD[@]}" -lpmem - 2> /dev/null; then
974		echo "--with-vbdev-compress requires libpmem."
975		echo "Please install then re-run this script."
976		exit 1
977	fi
978	# Try to enable mlx5 compress
979	CONFIG[VBDEV_COMPRESS_MLX5]="y"
980
981	# Check if libmlx5 exists to enable mlx5_pci compress PMD
982	if ! mlx5_build; then
983		echo "libmlx5 is not found, so disabling DPDK mlx5_pci compress PMD"
984		CONFIG[VBDEV_COMPRESS_MLX5]="n"
985	else
986		if [[ "${CONFIG[DPDK_PKG_CONFIG]}" = "y" ]]; then
987			# Check if librte_compress_mlx5 exists in DPDK package
988			if [ ! -f "${CONFIG[DPDK_LIB_DIR]}"/librte_compress_mlx5.so ]; then
989				echo "librte_compress_mlx5 is not found, so disabling DPDK mlx5_pci compress PMD"
990				CONFIG[VBDEV_COMPRESS_MLX5]="n"
991			fi
992		else
993			# Check DPDK version to determine if mlx5_pci driver is supported
994			dpdk_ver=$(dpdk_version)
995			if [[ $dpdk_ver = "none" ]]; then
996				echo "Cannot get DPDK version, so disabling DPDK mlx5_pci compress PMD"
997				CONFIG[VBDEV_COMPRESS_MLX5]="n"
998			elif [[ -n $dpdk_ver ]] && lt "$dpdk_ver" 21.02.0; then
999				# mlx5_pci for compress is supported by DPDK >- 21.02.0
1000				echo "DPDK version ${dpdk_ver} doesn't support mlx5_pci compress PMD"
1001				CONFIG[VBDEV_COMPRESS_MLX5]="n"
1002			elif [[ -n ${CONFIG[DPDK_LIB_DIR]} ]] && [ ! -f "${CONFIG[DPDK_LIB_DIR]}"/librte_compress_mlx5.so ]; then
1003				# This is only checked when --with-dpdk or --with-dpdk=* is used
1004				echo "librte_compress_mlx5 is not found, so disabling DPDK mlx5_pci compress PMD"
1005				CONFIG[VBDEV_COMPRESS_MLX5]="n"
1006			fi
1007		fi
1008	fi
1009fi
1010
1011if [[ "${CONFIG[CRYPTO]}" = "y" ]]; then
1012	# Try to enable mlx5 crypto
1013	CONFIG[CRYPTO_MLX5]="y"
1014
1015	# Check if libmlx5 exists to enable mlx5_pci compress PMD
1016	if ! mlx5_build; then
1017		echo "libmlx5 is not found, so disabling DPDK mlx5_pci crypto PMD"
1018		CONFIG[CRYPTO_MLX5]="n"
1019	else
1020		if [[ "${CONFIG[DPDK_PKG_CONFIG]}" = "y" ]]; then
1021			# Check if librte_crypto_mlx5 exists in DPDK package
1022			if [ ! -f "${CONFIG[DPDK_LIB_DIR]}"/librte_crypto_mlx5.so ]; then
1023				echo "librte_crypto_mlx5 is not found, so disabling DPDK mlx5_pci crypto PMD"
1024				CONFIG[CRYPTO_MLX5]="n"
1025			fi
1026		else
1027			# Check DPDK version to determine if mlx5_pci driver is supported
1028			dpdk_ver=$(dpdk_version)
1029			if [[ $dpdk_ver = "none" ]]; then
1030				echo "Cannot get DPDK version, so disabling DPDK mlx5_pci crypto PMD"
1031				CONFIG[CRYPTO_MLX5]="n"
1032			elif [[ -n $dpdk_ver ]] && lt "$dpdk_ver" 21.11.0; then
1033				# mlx5_pci for crypto is supported by DPDK >- 21.11.0
1034				echo "DPDK version ${dpdk_ver} doesn't support mlx5_pci crypto PMD"
1035				CONFIG[CRYPTO_MLX5]="n"
1036			elif [[ -n ${CONFIG[DPDK_LIB_DIR]} ]] && [ ! -f "${CONFIG[DPDK_LIB_DIR]}"/librte_crypto_mlx5.so ]; then
1037				# This is only checked when --with-dpdk or --with-dpdk=* is used
1038				echo "librte_crypto_mlx5 is not found, so disabling DPDK mlx5_pci crypto PMD"
1039				CONFIG[CRYPTO_MLX5]="n"
1040			fi
1041		fi
1042	fi
1043fi
1044
1045if [[ "${CONFIG[NVME_CUSE]}" = "y" ]]; then
1046	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' \
1047		| "${BUILD_CMD[@]}" -lfuse3 -D_FILE_OFFSET_BITS=64 - 2> /dev/null; then
1048		echo "--with-nvme-cuse requires libfuse3."
1049		echo "Please install then re-run this script."
1050		exit 1
1051	fi
1052fi
1053
1054if [[ "${CONFIG[RBD]}" = "y" ]]; then
1055	if ! echo -e '#include <rbd/librbd.h>\n#include <rados/librados.h>\n' \
1056		'int main(void) { return 0; }\n' \
1057		| "${BUILD_CMD[@]}" -lrados -lrbd - 2> /dev/null; then
1058		echo "--with-rbd requires librados and librbd."
1059		echo "Please install then re-run this script."
1060		exit 1
1061	fi
1062fi
1063
1064if [[ "${CONFIG[UBLK]}" = "y" ]]; then
1065	if ! echo -e '#include <linux/ublk_cmd.h>\n#include <liburing.h>\n' \
1066		'int main(void) { return 0; }\n' \
1067		| "${BUILD_CMD[@]}" -luring - 2> /dev/null; then
1068		echo "--with-ublk requires liburing and ublk_drv."
1069		echo "Please install then re-run this script."
1070		exit 1
1071	fi
1072fi
1073
1074if [[ "${CONFIG[DPDK_UADK]}" = "y" ]]; then
1075	if ! pkg-config --exists libwd; then
1076		echo "--with-dpdk-uadk requires uadk library."
1077		echo "Please install then re-run this script."
1078		exit 1
1079	fi
1080fi
1081
1082if [[ "${CONFIG[ISCSI_INITIATOR]}" = "y" ]]; then
1083	# Fedora installs libiscsi to /usr/lib64/iscsi for some reason.
1084	if ! echo -e '#include <iscsi/iscsi.h>\n#include <iscsi/scsi-lowlevel.h>\n' \
1085		'#if LIBISCSI_API_VERSION < 20150621\n' \
1086		'#error\n' \
1087		'#endif\n' \
1088		'int main(void) { return 0; }\n' \
1089		| "${BUILD_CMD[@]}" -L/usr/lib64/iscsi -liscsi - 2> /dev/null; then
1090		echo "--with-iscsi-initiator requires libiscsi with"
1091		echo "LIBISCSI_API_VERSION >= 20150621."
1092		echo "Please install then re-run this script."
1093		exit 1
1094	fi
1095fi
1096
1097if [[ "${CONFIG[DAOS]}" = "y" ]]; then
1098	daos_build_cmd=("${BUILD_CMD[@]}")
1099	if [[ -n "${CONFIG[DAOS_DIR]}" ]]; then
1100		daos_build_cmd+=(-I"${CONFIG[DAOS_DIR]}"/include -L"${CONFIG[DAOS_DIR]}"/lib64)
1101	fi
1102	if ! echo -e '#include <daos.h>\n#include <daos_fs.h>\n' \
1103		'int main(void) { return 0; }\n' \
1104		| "${daos_build_cmd[@]}" -lgurt -ldaos -ldaos_common -ldfs - 2> /dev/null; then
1105		echo "--with-daos requires libdaos, libdaos_common, libdfs and libgurt"
1106		echo "Please install then re-run this script."
1107		exit 1
1108	fi
1109fi
1110
1111if [[ "${CONFIG[ASAN]}" = "y" ]]; then
1112	if ! echo -e 'int main(void) { return 0; }\n' \
1113		| "${BUILD_CMD[@]}" -fsanitize=address - 2> /dev/null; then
1114		echo "--enable-asan requires libasan."
1115		echo "Please install then re-run this script."
1116		exit 1
1117	fi
1118fi
1119
1120if [[ "${CONFIG[UBSAN]}" = "y" ]]; then
1121	if ! echo -e 'int main(void) { return 0; }\n' \
1122		| "${BUILD_CMD[@]}" -fsanitize=undefined - 2> /dev/null; then
1123		echo "--enable-ubsan requires libubsan."
1124		echo "Please install then re-run this script."
1125		echo "If installed, please check that the GCC version is at least 6.4"
1126		echo "and synchronize CC accordingly."
1127		exit 1
1128	fi
1129fi
1130
1131if [[ "${CONFIG[TSAN]}" = "y" ]]; then
1132	if ! echo -e 'int main(void) { return 0; }\n' \
1133		| "${BUILD_CMD[@]}" -fsanitize=thread - 2> /dev/null; then
1134		echo "--enable-tsan requires libtsan."
1135		echo "Please install then re-run this script."
1136		exit 1
1137	fi
1138fi
1139
1140if echo -e '#include <stdlib.h>\nint main(void) { arc4random(); return 0; }\n' \
1141	| "${BUILD_CMD[@]}" - 2> /dev/null; then
1142	CONFIG[HAVE_ARC4RANDOM]="y"
1143fi
1144
1145if echo -e '#include <uuid/uuid.h>\nint main(void) { uuid_generate_sha1(NULL, NULL, NULL, 0); return 0; }\n' \
1146	| "${BUILD_CMD[@]}" - -luuid 2> /dev/null; then
1147	CONFIG[HAVE_UUID_GENERATE_SHA1]="y"
1148fi
1149
1150if echo -e '#include <execinfo.h>' | "${BUILD_CMD[@]}" -c - 2> /dev/null; then
1151	CONFIG[HAVE_EXECINFO_H]=y
1152fi
1153
1154if echo -e '#include <keyutils.h>\nint main(void) { request_key(0, 0, 0, -1); return 0; }' \
1155	| "${BUILD_CMD[@]}" - -lkeyutils 2> /dev/null; then
1156	CONFIG[HAVE_KEYUTILS]=y
1157fi
1158
1159if echo -e '#include <openssl/evp.h>\nint main(void) { EVP_MAC *m = EVP_MAC_fetch(0, 0, 0); return 0; }' \
1160	| "${BUILD_CMD[@]}" - -lcrypto 2> /dev/null; then
1161	CONFIG[HAVE_EVP_MAC]=y
1162fi
1163
1164if [[ "${CONFIG[OCF]}" = "y" ]]; then
1165	# If OCF_PATH is a file, assume it is a library and use it to compile with
1166	if [ -f ${CONFIG[OCF_PATH]} ]; then
1167		CONFIG[CUSTOMOCF]=y
1168	else
1169		CONFIG[CUSTOMOCF]=n
1170	fi
1171fi
1172
1173if [[ "${CONFIG[PGO_CAPTURE]}" = "y" && "${CONFIG[PGO_USE]}" = "y" ]]; then
1174	echo "ERROR: --enable-pgo-capture and --enable-pgo-use are mutually exclusive."
1175	exit 1
1176elif [[ "${CONFIG[PGO_CAPTURE]}" = "y" || "${CONFI[PGO_USE]}" = "y" ]]; then
1177	if [[ -z "${CONFIG[PGO_DIR]}" ]]; then
1178		CONFIG[PGO_DIR]=$(realpath $rootdir/build/pgo)
1179	fi
1180fi
1181
1182if [[ "${CONFIG[PGO_USE]}" = "y" ]]; then
1183	if [[ "$CC_TYPE" = "clang" ]]; then
1184		# For clang we need to run an extra step on gathered profiling data.
1185		echo "Generating suitable profile data"
1186		llvm-profdata merge -output=${CONFIG[PGO_DIR]}/default.profdata ${CONFIG[PGO_DIR]}
1187	fi
1188fi
1189
1190if [[ "${CONFIG[URING]}" = "y" || "${CONFIG[XNVME]}" = "y" ]]; then
1191	if [[ -n "${CONFIG[URING_PATH]}" ]]; then
1192		check_dir "${CONFIG[URING_PATH]}"
1193	elif ! echo -e '#include <liburing.h>\nint main(void) { return 0; }\n' \
1194		| "${BUILD_CMD[@]}" -luring - 2> /dev/null; then
1195		echo "--with-uring requires liburing."
1196		echo "Please build and install then re-run this script."
1197		exit 1
1198	fi
1199	# Support for Zoned devices is enabled by default for Uring bdev. Check appropriate support in kernel.
1200	if [[ "${CONFIG[URING_ZNS]}" = "y" ]]; then
1201		if ! echo -e '#include<linux/blkzoned.h>\nint main(void) { return BLK_ZONE_REP_CAPACITY; }\n' \
1202			| "${BUILD_CMD[@]}" -c - 2> /dev/null; then
1203			echo "Disabling Zoned NS support in Uring! Requires blkzoned.h from kernel >= linux-5.9."
1204			CONFIG[URING_ZNS]=n
1205		fi
1206	fi
1207fi
1208
1209if [[ "${CONFIG[FUSE]}" = "y" ]]; then
1210	if [[ ! -d /usr/include/fuse3 ]] && [[ ! -d /usr/local/include/fuse3 ]]; then
1211		echo "--with-fuse requires libfuse3."
1212		echo "Please install then re-run this script."
1213		exit 1
1214	fi
1215fi
1216
1217if [ "${CONFIG[CET]}" = "y" ]; then
1218	if ! echo -e 'int main(void) { return 0; }\n' | "${BUILD_CMD[@]}" -fcf-protection - 2> /dev/null; then
1219		echo "--enable-cet requires compiler/linker that supports CET."
1220		echo "Please install then re-run this script."
1221		exit 1
1222	fi
1223fi
1224
1225if [[ "${CONFIG[FUZZER]}" = "y" && "$CC_TYPE" != "clang" ]]; then
1226	echo "--with-fuzzer requires setting CC and CXX to clang."
1227	exit 1
1228fi
1229
1230if [[ $arch == x86_64* ]] || [[ $arch == aarch64* ]]; then
1231	CONFIG[ISAL]=y
1232	# make sure the submodule is initialized
1233	if [ ! -f "$rootdir"/isa-l/autogen.sh ]; then
1234		echo "ISA-L is required but was not found, please init the submodule with:"
1235		echo "  git submodule update --init"
1236		echo "and then re-run this script."
1237		exit 1
1238	fi
1239	# for x86 only, check the nasm version for ISA-L and IPSEC
1240	if [[ $arch == x86_64* ]]; then
1241		ver=$(nasm -v 2> /dev/null | awk '{print $3}' | awk -Fr '{print $1}')
1242		if lt "$ver" 2.14; then
1243			CONFIG[ISAL]=n
1244			# IPSEC has nasm requirement and DPDK crypto relies on IPSEC
1245			CONFIG[IPSEC_MB]=n
1246			echo "WARNING: ISA-L & DPDK crypto cannot be used as nasm ver must be 2.14 or newer."
1247		fi
1248	fi
1249	# check gas version on aarch64
1250	if [[ $arch == aarch64* ]]; then
1251		ver=$(as --version 2> /dev/null | awk '/GNU assembler/{print $NF}')
1252		if lt "$ver" 2.24; then
1253			# ISA-L, compression & crypto require gas version 2.24 or newer.
1254			CONFIG[ISAL]=n
1255			echo "Notice: ISA-L, compression & crypto require GAS version 2.24 or newer. Turning off default ISA-L and crypto features."
1256		elif lt "$ver" 2.34; then
1257			#For gas v2.24~v2.34, sve2 instructions are not supported. To workaround it, sve2 optimization should be disabled
1258			ISAL_CRYPTO_OPTS+=("--disable-sve2")
1259		fi
1260	fi
1261else
1262	# for PPC
1263	CONFIG[ISAL]=n
1264	echo "WARNING: ISA-L cannot be used due to architecture incompatibility."
1265fi
1266
1267# now either configure ISA-L or disable unavailable features
1268if [[ "${CONFIG[ISAL]}" = "y" ]]; then
1269	cd $rootdir/isa-l
1270	ISAL_LOG=$rootdir/.spdk-isal.log
1271	if [[ -n "${CONFIG[CROSS_PREFIX]}" ]]; then
1272		ISAL_OPTS=("--host=${CONFIG[CROSS_PREFIX]}")
1273	else
1274		ISAL_OPTS=()
1275	fi
1276	if [[ "${CONFIG[SHARED]}" = "y" ]]; then
1277		ISAL_OPTS+=("--enable-shared=yes")
1278	else
1279		ISAL_OPTS+=("--enable-shared=no")
1280	fi
1281	ISAL_OPTS+=("--prefix=${CONFIG[PREFIX]}")
1282	echo -n "Configuring ISA-L (logfile: $ISAL_LOG)..."
1283	./autogen.sh &> $ISAL_LOG
1284	./configure CFLAGS="-fPIC -g -O2 -fuse-ld=$LD_TYPE -Wno-unused-command-line-argument" "${ISAL_OPTS[@]}" --enable-shared=no >> $ISAL_LOG 2>&1
1285	echo "done."
1286	cd $rootdir
1287else
1288	echo "Without ISA-L, there is no software support for crypto or compression,"
1289	echo "so these features will be disabled."
1290	CONFIG[CRYPTO]=n
1291	CONFIG[VBDEV_COMPRESS]=n
1292	CONFIG[DPDK_COMPRESSDEV]=n
1293fi
1294
1295# ISA-L-crypto complements ISA-L functionality, it is only enabled together with ISA-L
1296if [[ "${CONFIG[ISAL]}" = "y" ]]; then
1297	if [ ! -f "$rootdir"/isa-l-crypto/autogen.sh ]; then
1298		echo "ISA-L-crypto is required but was not found, please init the submodule with:"
1299		echo "  git submodule update --init"
1300		echo "and then re-run this script."
1301		exit 1
1302	fi
1303
1304	cd $rootdir/isa-l-crypto
1305	ISAL_CRYPTO_LOG=$rootdir/.spdk-isal-crypto.log
1306	if [[ -n "${CONFIG[CROSS_PREFIX]}" ]]; then
1307		ISAL_CRYPTO_OPTS+=("--host=${CONFIG[CROSS_PREFIX]}")
1308	fi
1309	if [[ "${CONFIG[SHARED]}" = "y" ]]; then
1310		ISAL_CRYPTO_OPTS+=("--enable-shared=yes")
1311	else
1312		ISAL_CRYPTO_OPTS+=("--enable-shared=no")
1313	fi
1314	ISAL_CRYPTO_OPTS+=("--prefix=${CONFIG[PREFIX]}")
1315	echo -n "Configuring ISA-L-crypto (logfile: $ISAL_CRYPTO_LOG)..."
1316	./autogen.sh &> $ISAL_CRYPTO_LOG
1317	./configure CFLAGS="-fPIC -g -O2 -fuse-ld=$LD_TYPE -Wno-unused-command-line-argument" "${ISAL_CRYPTO_OPTS[@]}" >> $ISAL_CRYPTO_LOG 2>&1
1318	echo "done."
1319	cd $rootdir
1320	CONFIG[ISAL_CRYPTO]=y
1321else
1322	CONFIG[ISAL_CRYPTO]=n
1323fi
1324
1325if [[ "${CONFIG[SMA]}" = "y" ]]; then
1326	if ! python3 -c 'import grpc; import grpc_tools' 2> /dev/null; then
1327		echo "--with-sma requires grpcio and grpcio-tools python packages."
1328		echo "Please install then re-run this script."
1329		exit 1
1330	fi
1331fi
1332
1333if [[ "${CONFIG[AVAHI]}" = "y" ]]; then
1334	if ! echo -e '#include <avahi-client/client.h>\n#include <avahi-common/malloc.h>\n' \
1335		'int main(void) { return 0; }\n' \
1336		| "${BUILD_CMD[@]}" -lavahi-client -lavahi-common - 2> /dev/null; then
1337		echo "--with-avahi requires libavahi-client and libavahi-common."
1338		echo "Please install then re-run this script."
1339		exit 1
1340	fi
1341fi
1342
1343if [[ "${CONFIG[GOLANG]}" = "y" ]]; then
1344	if ! go version 2> /dev/null; then
1345		echo "--with-golang requires Go installation."
1346		echo "Please install then re-run this script."
1347		exit 1
1348	fi
1349fi
1350
1351if [[ -n ${CONFIG[MAX_LCORES]} ]]; then
1352	if [[ ! ${CONFIG[MAX_LCORES]} =~ ^([1-9][0-9]*|detect)$ ]] || ((CONFIG[MAX_LCORES] > 1024)); then
1353		echo "ERROR: Max number of lcores must be a decimal number in range [1..1024] or 'detect' (given: ${CONFIG[MAX_LCORES]})"
1354		exit 1
1355	fi
1356fi
1357
1358if [[ "${CONFIG[FSDEV]}" = "n" ]]; then
1359	if [[ "$AIO_FSDEV_REQUIRED" = "y" ]]; then
1360		echo "ERROR: --with-aio-fsdev cannot be specified as fsdev is disabled."
1361		exit 1
1362	fi
1363
1364	# if AIO_FSDEV is not explicitly required by user, we just silently disable it
1365	CONFIG[AIO_FSDEV]=n
1366fi
1367
1368if [[ "${CONFIG[AIO_FSDEV]}" = "y" ]]; then
1369	if echo -e '#define _GNU_SOURCE\n#include <unistd.h>\n' \
1370		'int main(void) { return copy_file_range(0, 0, 0, 0, 0, 0); }\n' \
1371		| "${BUILD_CMD[@]}" - 2> /dev/null; then
1372		CONFIG[COPY_FILE_RANGE]=y
1373	else
1374		CONFIG[COPY_FILE_RANGE]=n
1375	fi
1376	if echo -e '#include <sys/stat.h>\n' \
1377		'int main(void) { struct stat s; s.st_atime = s.st_atime; return 0 ;}\n' \
1378		| "${BUILD_CMD[@]}" - 2> /dev/null; then
1379		CONFIG[HAVE_STRUCT_STAT_ST_ATIM]=y
1380		CONFIG[HAVE_STRUCT_STAT_ST_ATIMESPEC]=n
1381	elif echo -e '#include <sys/stat.h>\n' \
1382		'int main(void) { struct stat s; s.st_atimespec = s.st_atimespec; return 0; }\n' \
1383		| "${BUILD_CMD[@]}" - 2> /dev/null; then
1384		CONFIG[HAVE_STRUCT_STAT_ST_ATIM]=n
1385		CONFIG[HAVE_STRUCT_STAT_ST_ATIMESPEC]=y
1386	else
1387		CONFIG[HAVE_STRUCT_STAT_ST_ATIM]=n
1388		CONFIG[HAVE_STRUCT_STAT_ST_ATIMESPEC]=n
1389	fi
1390fi
1391
1392# For ARM Neoverse-N1 platform, debug build needs gcc version newer than 8.4
1393if [[ "${CONFIG[DEBUG]}" = "y" && $arch = aarch64* && "$CC_TYPE" = "gcc" ]]; then
1394	GCC_VERSION=$($CC -dumpfullversion)
1395	PART_NUM=$(grep -i -m 1 "CPU part" /proc/cpuinfo | awk '{print $4}')
1396
1397	if [[ "$(printf '%s\n' "8.4.0" "$GCC_VERSION" | sort -V | head -n1)" != "8.4.0" ]]; then
1398		if [[ $PART_NUM = 0xd0c ]]; then
1399			echo "WARNING: For ARM Neoverse-N1 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		elif [[ $PART_NUM = 0x0b2 ]]; then
1403			echo "WARNING: For ARM octeontx2 platform, debug build needs GCC version newer than 8.4."
1404			echo "         Will work around this by using armv8.2-a+crypto as target architecture for now."
1405			CONFIG[ARCH]=armv8.2-a+crypto
1406		fi
1407	fi
1408fi
1409
1410# We are now ready to generate final configuration. But first do sanity
1411# check to see if all keys in CONFIG array have its reflection in CONFIG file.
1412if (($(grep -cE "^\s*CONFIG_[[:alnum:]_]+=" "$rootdir/CONFIG") != ${#CONFIG[@]})); then
1413	echo ""
1414	echo "BUG: Some configuration options are not present in CONFIG file. Please update this file."
1415	echo "Missing options in CONFIG (+) file and in current config (-): "
1416	diff -u --label "CONFIG file" --label "CONFIG[@]" \
1417		<(sed -r -e '/^[[:space:]]*$/d; /^[[:space:]]*#.*/d; s/(CONFIG_[[:alnum:]_]+)=.*/\1/g' CONFIG | sort) \
1418		<(printf "CONFIG_%s\n" "${!CONFIG[@]}" | sort)
1419	exit 1
1420fi
1421
1422echo -n "Creating mk/config.mk..."
1423cp -f $rootdir/CONFIG $rootdir/mk/config.mk
1424ARGS=$(echo "$@" | sed 's/ /\\ /g')
1425sed -i.bak -r "s#__CONFIGURE_OPTIONS__#${ARGS}#g" $rootdir/mk/config.mk
1426for key in "${!CONFIG[@]}"; do
1427	sed -i.bak -r "s#[[:space:]]*CONFIG_${key}=.*#CONFIG_${key}\?=${CONFIG[$key]}#g" $rootdir/mk/config.mk
1428done
1429# On FreeBSD sed -i 'SUFFIX' - SUFFIX is mandatory. So no way but to delete the backed file.
1430rm -f $rootdir/mk/config.mk.bak
1431echo "done."
1432
1433# Environment variables
1434echo -n "Creating mk/cc.flags.mk..."
1435rm -f $rootdir/mk/cc.flags.mk
1436[ -n "$CFLAGS" ] && echo "CFLAGS?=$CFLAGS" > $rootdir/mk/cc.flags.mk
1437[ -n "$CXXFLAGS" ] && echo "CXXFLAGS?=$CXXFLAGS" >> $rootdir/mk/cc.flags.mk
1438[ -n "$LDFLAGS" ] && echo "LDFLAGS?=$LDFLAGS" >> $rootdir/mk/cc.flags.mk
1439[ -n "$DESTDIR" ] && echo "DESTDIR?=$DESTDIR" >> $rootdir/mk/cc.flags.mk
1440echo "done."
1441
1442# Create .sh with build config for easy sourcing|lookup during the tests.
1443for conf in "${!CONFIG[@]}"; do
1444	echo "CONFIG_$conf=${CONFIG[$conf]}"
1445done > "$rootdir/test/common/build_config.sh"
1446
1447if [[ $sys_name == "FreeBSD" ]]; then
1448	echo "Type 'gmake' to build."
1449else
1450	echo "Type 'make' to build."
1451fi
1452
1453exit 0
1454