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