xref: /spdk/configure (revision 32999ab917f67af61872f868585fd3d78ad6fb8a)
1#!/usr/bin/env bash
2
3set -e
4
5trap 'echo -e "\n\nConfiguration failed\n\n" >&2' ERR
6
7rootdir=$(readlink -f $(dirname $0))
8source "$rootdir/scripts/common.sh"
9
10function usage() {
11	echo "'configure' configures SPDK to compile on supported platforms."
12	echo ""
13	echo "Usage: ./configure [OPTION]..."
14	echo ""
15	echo "Defaults for the options are specified in brackets."
16	echo ""
17	echo "General:"
18	echo " -h, --help                Display this help and exit"
19	echo ""
20	echo " --prefix=path             Configure installation prefix (default: /usr/local)"
21	echo " --target-arch=arch        Target build architecture. Must be a valid GNU arch. Default: native"
22	echo ""
23	echo " --cross-prefix=prefix     Prefix for cross compilation (default: none)"
24	echo "                           example: aarch64-linux-gnu"
25	echo ""
26	echo " --enable-debug            Configure for debug builds"
27	echo " --enable-werror           Treat compiler warnings as errors"
28	echo " --enable-asan             Enable address sanitizer"
29	echo " --enable-ubsan            Enable undefined behavior sanitizer"
30	echo " --enable-coverage         Enable code coverage tracking"
31	echo " --enable-lto              Enable link-time optimization"
32	echo " --enable-pgo-capture      Enable generation of profile guided optimization data"
33	echo " --enable-pgo-use          Use previously captured profile guided optimization data"
34	echo " --enable-cet              Enable Intel Control-flow Enforcement Technology (CET)"
35	echo " --disable-tests           Disable building of functional tests"
36	echo " --disable-unit-tests      Disable building of unit tests"
37	echo " --disable-examples        Disable building of examples"
38	echo ""
39	echo "Specifying Dependencies:"
40	echo "--with-DEPENDENCY[=path]   Use the given dependency. Optionally, provide the"
41	echo "                           path."
42	echo "--without-DEPENDENCY       Do not link to the given dependency. This may"
43	echo "                           disable features and components."
44	echo ""
45	echo "Valid dependencies are listed below."
46	echo " dpdk                      Build against a custom dpdk version. By default, the dpdk"
47	echo "                           submodule in spdk tree will be used."
48	echo "                           example: /usr/share/dpdk/x86_64-default-linuxapp-gcc"
49	echo " env                       Use an alternate environment implementation instead of DPDK."
50	echo "                           Implies --without-dpdk."
51	echo " idxd                      Build the IDXD library and accel framework plug-in module."
52	echo "                           Disabled while experimental. Only built for x86 when enabled."
53	echo " crypto                    Build vbdev crypto module."
54	echo "                           No path required."
55	echo " fio                       Build fio_plugin."
56	echo "                           default: /usr/src/fio"
57	echo " vhost                     Build vhost target. Enabled by default."
58	echo "                           No path required."
59	echo " virtio                    Build vhost initiator and virtio-pci bdev modules."
60	echo "                           No path required."
61	echo " vfio-user                 Build custom vfio-user transport for NVMf target and NVMe initiator."
62	echo "                           example: /usr/src/libvfio-user"
63	echo " pmdk                      Build persistent memory bdev."
64	echo "                           example: /usr/share/pmdk"
65	echo " reduce                    Build vbdev compression module."
66	echo "                           No path required."
67	echo " rbd                       Build Ceph RBD bdev module."
68	echo "                           No path required."
69	echo " rdma                      Build RDMA transport for NVMf target and initiator."
70	echo "                           Accepts optional RDMA provider name. Can be \"verbs\" or \"mlx5_dv\"."
71	echo "                           If no provider specified, \"verbs\" provider is used by default."
72	echo " fc                        Build FC transport for NVMf target."
73	echo "                           If an argument is provided, it is considered a directory containing"
74	echo "                           libufc.a and fc_lld.h. Otherwise the regular system paths will"
75	echo "                           be searched."
76	echo " shared                    Build spdk shared libraries."
77	echo "                           No path required."
78	echo " iscsi-initiator           Build with iscsi bdev module."
79	echo "                           No path required."
80	echo " vtune                     Required to profile I/O under Intel VTune Amplifier XE."
81	echo "                           example: /opt/intel/vtune_amplifier_xe_version"
82	echo " ocf                       Build OCF library and bdev module."
83	echo "                           If argument is directory, interpret it as root of OCF repo"
84	echo "                           If argument is file, interpret it as compiled OCF lib"
85	echo "                           If no argument is specified, OCF git submodule is used by default"
86	echo "                           example: /usr/src/ocf/"
87	echo " isal                      Build with ISA-L. Enabled by default on x86 and aarch64 architectures."
88	echo "                           No path required."
89	echo " uring                     Build I/O uring bdev or socket module."
90	echo "                           If an argument is provided, it is considered a directory containing"
91	echo "                           liburing.a and io_uring.h. Otherwise the regular system paths will"
92	echo "                           be searched."
93	echo " fuse                      Build FUSE components for mounting a blobfs filesystem."
94	echo "                           No path required."
95	echo " nvme-cuse                 Build NVMe driver with support for CUSE-based character devices."
96	echo "                           No path required."
97	echo " raid5                     Build with bdev_raid module RAID5 support."
98	echo "                           No path required."
99	echo " wpdk                      Build using WPDK to provide support for Windows (experimental)."
100	echo "                           The argument must be a directory containing lib and include."
101	echo ""
102	echo "Environment variables:"
103	echo ""
104	echo "CC                         C compiler"
105	echo "CFLAGS                     C compiler flags"
106	echo "CXX                        C++ compiler"
107	echo "CXXFLAGS                   C++ compiler flags"
108	echo "LD                         Linker"
109	echo "LDFLAGS                    Linker flags"
110	echo "DESTDIR                    Destination for 'make install'"
111	echo ""
112}
113
114# Load default values
115# Convert config to sourcable configuration file
116sed -r 's/CONFIG_([[:alnum:]_]+)=(.*)/CONFIG[\1]=\2/g' $rootdir/CONFIG > $rootdir/CONFIG.sh
117declare -A CONFIG
118source $rootdir/CONFIG.sh
119rm $rootdir/CONFIG.sh
120
121for i in "$@"; do
122	case "$i" in
123		--cross-prefix=*)
124			CONFIG[CROSS_PREFIX]="${i#*=}"
125			;;
126		--enable-lto)
127			CONFIG[LTO]=y
128			;;
129		--disable-lto)
130			CONFIG[LTO]=n
131			;;
132	esac
133done
134
135# Detect the compiler toolchain
136$rootdir/scripts/detect_cc.sh --cc="$CC" --cxx="$CXX" --lto="${CONFIG[LTO]}" --ld="$LD" --cross-prefix="${CONFIG[CROSS_PREFIX]}" > $rootdir/mk/cc.mk
137
138CC=$(grep "DEFAULT_CC=" "$rootdir/mk/cc.mk" | sed s/DEFAULT_CC=//)
139CC_TYPE=$(grep "CC_TYPE=" "$rootdir/mk/cc.mk" | cut -d "=" -f 2)
140
141arch=$($CC -dumpmachine)
142sys_name=$(uname -s)
143
144if [[ $arch == *mingw* ]] || [[ $arch == *windows* ]]; then
145	sys_name=Windows
146fi
147
148# Sanitize default configuration. All parameters set by user explicit should fail
149# Force no ISA-L if non-x86 or non-aarch64 architecture
150if [[ "${CONFIG[ISAL]}" = "y" ]]; then
151	if [[ $arch != x86_64* ]] && [[ $arch != aarch64* ]]; then
152		CONFIG[ISAL]=n
153		echo "Notice: ISA-L not supported for ${arch}. Turning off default feature."
154	fi
155fi
156
157if [[ $sys_name != "Linux" ]]; then
158	# Vhost, rte_vhost library and virtio are only supported on Linux.
159	CONFIG[VHOST]="n"
160	CONFIG[VIRTIO]="n"
161	echo "Notice: Vhost, rte_vhost library and virtio are only supported on Linux. Turning off default feature."
162fi
163
164#check nasm only on x86
165if [[ $arch == x86_64* ]]; then
166	ver=$(nasm -v 2> /dev/null | awk '{print $3}')
167	if lt "$ver" 2.14; then
168		# ISA-L, compression & crypto require NASM version 2.14 or newer.
169		CONFIG[ISAL]=n
170		CONFIG[CRYPTO]=n
171		CONFIG[IPSEC_MB]=n
172		CONFIG[REDUCE]=n
173		HAVE_NASM=n
174		echo "Notice: ISA-L, compression & crypto require NASM version 2.14 or newer. Turning off default ISA-L and crypto features."
175	else
176		HAVE_NASM=y
177	fi
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
189for i in "$@"; do
190	case "$i" in
191		-h | --help)
192			usage
193			exit 0
194			;;
195		--cross-prefix=*) ;&
196		--enable-lto) ;&
197		--disable-lto)
198			# Options handled before detecting CC.
199			;;
200		--prefix=*)
201			CONFIG[PREFIX]="${i#*=}"
202			;;
203		--target-arch=*)
204			CONFIG[ARCH]="${i#*=}"
205			;;
206		--enable-debug)
207			CONFIG[DEBUG]=y
208			;;
209		--disable-debug)
210			CONFIG[DEBUG]=n
211			;;
212		--enable-asan)
213			CONFIG[ASAN]=y
214			;;
215		--disable-asan)
216			CONFIG[ASAN]=n
217			;;
218		--enable-ubsan)
219			CONFIG[UBSAN]=y
220			;;
221		--disable-ubsan)
222			CONFIG[UBSAN]=n
223			;;
224		--enable-tsan)
225			CONFIG[TSAN]=y
226			;;
227		--disable-tsan)
228			CONFIG[TSAN]=n
229			;;
230		--enable-coverage)
231			CONFIG[COVERAGE]=y
232			;;
233		--disable-coverage)
234			CONFIG[COVERAGE]=n
235			;;
236		--enable-pgo-capture)
237			CONFIG[PGO_CAPTURE]=y
238			;;
239		--disable-pgo-capture)
240			CONFIG[PGO_CAPTURE]=n
241			;;
242		--enable-pgo-use)
243			CONFIG[PGO_USE]=y
244			;;
245		--disable-pgo-use)
246			CONFIG[PGO_USE]=n
247			;;
248		--enable-tests)
249			CONFIG[TESTS]=y
250			;;
251		--disable-tests)
252			CONFIG[TESTS]=n
253			;;
254		--enable-unit-tests)
255			CONFIG[UNIT_TESTS]=y
256			;;
257		--disable-unit-tests)
258			CONFIG[UNIT_TESTS]=n
259			;;
260		--enable-examples)
261			CONFIG[EXAMPLES]=y
262			;;
263		--disable-examples)
264			CONFIG[EXAMPLES]=n
265			;;
266		--enable-werror)
267			CONFIG[WERROR]=y
268			;;
269		--disable-werror)
270			CONFIG[WERROR]=n
271			;;
272		--enable-cet)
273			CONFIG[CET]=y
274			;;
275		--disable-cet)
276			CONFIG[CET]=n
277			;;
278		--with-dpdk=*)
279			check_dir "$i"
280			CONFIG[DPDK_DIR]=$(readlink -f ${i#*=})
281			;;
282		--without-dpdk)
283			CONFIG[DPDK_DIR]=
284			;;
285		--with-wpdk=*)
286			check_dir "$i"
287			CONFIG[WPDK_DIR]=$(readlink -f ${i#*=})
288			;;
289		--with-env=*)
290			CONFIG[ENV]="${i#*=}"
291			;;
292		--with-rbd)
293			CONFIG[RBD]=y
294			;;
295		--without-rbd)
296			CONFIG[RBD]=n
297			;;
298		--with-rdma=*)
299			CONFIG[RDMA]=y
300			CONFIG[RDMA_PROV]=${i#*=}
301			;;
302		--with-rdma)
303			CONFIG[RDMA]=y
304			CONFIG[RDMA_PROV]="verbs"
305			;;
306		--without-rdma)
307			CONFIG[RDMA]=n
308			;;
309		--with-fc=*)
310			CONFIG[FC]=y
311			CONFIG[FC_PATH]=$(readlink -f ${i#*=})
312			;;
313		--with-fc)
314			CONFIG[FC]=y
315			CONFIG[FC_PATH]=
316			;;
317		--without-fc)
318			CONFIG[FC]=n
319			CONFIG[FC_PATH]=
320			;;
321		--with-shared)
322			CONFIG[SHARED]=y
323			;;
324		--without-shared)
325			CONFIG[SHARED]=n
326			;;
327		--with-iscsi-initiator)
328			CONFIG[ISCSI_INITIATOR]=y
329			;;
330		--without-iscsi-initiator)
331			CONFIG[ISCSI_INITIATOR]=n
332			;;
333		--with-crypto)
334			CONFIG[CRYPTO]=y
335			;;
336		--without-crypto)
337			CONFIG[CRYPTO]=n
338			;;
339		--with-vhost)
340			CONFIG[VHOST]=y
341			;;
342		--without-vhost)
343			CONFIG[VHOST]=n
344			;;
345		--with-virtio)
346			CONFIG[VIRTIO]=y
347			;;
348		--without-virtio)
349			CONFIG[VIRTIO]=n
350			;;
351		--with-vfio-user)
352			CONFIG[VFIO_USER]=y
353			CONFIG[VFIO_USER_DIR]=""
354			;;
355		--with-vfio-user=*)
356			CONFIG[VFIO_USER]=y
357			check_dir "$i"
358			CONFIG[VFIO_USER_DIR]=$(readlink -f ${i#*=})
359			;;
360		--without-vfio-user)
361			CONFIG[VFIO_USER]=n
362			;;
363		--with-pmdk)
364			CONFIG[PMDK]=y
365			CONFIG[PMDK_DIR]=""
366			;;
367		--with-pmdk=*)
368			CONFIG[PMDK]=y
369			check_dir "$i"
370			CONFIG[PMDK_DIR]=$(readlink -f ${i#*=})
371			;;
372		--without-pmdk)
373			CONFIG[PMDK]=n
374			;;
375		--with-reduce)
376			CONFIG[REDUCE]=y
377			;;
378		--without-reduce)
379			CONFIG[REDUCE]=n
380			;;
381		--with-fio) ;&
382		--with-fio=*)
383			if [[ ${i#*=} != "$i" ]]; then
384				CONFIG[FIO_SOURCE_DIR]=$(readlink -f "${i#*=}")
385			fi
386			check_dir "--with-fio=${CONFIG[FIO_SOURCE_DIR]}"
387			CONFIG[FIO_PLUGIN]=y
388			;;
389		--without-fio)
390			CONFIG[FIO_PLUGIN]=n
391			;;
392		--with-vtune=*)
393			check_dir "$i"
394			CONFIG[VTUNE_DIR]="${i#*=}"
395			CONFIG[VTUNE]=y
396			;;
397		--without-vtune)
398			CONFIG[VTUNE_DIR]=
399			CONFIG[VTUNE]=n
400			;;
401		--with-ocf)
402			CONFIG[OCF]=y
403			CONFIG[OCF_PATH]=$(readlink -f "./ocf")
404			;;
405		--with-ocf=*)
406			CONFIG[OCF]=y
407			CONFIG[OCF_PATH]=$(readlink -f ${i#*=})
408			;;
409		--without-ocf)
410			CONFIG[OCF]=n
411			CONFIG[OCF_PATH]=
412			;;
413		--with-isal)
414			CONFIG[ISAL]=y
415			;;
416		--without-isal)
417			CONFIG[ISAL]=n
418			;;
419		--with-uring=*)
420			CONFIG[URING]=y
421			CONFIG[URING_PATH]=$(readlink -f ${i#*=})
422			;;
423		--with-uring)
424			CONFIG[URING]=y
425			CONFIG[URING_PATH]=
426			;;
427		--without-uring)
428			CONFIG[URING]=n
429			CONFIG[URING_PATH]=
430			;;
431		--with-fuse)
432			CONFIG[FUSE]=y
433			;;
434		--without-fuse)
435			CONFIG[FUSE]=n
436			;;
437		--with-nvme-cuse)
438			CONFIG[NVME_CUSE]=y
439			;;
440		--without-nvme-cuse)
441			CONFIG[NVME_CUSE]=n
442			;;
443		--with-raid5)
444			CONFIG[RAID5]=y
445			;;
446		--without-raid5)
447			CONFIG[RAID5]=n
448			;;
449		--with-idxd)
450			CONFIG[IDXD]=y
451			;;
452		--without-idxd)
453			CONFIG[IDXD]=n
454			;;
455		--)
456			break
457			;;
458		*)
459			echo "Unrecognized option $i"
460			usage
461			exit 1
462			;;
463	esac
464done
465
466if [[ $arch == x86_64* ]]; then
467	BUILD_CMD=("$CC" -o /dev/null -x c $CPPFLAGS $CFLAGS $LDFLAGS "-march=native")
468else
469	BUILD_CMD=("$CC" -o /dev/null -x c $CPPFLAGS $CFLAGS $LDFLAGS)
470fi
471BUILD_CMD+=(-I/usr/local/include -L/usr/local/lib)
472
473if [[ "${CONFIG[VFIO_USER]}" = "y" ]]; then
474
475	if ! hash cmake; then
476		echo "ERROR: --with-vfio-user requires cmake"
477		echo "Please install then re-run this script"
478		exit 1
479	fi
480	if [[ ! -d /usr/include/json-c ]] && [[ ! -d /usr/local/include/json-c ]]; then
481		echo "ERROR: --with-vfio-user requires json-c-devel"
482		echo "Please install then re-run this script"
483		exit 1
484	fi
485	if [[ ! -e /usr/include/cmocka.h ]] && [[ ! -e /usr/local/include/cmocka.h ]]; then
486		echo "ERROR: --with-vfio-user requires libcmocka-devel"
487		echo "Please install then re-run this script"
488		exit 1
489	fi
490fi
491
492# IDXD uses Intel specific instructions.
493if [[ "${CONFIG[IDXD]}" = "y" ]]; then
494	if [ $(uname -s) == "FreeBSD" ]; then
495		intel="hw.model: Intel"
496		cpu_vendor=$(sysctl -a | grep hw.model | cut -c 1-15)
497	else
498		intel="GenuineIntel"
499		cpu_vendor=$(grep -i 'vendor' /proc/cpuinfo --max-count=1)
500	fi
501	if [[ "$cpu_vendor" != *"$intel"* ]]; then
502		echo "ERROR: IDXD cannot be used due to CPU incompatiblity."
503		exit 1
504	fi
505fi
506
507# Detect architecture and force no ISA-L if non-x86 or non-aarch64 architecture
508if [[ "${CONFIG[ISAL]}" = "y" ]]; then
509	if [[ $arch != x86_64* ]] && [[ $arch != aarch64* ]]; then
510		echo "ERROR: ISA-L cannot be used due to CPU incompatiblity."
511		exit 1
512	fi
513fi
514
515if [[ "${CONFIG[ISAL]}" = "n" ]] && [[ "${CONFIG[REDUCE]}" = "y" ]]; then
516	echo "ERROR Conflicting options: --with-reduce is not compatible with --without-isal."
517	exit 1
518fi
519
520if [ -z "${CONFIG[ENV]}" ]; then
521	CONFIG[ENV]=$rootdir/lib/env_dpdk
522	echo "Using default SPDK env in ${CONFIG[ENV]}"
523	if [ -z "${CONFIG[DPDK_DIR]}" ]; then
524		if [ ! -f "$rootdir"/dpdk/config/meson.build ]; then
525			echo "DPDK not found; please specify --with-dpdk=<path> or run:"
526			echo
527			echo "  git submodule update --init"
528			exit 1
529		else
530			CONFIG[DPDK_DIR]="${rootdir}/dpdk/build"
531			echo "Using default DPDK in ${CONFIG[DPDK_DIR]}"
532		fi
533	fi
534else
535	if [ -n "${CONFIG[DPDK_DIR]}" ]; then
536		echo "--with-env and --with-dpdk are mutually exclusive."
537		exit 1
538	fi
539
540	if [ "${CONFIG[VHOST]}" = "y" ]; then
541		echo "Vhost is only supported when using the default DPDK environment. Disabling it."
542	fi
543	# Always disable vhost, but only print the error message if the user explicitly turned it on.
544	CONFIG[VHOST]="n"
545	if [ "${CONFIG[VIRTIO]}" = "y" ]; then
546		echo "Virtio is only supported when using the default DPDK environment. Disabling it."
547	fi
548	# Always disable virtio, but only print the error message if the user explicitly turned it on.
549	CONFIG[VIRTIO]="n"
550fi
551
552if [[ $sys_name == "Windows" ]]; then
553	if [ -z "${CONFIG[WPDK_DIR]}" ]; then
554		if [ ! -f "$rootdir"/wpdk/Makefile ]; then
555			echo "WPDK not found; please specify --with-wpdk=<path>. See https://wpdk.github.io."
556			exit 1
557		else
558			CONFIG[WPDK_DIR]="${rootdir}/wpdk/build"
559			echo "Using default WPDK in ${CONFIG[WPDK_DIR]}"
560		fi
561	fi
562else
563	if [ -n "${CONFIG[WPDK_DIR]}" ]; then
564		echo "ERROR: --with-wpdk is only supported for Windows"
565		exit 1
566	fi
567fi
568
569if [ "${CONFIG[VTUNE]}" = "y" ]; then
570	if [ -z "${CONFIG[VTUNE_DIR]}" ]; then
571		echo "When VTune is enabled, you must specify the VTune directory using --with-vtune=path"
572		exit 1
573	fi
574fi
575
576if [[ "${CONFIG[ASAN]}" = "y" && "${CONFIG[TSAN]}" = "y" ]]; then
577	echo "ERROR: ASAN and TSAN cannot be enabled at the same time."
578	exit 1
579fi
580
581if [[ $sys_name == "FreeBSD" ]]; then
582	# FreeBSD doesn't support all configurations
583	if [[ "${CONFIG[COVERAGE]}" == "y" ]]; then
584		echo "ERROR: CONFIG_COVERAGE not available on FreeBSD"
585		exit 1
586	fi
587fi
588
589if [[ $sys_name != "Linux" ]]; then
590	if [[ "${CONFIG[VHOST]}" == "y" ]]; then
591		echo "Vhost is only supported on Linux."
592		exit 1
593	fi
594	if [[ "${CONFIG[VIRTIO]}" == "y" ]]; then
595		echo "Virtio is only supported on Linux."
596		exit 1
597	fi
598fi
599
600if [ "${CONFIG[RDMA]}" = "y" ]; then
601	if [[ ! "${CONFIG[RDMA_PROV]}" == "verbs" ]] && [[ ! "${CONFIG[RDMA_PROV]}" == "mlx5_dv" ]]; then
602		echo "Invalid RDMA provider specified, must be \"verbs\" or \"mlx5_dv\""
603		exit 1
604	fi
605
606	if ! echo -e '#include <infiniband/verbs.h>\n#include <rdma/rdma_verbs.h>\n' \
607		'int main(void) { return 0; }\n' \
608		| "${BUILD_CMD[@]}" -libverbs -lrdmacm - 2> /dev/null; then
609		echo "--with-rdma requires libverbs and librdmacm."
610		echo "Please install then re-run this script."
611		exit 1
612	fi
613
614	if echo -e '#include <infiniband/verbs.h>\n' \
615		'int main(void) { return !!IBV_WR_SEND_WITH_INV; }\n' \
616		| "${BUILD_CMD[@]}" -c - 2> /dev/null; then
617		CONFIG[RDMA_SEND_WITH_INVAL]="y"
618	else
619		CONFIG[RDMA_SEND_WITH_INVAL]="n"
620		echo "
621*******************************************************************************
622WARNING: The Infiniband Verbs opcode Send With Invalidate is either not
623supported or is not functional with the current version of libibverbs installed
624on this system. Please upgrade to at least version 1.1.
625
626Beginning with Linux kernel 4.14, the kernel NVMe-oF initiator leverages Send
627With Invalidate RDMA operations to improve performance. Failing to use the
628Send With Invalidate operation on the NVMe-oF target side results in full
629functionality, but greatly reduced performance. The SPDK NVMe-oF target will
630be unable to leverage that operation using the currently installed version
631of libibverbs, so Linux kernel NVMe-oF initiators based on kernels greater
632than or equal to 4.14 will see significantly reduced performance.
633*******************************************************************************"
634	fi
635
636	if echo -e '#include <rdma/rdma_cma.h>\n' \
637		'int main(void) { return !!RDMA_OPTION_ID_ACK_TIMEOUT; }\n' \
638		| "${BUILD_CMD[@]}" -c - 2> /dev/null; then
639		CONFIG[RDMA_SET_ACK_TIMEOUT]="y"
640	else
641		CONFIG[RDMA_SET_ACK_TIMEOUT]="n"
642		echo "RDMA_OPTION_ID_ACK_TIMEOUT is not supported"
643	fi
644
645	if [ "${CONFIG[RDMA_PROV]}" == "mlx5_dv" ]; then
646		if ! echo -e '#include <spdk/stdinc.h>\n' \
647			'#include <infiniband/mlx5dv.h>\n' \
648			'#include <rdma/rdma_cma.h>\n' \
649			'int main(void) { return rdma_establish(NULL) || ' \
650			'!!IBV_QP_INIT_ATTR_SEND_OPS_FLAGS || !!MLX5_OPCODE_RDMA_WRITE; }\n' \
651			| "${BUILD_CMD[@]}" -lmlx5 -I${rootdir}/include -c - 2> /dev/null; then
652			echo "mlx5_dv provider is not supported"
653			exit 1
654		fi
655	fi
656
657	echo "Using '${CONFIG[RDMA_PROV]}' RDMA provider"
658fi
659
660if [[ "${CONFIG[FC]}" = "y" ]]; then
661	if [[ -n "${CONFIG[FC_PATH]}" ]]; then
662		if [ ! -d "${CONFIG[FC_PATH]}" ]; then
663			echo "${CONFIG[FC_PATH]}: directory not found"
664			exit 1
665		fi
666	fi
667fi
668
669if [[ "${CONFIG[ISAL]}" = "y" ]] || [[ "${CONFIG[CRYPTO]}" = "y" ]]; then
670	if [[ "${HAVE_NASM}" = "n" ]] && [[ $arch == x86_64* ]]; then
671		echo "ERROR: ISA-L, compression & crypto require NASM version 2.14 or newer."
672		echo "Please install or upgrade them re-run this script."
673		exit 1
674	else
675		if [[ "${CONFIG[CRYPTO]}" = "y" ]]; then
676			CONFIG[IPSEC_MB]=y
677		fi
678	fi
679fi
680
681if [[ "${CONFIG[PMDK]}" = "y" ]]; then
682	if ! echo -e '#include <libpmemblk.h>\nint main(void) { return 0; }\n' \
683		| "${BUILD_CMD[@]}" -lpmemblk - 2> /dev/null; then
684		echo "--with-pmdk requires libpmemblk."
685		echo "Please install then re-run this script."
686		exit 1
687	fi
688fi
689
690if [[ "${CONFIG[REDUCE]}" = "y" ]]; then
691	if ! echo -e '#include <libpmem.h>\nint main(void) { return 0; }\n' \
692		| "${BUILD_CMD[@]}" -lpmem - 2> /dev/null; then
693		echo "--with-reduce requires libpmem."
694		echo "Please install then re-run this script."
695		exit 1
696	fi
697fi
698
699if [[ "${CONFIG[NVME_CUSE]}" = "y" ]]; then
700	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' \
701		| "${BUILD_CMD[@]}" -lfuse3 -D_FILE_OFFSET_BITS=64 - 2> /dev/null; then
702		echo "--with-cuse requires libfuse3."
703		echo "Please install then re-run this script."
704		exit 1
705	fi
706fi
707
708if [[ "${CONFIG[RBD]}" = "y" ]]; then
709	if ! echo -e '#include <rbd/librbd.h>\n#include <rados/librados.h>\n' \
710		'int main(void) { return 0; }\n' \
711		| "${BUILD_CMD[@]}" -lrados -lrbd - 2> /dev/null; then
712		echo "--with-rbd requires librados and librbd."
713		echo "Please install then re-run this script."
714		exit 1
715	fi
716fi
717
718if [[ "${CONFIG[ISCSI_INITIATOR]}" = "y" ]]; then
719	# Fedora installs libiscsi to /usr/lib64/iscsi for some reason.
720	if ! echo -e '#include <iscsi/iscsi.h>\n#include <iscsi/scsi-lowlevel.h>\n' \
721		'#if LIBISCSI_API_VERSION < 20150621\n' \
722		'#error\n' \
723		'#endif\n' \
724		'int main(void) { return 0; }\n' \
725		| "${BUILD_CMD[@]}" -L/usr/lib64/iscsi -liscsi - 2> /dev/null; then
726		echo "--with-iscsi-initiator requires libiscsi with"
727		echo "LIBISCSI_API_VERSION >= 20150621."
728		echo "Please install then re-run this script."
729		exit 1
730	fi
731fi
732
733if [[ "${CONFIG[ASAN]}" = "y" ]]; then
734	if ! echo -e 'int main(void) { return 0; }\n' \
735		| "${BUILD_CMD[@]}" -fsanitize=address - 2> /dev/null; then
736		echo "--enable-asan requires libasan."
737		echo "Please install then re-run this script."
738		exit 1
739	fi
740fi
741
742if [[ "${CONFIG[UBSAN]}" = "y" ]]; then
743	if ! echo -e 'int main(void) { return 0; }\n' \
744		| "${BUILD_CMD[@]}" -fsanitize=undefined - 2> /dev/null; then
745		echo "--enable-ubsan requires libubsan."
746		echo "Please install then re-run this script."
747		echo "If installed, please check that the GCC version is at least 6.4"
748		echo "and synchronize CC accordingly."
749		exit 1
750	fi
751fi
752
753if [[ "${CONFIG[TSAN]}" = "y" ]]; then
754	if ! echo -e 'int main(void) { return 0; }\n' \
755		| "${BUILD_CMD[@]}" -fsanitize=thread - 2> /dev/null; then
756		echo "--enable-tsan requires libtsan."
757		echo "Please install then re-run this script."
758		exit 1
759	fi
760fi
761
762if [[ "${CONFIG[OCF]}" = "y" ]]; then
763	# If OCF_PATH is a file, assume it is a library and use it to compile with
764	if [ -f ${CONFIG[OCF_PATH]} ]; then
765		CONFIG[CUSTOMOCF]=y
766	else
767		CONFIG[CUSTOMOCF]=n
768	fi
769fi
770
771if [[ "${CONFIG[PGO_CAPTURE]}" = "y" && "${CONFIG[PGO_USE]}" = "y" ]]; then
772	echo "ERROR: --enable-pgo-capture and --enable-pgo-use are mutually exclusive."
773	exit 1
774elif [[ "${CONFIG[PGO_USE]}" = "y" ]]; then
775	if [[ "$CC_TYPE" = "clang" ]]; then
776		# For clang we need to run an extra step on gathered profiling data.
777		echo "Generating suitable profile data"
778		llvm-profdata merge -output=build/pgo/default.profdata build/pgo
779	fi
780fi
781
782if [[ "${CONFIG[URING]}" = "y" ]]; then
783	if [[ -n "${CONFIG[URING_PATH]}" ]]; then
784		if [ ! -d "${CONFIG[URING_PATH]}" ]; then
785			echo "${CONFIG[URING_PATH]}: directory not found"
786			exit 1
787		fi
788	elif ! echo -e '#include <liburing.h>\nint main(void) { return 0; }\n' \
789		| "${BUILD_CMD[@]}" -luring - 2> /dev/null; then
790		echo "--with-uring requires liburing."
791		echo "Please build and install then re-run this script."
792		exit 1
793	fi
794fi
795
796if [[ "${CONFIG[FUSE]}" = "y" ]]; then
797	if [[ ! -d /usr/include/fuse3 ]] && [[ ! -d /usr/local/include/fuse3 ]]; then
798		echo "--with-fuse requires libfuse3."
799		echo "Please install then re-run this script."
800		exit 1
801	fi
802fi
803
804if [ "${CONFIG[CET]}" = "y" ]; then
805	if ! echo -e 'int main(void) { return 0; }\n' | "${BUILD_CMD[@]}" -fcf-protection - 2> /dev/null; then
806		echo "--enable-cet requires compiler/linker that supports CET."
807		echo "Please install then re-run this script."
808		exit 1
809	fi
810fi
811
812if [[ "${CONFIG[ISAL]}" = "y" ]]; then
813	if [ ! -f "$rootdir"/isa-l/autogen.sh ]; then
814		echo "ISA-L was not found; To install ISA-L run:"
815		echo "  git submodule update --init"
816		exit 1
817	fi
818
819	cd $rootdir/isa-l
820	ISAL_LOG=$rootdir/isa-l/spdk-isal.log
821	if [[ -n "${CONFIG[CROSS_PREFIX]}" ]]; then
822		ISAL_OPTS=("--host=${CONFIG[CROSS_PREFIX]}")
823	else
824		ISAL_OPTS=()
825	fi
826	echo -n "Configuring ISA-L (logfile: $ISAL_LOG)..."
827	./autogen.sh &> $ISAL_LOG
828	./configure CFLAGS="-fPIC -g -O2" "${ISAL_OPTS[@]}" --enable-shared=no >> $ISAL_LOG 2>&1
829	echo "done."
830	cd $rootdir
831fi
832
833# We are now ready to generate final configuration. But first do sanity
834# check to see if all keys in CONFIG array have its reflection in CONFIG file.
835if (($(grep -cE "^\s*CONFIG_[[:alnum:]_]+=" "$rootdir/CONFIG") != ${#CONFIG[@]})); then
836	echo ""
837	echo "BUG: Some configuration options are not present in CONFIG file. Please update this file."
838	echo "Missing options in CONFIG (+) file and in current config (-): "
839	diff -u --label "CONFIG file" --label "CONFIG[@]" \
840		<(sed -r -e '/^\s*$/d; /^\s*#.*/d; s/(CONFIG_[[:alnum:]_]+)=.*/\1/g' CONFIG | sort) \
841		<(printf "CONFIG_%s\n" "${!CONFIG[@]}" | sort)
842	exit 1
843fi
844
845echo -n "Creating mk/config.mk..."
846cp -f $rootdir/CONFIG $rootdir/mk/config.mk
847for key in "${!CONFIG[@]}"; do
848	sed -i.bak -r "s#^\s*CONFIG_${key}=.*#CONFIG_${key}\?=${CONFIG[$key]}#g" $rootdir/mk/config.mk
849done
850# On FreeBSD sed -i 'SUFFIX' - SUFFIX is mandatory. So no way but to delete the backed file.
851rm -f $rootdir/mk/config.mk.bak
852echo "done."
853
854# Environment variables
855echo -n "Creating mk/cc.flags.mk..."
856rm -f $rootdir/mk/cc.flags.mk
857[ -n "$CFLAGS" ] && echo "CFLAGS?=$CFLAGS" > $rootdir/mk/cc.flags.mk
858[ -n "$CXXFLAGS" ] && echo "CXXFLAGS?=$CXXFLAGS" >> $rootdir/mk/cc.flags.mk
859[ -n "$LDFLAGS" ] && echo "LDFLAGS?=$LDFLAGS" >> $rootdir/mk/cc.flags.mk
860[ -n "$DESTDIR" ] && echo "DESTDIR?=$DESTDIR" >> $rootdir/mk/cc.flags.mk
861echo "done."
862
863# Create .sh with build config for easy sourcing|lookup during the tests.
864for conf in "${!CONFIG[@]}"; do
865	echo "CONFIG_$conf=${CONFIG[$conf]}"
866done > "$rootdir/test/common/build_config.sh"
867
868if [[ $sys_name == "FreeBSD" ]]; then
869	echo "Type 'gmake' to build."
870else
871	echo "Type 'make' to build."
872fi
873
874exit 0
875