xref: /spdk/configure (revision ee32a82bfd3ff5b1a10ed775ee06f0eaffce60eb)
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 echo -e '#include <lz4.h>\nint main(void) { return 0; }\n' \
1161	| "${BUILD_CMD[@]}" -llz4 - 2> /dev/null; then
1162	CONFIG[HAVE_LZ4]="y"
1163fi
1164
1165if [[ "${CONFIG[OCF]}" = "y" ]]; then
1166	# If OCF_PATH is a file, assume it is a library and use it to compile with
1167	if [ -f ${CONFIG[OCF_PATH]} ]; then
1168		CONFIG[CUSTOMOCF]=y
1169	else
1170		CONFIG[CUSTOMOCF]=n
1171	fi
1172fi
1173
1174if [[ "${CONFIG[PGO_CAPTURE]}" = "y" && "${CONFIG[PGO_USE]}" = "y" ]]; then
1175	echo "ERROR: --enable-pgo-capture and --enable-pgo-use are mutually exclusive."
1176	exit 1
1177elif [[ "${CONFIG[PGO_CAPTURE]}" = "y" || "${CONFI[PGO_USE]}" = "y" ]]; then
1178	if [[ -z "${CONFIG[PGO_DIR]}" ]]; then
1179		CONFIG[PGO_DIR]=$(realpath $rootdir/build/pgo)
1180	fi
1181fi
1182
1183if [[ "${CONFIG[PGO_USE]}" = "y" ]]; then
1184	if [[ "$CC_TYPE" = "clang" ]]; then
1185		# For clang we need to run an extra step on gathered profiling data.
1186		echo "Generating suitable profile data"
1187		llvm-profdata merge -output=${CONFIG[PGO_DIR]}/default.profdata ${CONFIG[PGO_DIR]}
1188	fi
1189fi
1190
1191if [[ "${CONFIG[URING]}" = "y" || "${CONFIG[XNVME]}" = "y" ]]; then
1192	if [[ -n "${CONFIG[URING_PATH]}" ]]; then
1193		check_dir "${CONFIG[URING_PATH]}"
1194	elif ! echo -e '#include <liburing.h>\nint main(void) { return 0; }\n' \
1195		| "${BUILD_CMD[@]}" -luring - 2> /dev/null; then
1196		echo "--with-uring requires liburing."
1197		echo "Please build and install then re-run this script."
1198		exit 1
1199	fi
1200	# Support for Zoned devices is enabled by default for Uring bdev. Check appropriate support in kernel.
1201	if [[ "${CONFIG[URING_ZNS]}" = "y" ]]; then
1202		if ! echo -e '#include<linux/blkzoned.h>\nint main(void) { return BLK_ZONE_REP_CAPACITY; }\n' \
1203			| "${BUILD_CMD[@]}" -c - 2> /dev/null; then
1204			echo "Disabling Zoned NS support in Uring! Requires blkzoned.h from kernel >= linux-5.9."
1205			CONFIG[URING_ZNS]=n
1206		fi
1207	fi
1208fi
1209
1210if [[ "${CONFIG[FUSE]}" = "y" ]]; then
1211	if [[ ! -d /usr/include/fuse3 ]] && [[ ! -d /usr/local/include/fuse3 ]]; then
1212		echo "--with-fuse requires libfuse3."
1213		echo "Please install then re-run this script."
1214		exit 1
1215	fi
1216fi
1217
1218if [ "${CONFIG[CET]}" = "y" ]; then
1219	if ! echo -e 'int main(void) { return 0; }\n' | "${BUILD_CMD[@]}" -fcf-protection - 2> /dev/null; then
1220		echo "--enable-cet requires compiler/linker that supports CET."
1221		echo "Please install then re-run this script."
1222		exit 1
1223	fi
1224fi
1225
1226if [[ "${CONFIG[FUZZER]}" = "y" && "$CC_TYPE" != "clang" ]]; then
1227	echo "--with-fuzzer requires setting CC and CXX to clang."
1228	exit 1
1229fi
1230
1231if [[ $arch == x86_64* ]] || [[ $arch == aarch64* ]]; then
1232	CONFIG[ISAL]=y
1233	# make sure the submodule is initialized
1234	if [ ! -f "$rootdir"/isa-l/autogen.sh ]; then
1235		echo "ISA-L is required but was not found, please init the submodule with:"
1236		echo "  git submodule update --init"
1237		echo "and then re-run this script."
1238		exit 1
1239	fi
1240	# for x86 only, check the nasm version for ISA-L and IPSEC
1241	if [[ $arch == x86_64* ]]; then
1242		ver=$(nasm -v 2> /dev/null | awk '{print $3}' | awk -Fr '{print $1}')
1243		if lt "$ver" 2.14; then
1244			CONFIG[ISAL]=n
1245			# IPSEC has nasm requirement and DPDK crypto relies on IPSEC
1246			CONFIG[IPSEC_MB]=n
1247			echo "WARNING: ISA-L & DPDK crypto cannot be used as nasm ver must be 2.14 or newer."
1248		fi
1249	fi
1250	# check gas version on aarch64
1251	if [[ $arch == aarch64* ]]; then
1252		ver=$(as --version 2> /dev/null | awk '/GNU assembler/{print $NF}')
1253		if lt "$ver" 2.24; then
1254			# ISA-L, compression & crypto require gas version 2.24 or newer.
1255			CONFIG[ISAL]=n
1256			echo "Notice: ISA-L, compression & crypto require GAS version 2.24 or newer. Turning off default ISA-L and crypto features."
1257		elif lt "$ver" 2.34; then
1258			#For gas v2.24~v2.34, sve2 instructions are not supported. To workaround it, sve2 optimization should be disabled
1259			ISAL_CRYPTO_OPTS+=("--disable-sve2")
1260		fi
1261	fi
1262else
1263	# for PPC
1264	CONFIG[ISAL]=n
1265	echo "WARNING: ISA-L cannot be used due to architecture incompatibility."
1266fi
1267
1268# now either configure ISA-L or disable unavailable features
1269if [[ "${CONFIG[ISAL]}" = "y" ]]; then
1270	cd $rootdir/isa-l
1271	ISAL_LOG=$rootdir/.spdk-isal.log
1272	if [[ -n "${CONFIG[CROSS_PREFIX]}" ]]; then
1273		ISAL_OPTS=("--host=${CONFIG[CROSS_PREFIX]}")
1274	else
1275		ISAL_OPTS=()
1276	fi
1277	if [[ "${CONFIG[SHARED]}" = "y" ]]; then
1278		ISAL_OPTS+=("--enable-shared=yes")
1279	else
1280		ISAL_OPTS+=("--enable-shared=no")
1281	fi
1282	ISAL_OPTS+=("--prefix=${CONFIG[PREFIX]}")
1283	echo -n "Configuring ISA-L (logfile: $ISAL_LOG)..."
1284	./autogen.sh &> $ISAL_LOG
1285	./configure CFLAGS="-fPIC -g -O2 -fuse-ld=$LD_TYPE -Wno-unused-command-line-argument" "${ISAL_OPTS[@]}" --enable-shared=no >> $ISAL_LOG 2>&1
1286	echo "done."
1287	cd $rootdir
1288else
1289	echo "Without ISA-L, there is no software support for crypto or compression,"
1290	echo "so these features will be disabled."
1291	CONFIG[CRYPTO]=n
1292	CONFIG[VBDEV_COMPRESS]=n
1293	CONFIG[DPDK_COMPRESSDEV]=n
1294fi
1295
1296# ISA-L-crypto complements ISA-L functionality, it is only enabled together with ISA-L
1297if [[ "${CONFIG[ISAL]}" = "y" ]]; then
1298	if [ ! -f "$rootdir"/isa-l-crypto/autogen.sh ]; then
1299		echo "ISA-L-crypto is required but was not found, please init the submodule with:"
1300		echo "  git submodule update --init"
1301		echo "and then re-run this script."
1302		exit 1
1303	fi
1304
1305	cd $rootdir/isa-l-crypto
1306	ISAL_CRYPTO_LOG=$rootdir/.spdk-isal-crypto.log
1307	if [[ -n "${CONFIG[CROSS_PREFIX]}" ]]; then
1308		ISAL_CRYPTO_OPTS+=("--host=${CONFIG[CROSS_PREFIX]}")
1309	fi
1310	if [[ "${CONFIG[SHARED]}" = "y" ]]; then
1311		ISAL_CRYPTO_OPTS+=("--enable-shared=yes")
1312	else
1313		ISAL_CRYPTO_OPTS+=("--enable-shared=no")
1314	fi
1315	ISAL_CRYPTO_OPTS+=("--prefix=${CONFIG[PREFIX]}")
1316	echo -n "Configuring ISA-L-crypto (logfile: $ISAL_CRYPTO_LOG)..."
1317	./autogen.sh &> $ISAL_CRYPTO_LOG
1318	./configure CFLAGS="-fPIC -g -O2 -fuse-ld=$LD_TYPE -Wno-unused-command-line-argument" "${ISAL_CRYPTO_OPTS[@]}" >> $ISAL_CRYPTO_LOG 2>&1
1319	echo "done."
1320	cd $rootdir
1321	CONFIG[ISAL_CRYPTO]=y
1322else
1323	CONFIG[ISAL_CRYPTO]=n
1324fi
1325
1326if [[ "${CONFIG[SMA]}" = "y" ]]; then
1327	if ! python3 -c 'import grpc; import grpc_tools' 2> /dev/null; then
1328		echo "--with-sma requires grpcio and grpcio-tools python packages."
1329		echo "Please install then re-run this script."
1330		exit 1
1331	fi
1332fi
1333
1334if [[ "${CONFIG[AVAHI]}" = "y" ]]; then
1335	if ! echo -e '#include <avahi-client/client.h>\n#include <avahi-common/malloc.h>\n' \
1336		'int main(void) { return 0; }\n' \
1337		| "${BUILD_CMD[@]}" -lavahi-client -lavahi-common - 2> /dev/null; then
1338		echo "--with-avahi requires libavahi-client and libavahi-common."
1339		echo "Please install then re-run this script."
1340		exit 1
1341	fi
1342fi
1343
1344if [[ "${CONFIG[GOLANG]}" = "y" ]]; then
1345	if ! go version 2> /dev/null; then
1346		echo "--with-golang requires Go installation."
1347		echo "Please install then re-run this script."
1348		exit 1
1349	fi
1350fi
1351
1352if [[ -n ${CONFIG[MAX_LCORES]} ]]; then
1353	if [[ ! ${CONFIG[MAX_LCORES]} =~ ^([1-9][0-9]*|detect)$ ]] || ((CONFIG[MAX_LCORES] > 1024)); then
1354		echo "ERROR: Max number of lcores must be a decimal number in range [1..1024] or 'detect' (given: ${CONFIG[MAX_LCORES]})"
1355		exit 1
1356	fi
1357fi
1358
1359if [[ "${CONFIG[FSDEV]}" = "n" ]]; then
1360	if [[ "$AIO_FSDEV_REQUIRED" = "y" ]]; then
1361		echo "ERROR: --with-aio-fsdev cannot be specified as fsdev is disabled."
1362		exit 1
1363	fi
1364
1365	# if AIO_FSDEV is not explicitly required by user, we just silently disable it
1366	CONFIG[AIO_FSDEV]=n
1367fi
1368
1369if [[ "${CONFIG[AIO_FSDEV]}" = "y" ]]; then
1370	if echo -e '#define _GNU_SOURCE\n#include <unistd.h>\n' \
1371		'int main(void) { return copy_file_range(0, 0, 0, 0, 0, 0); }\n' \
1372		| "${BUILD_CMD[@]}" - 2> /dev/null; then
1373		CONFIG[COPY_FILE_RANGE]=y
1374	else
1375		CONFIG[COPY_FILE_RANGE]=n
1376	fi
1377	if echo -e '#include <sys/stat.h>\n' \
1378		'int main(void) { struct stat s; s.st_atime = s.st_atime; return 0 ;}\n' \
1379		| "${BUILD_CMD[@]}" - 2> /dev/null; then
1380		CONFIG[HAVE_STRUCT_STAT_ST_ATIM]=y
1381		CONFIG[HAVE_STRUCT_STAT_ST_ATIMESPEC]=n
1382	elif echo -e '#include <sys/stat.h>\n' \
1383		'int main(void) { struct stat s; s.st_atimespec = s.st_atimespec; return 0; }\n' \
1384		| "${BUILD_CMD[@]}" - 2> /dev/null; then
1385		CONFIG[HAVE_STRUCT_STAT_ST_ATIM]=n
1386		CONFIG[HAVE_STRUCT_STAT_ST_ATIMESPEC]=y
1387	else
1388		CONFIG[HAVE_STRUCT_STAT_ST_ATIM]=n
1389		CONFIG[HAVE_STRUCT_STAT_ST_ATIMESPEC]=n
1390	fi
1391fi
1392
1393# For ARM Neoverse-N1 platform, debug build needs gcc version newer than 8.4
1394if [[ "${CONFIG[DEBUG]}" = "y" && $arch = aarch64* && "$CC_TYPE" = "gcc" ]]; then
1395	GCC_VERSION=$($CC -dumpfullversion)
1396	PART_NUM=$(grep -i -m 1 "CPU part" /proc/cpuinfo | awk '{print $4}')
1397
1398	if [[ "$(printf '%s\n' "8.4.0" "$GCC_VERSION" | sort -V | head -n1)" != "8.4.0" ]]; then
1399		if [[ $PART_NUM = 0xd0c ]]; then
1400			echo "WARNING: For ARM Neoverse-N1 platform, debug build needs GCC version newer than 8.4."
1401			echo "         Will work around this by using armv8.2-a+crypto as target architecture for now."
1402			CONFIG[ARCH]=armv8.2-a+crypto
1403		elif [[ $PART_NUM = 0x0b2 ]]; then
1404			echo "WARNING: For ARM octeontx2 platform, debug build needs GCC version newer than 8.4."
1405			echo "         Will work around this by using armv8.2-a+crypto as target architecture for now."
1406			CONFIG[ARCH]=armv8.2-a+crypto
1407		fi
1408	fi
1409fi
1410
1411# We are now ready to generate final configuration. But first do sanity
1412# check to see if all keys in CONFIG array have its reflection in CONFIG file.
1413if (($(grep -cE "^\s*CONFIG_[[:alnum:]_]+=" "$rootdir/CONFIG") != ${#CONFIG[@]})); then
1414	echo ""
1415	echo "BUG: Some configuration options are not present in CONFIG file. Please update this file."
1416	echo "Missing options in CONFIG (+) file and in current config (-): "
1417	diff -u --label "CONFIG file" --label "CONFIG[@]" \
1418		<(sed -r -e '/^[[:space:]]*$/d; /^[[:space:]]*#.*/d; s/(CONFIG_[[:alnum:]_]+)=.*/\1/g' CONFIG | sort) \
1419		<(printf "CONFIG_%s\n" "${!CONFIG[@]}" | sort)
1420	exit 1
1421fi
1422
1423echo -n "Creating mk/config.mk..."
1424cp -f $rootdir/CONFIG $rootdir/mk/config.mk
1425ARGS=$(echo "$@" | sed 's/ /\\ /g')
1426sed -i.bak -r "s#__CONFIGURE_OPTIONS__#${ARGS}#g" $rootdir/mk/config.mk
1427for key in "${!CONFIG[@]}"; do
1428	sed -i.bak -r "s#[[:space:]]*CONFIG_${key}=.*#CONFIG_${key}\?=${CONFIG[$key]}#g" $rootdir/mk/config.mk
1429done
1430# On FreeBSD sed -i 'SUFFIX' - SUFFIX is mandatory. So no way but to delete the backed file.
1431rm -f $rootdir/mk/config.mk.bak
1432echo "done."
1433
1434# Environment variables
1435echo -n "Creating mk/cc.flags.mk..."
1436rm -f $rootdir/mk/cc.flags.mk
1437[ -n "$CFLAGS" ] && echo "CFLAGS?=$CFLAGS" > $rootdir/mk/cc.flags.mk
1438[ -n "$CXXFLAGS" ] && echo "CXXFLAGS?=$CXXFLAGS" >> $rootdir/mk/cc.flags.mk
1439[ -n "$LDFLAGS" ] && echo "LDFLAGS?=$LDFLAGS" >> $rootdir/mk/cc.flags.mk
1440[ -n "$DESTDIR" ] && echo "DESTDIR?=$DESTDIR" >> $rootdir/mk/cc.flags.mk
1441echo "done."
1442
1443# Create .sh with build config for easy sourcing|lookup during the tests.
1444for conf in "${!CONFIG[@]}"; do
1445	echo "CONFIG_$conf=${CONFIG[$conf]}"
1446done > "$rootdir/test/common/build_config.sh"
1447
1448if [[ $sys_name == "FreeBSD" ]]; then
1449	echo "Type 'gmake' to build."
1450else
1451	echo "Type 'make' to build."
1452fi
1453
1454exit 0
1455