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