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