#!/bin/sh set -e cc=${CC:-gcc} cxx=${CXX:-g++} for opt do optarg=$(expr "x$opt" : 'x[^=]*=\(.*\)' || true) case "$opt" in --help|-h) show_help=yes ;; --prefix=*) prefix="$(realpath -s $optarg)" ;; --includedir=*) includedir="$optarg" ;; --libdir=*) libdir="$optarg" ;; --libdevdir=*) libdevdir="$optarg" ;; --mandir=*) mandir="$optarg" ;; --datadir=*) datadir="$optarg" ;; --cc=*) cc="$optarg" ;; --cxx=*) cxx="$optarg" ;; --use-libc) use_libc=yes ;; --enable-sanitizer) use_sanitizer=yes ;; *) echo "ERROR: unknown option $opt" echo "Try '$0 --help' for more information" exit 1 ;; esac done if test -z "$prefix"; then prefix=/usr fi if test -z "$includedir"; then includedir="$prefix/include" fi if test -z "$libdir"; then libdir="$prefix/lib" fi if test -z "$libdevdir"; then libdevdir="$prefix/lib" fi if test -z "$mandir"; then mandir="$prefix/man" fi if test -z "$datadir"; then datadir="$prefix/share" fi if test x"$libdir" = x"$libdevdir"; then relativelibdir="" else relativelibdir="$libdir/" fi if test "$show_help" = "yes"; then cat < trap "rm -rf $TMP_DIRECTORY" EXIT INT QUIT TERM rm -rf config.log config_host_mak="config-host.mak" config_host_h="config-host.h" rm -rf $config_host_mak rm -rf $config_host_h fatal() { echo $@ echo "Configure failed, check config.log and/or the above output" rm -rf $config_host_mak rm -rf $config_host_h exit 1 } # Print result for each configuration test print_config() { printf "%-30s%s\n" "$1" "$2" } # Default CFLAGS CFLAGS="-D_GNU_SOURCE -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64 -include config-host.h" BUILD_CFLAGS="" # Print configure header at the top of $config_host_h echo "/*" > $config_host_h echo " * Automatically generated by configure - do not modify" >> $config_host_h printf " * Configured with:" >> $config_host_h printf " * '%s'" "$0" "$@" >> $config_host_h echo "" >> $config_host_h echo " */" >> $config_host_h echo "# Automatically generated by configure - do not modify" > $config_host_mak printf "# Configured with:" >> $config_host_mak printf " '%s'" "$0" "$@" >> $config_host_mak echo >> $config_host_mak do_cxx() { # Run the compiler, capturing its output to the log. echo $cxx "$@" >> config.log $cxx "$@" >> config.log 2>&1 || return $? return 0 } do_cc() { # Run the compiler, capturing its output to the log. echo $cc "$@" >> config.log $cc "$@" >> config.log 2>&1 || return $? # Test passed. If this is an --enable-werror build, rerun # the test with -Werror and bail out if it fails. This # makes warning-generating-errors in configure test code # obvious to developers. if test "$werror" != "yes"; then return 0 fi # Don't bother rerunning the compile if we were already using -Werror case "$*" in *-Werror*) return 0 ;; esac echo $cc -Werror "$@" >> config.log $cc -Werror "$@" >> config.log 2>&1 && return $? echo "ERROR: configure test passed without -Werror but failed with -Werror." echo "This is probably a bug in the configure script. The failing command" echo "will be at the bottom of config.log." fatal "You can run configure with --disable-werror to bypass this check." } compile_prog() { local_cflags="$1" local_ldflags="$2 $LIBS" echo "Compiling test case $3" >> config.log do_cc $CFLAGS $local_cflags -o $TMPE $TMPC $LDFLAGS $local_ldflags } compile_prog_cxx() { local_cflags="$1" local_ldflags="$2 $LIBS" echo "Compiling test case $3" >> config.log do_cxx $CFLAGS $local_cflags -o $TMPE $TMPCXX $LDFLAGS $local_ldflags } has() { type "$1" >/dev/null 2>&1 } output_mak() { echo "$1=$2" >> $config_host_mak } output_sym() { output_mak "$1" "y" echo "#define $1" >> $config_host_h } print_and_output_mak() { print_config "$1" "$2" output_mak "$1" "$2" } print_and_output_mak "prefix" "$prefix" print_and_output_mak "includedir" "$includedir" print_and_output_mak "libdir" "$libdir" print_and_output_mak "libdevdir" "$libdevdir" print_and_output_mak "relativelibdir" "$relativelibdir" print_and_output_mak "mandir" "$mandir" print_and_output_mak "datadir" "$datadir" #################################################### # Check for correct compiler runtime library to link with libgcc_link_flag="-lgcc" if $cc -print-libgcc-file-name >/dev/null 2>&1; then libgcc_link_flag="$($cc $CFLAGS $LDFLAGS -print-libgcc-file-name)" fi print_and_output_mak "libgcc_link_flag" "$libgcc_link_flag" #################################################### ########################################## # check for compiler -Wstringop-overflow stringop_overflow="no" cat > $TMPC << EOF #include int main(int argc, char **argv) { return 0; } EOF if compile_prog "-Werror -Wstringop-overflow=0" "" "stringop_overflow"; then stringop_overflow="yes" fi print_config "stringop_overflow" "$stringop_overflow" ########################################## # check for compiler -Warryr-bounds array_bounds="no" cat > $TMPC << EOF #include int main(int argc, char **argv) { return 0; } EOF if compile_prog "-Werror -Warray-bounds=0" "" "array_bounds"; then array_bounds="yes" fi print_config "array_bounds" "$array_bounds" ########################################## # check for __kernel_rwf_t __kernel_rwf_t="no" cat > $TMPC << EOF #include int main(int argc, char **argv) { __kernel_rwf_t x; x = 0; return x; } EOF if compile_prog "" "" "__kernel_rwf_t"; then __kernel_rwf_t="yes" fi print_config "__kernel_rwf_t" "$__kernel_rwf_t" ########################################## # check for __kernel_timespec __kernel_timespec="no" cat > $TMPC << EOF #include #include int main(int argc, char **argv) { struct __kernel_timespec ts; ts.tv_sec = 0; ts.tv_nsec = 1; return 0; } EOF if compile_prog "" "" "__kernel_timespec"; then __kernel_timespec="yes" fi print_config "__kernel_timespec" "$__kernel_timespec" ########################################## # check for open_how open_how="no" cat > $TMPC << EOF #include #include #include #include int main(int argc, char **argv) { struct open_how how; how.flags = 0; how.mode = 0; how.resolve = 0; return 0; } EOF if compile_prog "" "" "open_how"; then open_how="yes" fi print_config "open_how" "$open_how" ########################################## # check for statx statx="no" cat > $TMPC << EOF #include #include #include #include #include int main(int argc, char **argv) { struct statx x; return memset(&x, 0, sizeof(x)) != NULL; } EOF if compile_prog "" "" "statx"; then statx="yes" fi print_config "statx" "$statx" ########################################## # check for glibc statx glibc_statx="no" cat > $TMPC << EOF #include #include #include #include #include int main(int argc, char **argv) { struct statx x; return memset(&x, 0, sizeof(x)) != NULL; } EOF if compile_prog "" "" "glibc_statx"; then glibc_statx="yes" fi print_config "glibc_statx" "$glibc_statx" ########################################## # check for C++ has_cxx="no" cat > $TMPCXX << EOF #include int main(int argc, char **argv) { std::cout << "Test"; return 0; } EOF if compile_prog_cxx "" "" "C++"; then has_cxx="yes" fi print_config "C++" "$has_cxx" ########################################## # check for ucontext support has_ucontext="no" cat > $TMPC << EOF #include int main(int argc, char **argv) { ucontext_t ctx; getcontext(&ctx); makecontext(&ctx, 0, 0); return 0; } EOF if compile_prog "" "" "has_ucontext"; then has_ucontext="yes" fi print_config "has_ucontext" "$has_ucontext" ########################################## # Check NVME_URING_CMD support nvme_uring_cmd="no" cat > $TMPC << EOF #include int main(void) { struct nvme_uring_cmd *cmd; return sizeof(struct nvme_uring_cmd); } EOF if compile_prog "" "" "nvme uring cmd"; then nvme_uring_cmd="yes" fi print_config "NVMe uring command support" "$nvme_uring_cmd" ########################################## # Check futexv support futexv="no" cat > $TMPC << EOF #include #include #include int main(void) { struct futex_waitv fw; memset(&fw, FUTEX_32, sizeof(fw)); return sizeof(struct futex_waitv); } EOF if compile_prog "" "" "futexv"; then futexv="yes" fi print_config "futex waitv support" "$futexv" ########################################## # Check block discard cmd support discard_cmd="no" cat > $TMPC << EOF #include int main(void) { return BLOCK_URING_CMD_DISCARD; } EOF if compile_prog "" "" "discard command"; then discard_cmd="yes" fi print_config "io_uring discard command support" "$discard_cmd" ########################################## # Check idtype_t support has_idtype_t="no" cat > $TMPC << EOF #include int main(void) { idtype_t v; return 0; } EOF if compile_prog "" "" "idtype_t"; then has_idtype_t="yes" fi print_config "has_idtype_t" "$has_idtype_t" ############################################################################# liburing_nolibc="no" if test "$use_libc" != "yes"; then # # Currently, CONFIG_NOLIBC only supports x86-64, x86 (32-bit), aarch64 and riscv64. # cat > $TMPC << EOF int main(void){ #if defined(__x86_64__) || defined(__i386__) || defined(__aarch64__) || (defined(__riscv) && __riscv_xlen == 64) return 0; #else #error libc is needed #endif } EOF if compile_prog "" "" "nolibc"; then liburing_nolibc="yes" fi fi print_config "nolibc" "$liburing_nolibc"; ############################################################################# #################################################### # Most Android devices don't have sys/fanotify.h has_fanotify="no" cat > $TMPC << EOF #include int main(void) { return 0; } EOF if compile_prog "" "" "fanotify"; then has_fanotify="yes" fi print_config "has_fanotify" "$has_fanotify" #################################################### ########################################## # check for ublk headers ublk_header="no" cat > $TMPC << EOF #include #include #include int main(int argc, char **argv) { struct ublksrv_ctrl_cmd cmd = { }; cmd.addr = UBLK_U_CMD_START_DEV; return cmd.queue_id; } EOF if compile_prog "" "" "ublk_header"; then ublk_header="yes" fi print_config "ublk_header" "$ublk_header" if test "$liburing_nolibc" = "yes"; then output_sym "CONFIG_NOLIBC" fi if test "$__kernel_rwf_t" = "yes"; then output_sym "CONFIG_HAVE_KERNEL_RWF_T" fi if test "$__kernel_timespec" = "yes"; then output_sym "CONFIG_HAVE_KERNEL_TIMESPEC" fi if test "$open_how" = "yes"; then output_sym "CONFIG_HAVE_OPEN_HOW" fi if test "$statx" = "yes"; then output_sym "CONFIG_HAVE_STATX" fi if test "$glibc_statx" = "yes"; then output_sym "CONFIG_HAVE_GLIBC_STATX" fi if test "$has_cxx" = "yes"; then output_sym "CONFIG_HAVE_CXX" fi if test "$has_ucontext" = "yes"; then output_sym "CONFIG_HAVE_UCONTEXT" fi if test "$stringop_overflow" = "yes"; then output_sym "CONFIG_HAVE_STRINGOP_OVERFLOW" fi if test "$array_bounds" = "yes"; then output_sym "CONFIG_HAVE_ARRAY_BOUNDS" fi if test "$nvme_uring_cmd" = "yes"; then output_sym "CONFIG_HAVE_NVME_URING" fi if test "$has_fanotify" = "yes"; then output_sym "CONFIG_HAVE_FANOTIFY" fi if test "$futexv" = "yes"; then output_sym "CONFIG_HAVE_FUTEXV" fi if test "$ublk_header" = "yes"; then output_sym "CONFIG_HAVE_UBLK_HEADER" fi if test "$use_sanitizer" = "yes"; then output_sym "CONFIG_USE_SANITIZER" print_config "use sanitizer" "yes" else print_config "use sanitizer" "no" fi echo "CC=$cc" >> $config_host_mak print_config "CC" "$cc" echo "CXX=$cxx" >> $config_host_mak print_config "CXX" "$cxx" # generate io_uring_version.h # Reset MAKEFLAGS MAKEFLAGS= MAKE_PRINT_VARS="include Makefile.common\nprint-%%: ; @echo \$(\$*)\n" VERSION_MAJOR=$(printf "$MAKE_PRINT_VARS" | make -s --no-print-directory -f - print-VERSION_MAJOR) VERSION_MINOR=$(printf "$MAKE_PRINT_VARS" | make -s --no-print-directory -f - print-VERSION_MINOR) io_uring_version_h="src/include/liburing/io_uring_version.h" cat > $io_uring_version_h << EOF /* SPDX-License-Identifier: MIT */ #ifndef LIBURING_VERSION_H #define LIBURING_VERSION_H #define IO_URING_VERSION_MAJOR $VERSION_MAJOR #define IO_URING_VERSION_MINOR $VERSION_MINOR #endif EOF # generate compat.h compat_h="src/include/liburing/compat.h" cat > $compat_h << EOF /* SPDX-License-Identifier: MIT */ #ifndef LIBURING_COMPAT_H #define LIBURING_COMPAT_H EOF if test "$__kernel_rwf_t" != "yes"; then cat >> $compat_h << EOF typedef int __kernel_rwf_t; EOF fi if test "$__kernel_timespec" != "yes"; then cat >> $compat_h << EOF #include struct __kernel_timespec { int64_t tv_sec; long long tv_nsec; }; /* is not available, so it can't be included */ #define UAPI_LINUX_IO_URING_H_SKIP_LINUX_TIME_TYPES_H 1 EOF else cat >> $compat_h << EOF #include /* is included above and not needed again */ #define UAPI_LINUX_IO_URING_H_SKIP_LINUX_TIME_TYPES_H 1 EOF fi if test "$open_how" != "yes"; then cat >> $compat_h << EOF #include struct open_how { uint64_t flags; uint64_t mode; uint64_t resolve; }; EOF else cat >> $compat_h << EOF #include EOF fi if [ "$glibc_statx" = "no" ] && [ "$statx" = "yes" ]; then cat >> $compat_h << EOF #include EOF fi if test "$futexv" != "yes"; then cat >> $compat_h << EOF #include #define FUTEX_32 2 #define FUTEX_WAITV_MAX 128 struct futex_waitv { uint64_t val; uint64_t uaddr; uint32_t flags; uint32_t __reserved; }; EOF fi if test "$has_idtype_t" != "yes"; then cat >> $compat_h << EOF typedef enum { P_ALL, /* Wait for any child. */ P_PID, /* Wait for specified process. */ P_PGID /* Wait for members of process group. */ } idtype_t; EOF fi if test "$discard_cmd" != "yes"; then cat >> $compat_h << EOF #include #ifndef BLOCK_URING_CMD_DISCARD #define BLOCK_URING_CMD_DISCARD _IO(0x12, 0) #endif EOF else cat >> $compat_h << EOF #include EOF fi cat >> $compat_h << EOF #endif EOF