# SPDX-License-Identifier: LGPL-3.0-or-later
#-------------------------------------------------------------------------------
#
# Copyright Panasas, 2012
# Contributor: Jim Lieb <jlieb@panasas.com>
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 3 of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
#
#-------------------------------------------------------------------------------
# NFS Ganesha  Cmake

# Current version as of Fedora 16.  Not tested with earlier.

cmake_minimum_required(VERSION 2.6.3)

message( STATUS "cmake version ${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" )

if( "${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" VERSION_GREATER "2.6" )
  if(COMMAND cmake_policy)
      cmake_policy(SET CMP0017 NEW)
  endif(COMMAND cmake_policy)
endif( "${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" VERSION_GREATER "2.6" )

# Find packages and libs we need for building
include(CheckIncludeFiles)
include(CheckLibraryExists)
include(CheckCSourceCompiles)
include(TestBigEndian)

# Set GANESHA_TOP_CMAKE_DIR to this CMakeLists.txt path
set(GANESHA_TOP_CMAKE_DIR ${CMAKE_CURRENT_SOURCE_DIR})

set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${GANESHA_TOP_CMAKE_DIR}/cmake/modules/")

project(nfs-ganesha C CXX)
# Project versioning
set(GANESHA_MAJOR_VERSION 7)
# Minor version is blank for development.  On release, it becomes ".0".  On a
# stable maintenance branch, this becomes ".N" where N is monotonically
# increasing starting at 1.3 Remember to include the "." !!
set(GANESHA_MINOR_VERSION .3)

IF(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")
set(GANESHA_BUILD_RELEASE 1)
ELSE()
set(GANESHA_BUILD_RELEASE 0)
ENDIF(CMAKE_BUILD_TYPE STREQUAL "Release" OR CMAKE_BUILD_TYPE STREQUAL "RelWithDebInfo")

# needs to come after project()
IF(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT OR CMAKE_INSTALL_PREFIX STREQUAL "/usr")
	SET(CMAKE_INSTALL_PREFIX "/usr" CACHE PATH "Install prefix for common files" FORCE)
	message(STATUS "override default CMAKE_INSTALL_PREFIX = ${CMAKE_INSTALL_PREFIX}")
	SET(SYSCONFDIR "/etc" CACHE PATH "Install prefix for common files")
	SET(SYSSTATEDIR "/var" CACHE PATH "Install prefix for common files")
ELSE()
	message(STATUS "was set CMAKE_INSTALL_PREFIX = ${CMAKE_INSTALL_PREFIX}")
	SET(SYSCONFDIR "${CMAKE_INSTALL_PREFIX}/etc" CACHE PATH "Install prefix for common files")
	SET(SYSSTATEDIR "${CMAKE_INSTALL_PREFIX}/var" CACHE PATH "Install prefix for common files")
ENDIF(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT OR CMAKE_INSTALL_PREFIX STREQUAL "/usr")

SET(RUNTIMEDIR "${SYSSTATEDIR}/run/ganesha" CACHE PATH "Runtime directory (for things like pid file, not touched by install)")

# Extra version is for naming development/RC.  It is blank in stable branches
# so it can be available to end-users to name local variants/versions
# If used, it is always of the form "-whateveryouwant"
set(GANESHA_EXTRA_VERSION )

set(GANESHA_VERSION ${GANESHA_MAJOR_VERSION}${GANESHA_MINOR_VERSION}${GANESHA_EXTRA_VERSION})
set(GANESHA_BASE_VERSION ${GANESHA_MAJOR_VERSION}${GANESHA_MINOR_VERSION})

set(VERSION_COMMENT
  "GANESHA file server is 64 bits compliant and supports NFS v3,4.0,4.1 (pNFS) and 9P"
)

# find out which platform we are building on
if(${CMAKE_SYSTEM_NAME} MATCHES "Linux")
  set(LINUX ON)
  set(UNIX ON)
  # Now detects the Linux's distro
  set(DISTRO "UNKNOWN")
  set(LIBEXECDIR "/${CMAKE_INSTALL_PREFIX}/libexec")

  EXECUTE_PROCESS(
      COMMAND awk -F=  "/^NAME=/ { print $2 }" /etc/os-release
      OUTPUT_VARIABLE SYS_RELEASE
      ERROR_QUIET
   )
  EXECUTE_PROCESS(
      COMMAND awk -F=  "/^ID_LIKE=/ { print $2 }" /etc/os-release
      OUTPUT_VARIABLE ID_LIKE
   )
# Red Hat Enterprise Linux versions before 7.0 will be detected as UNKNOWN

  if( ${SYS_RELEASE} MATCHES "Red Hat" )
     message( STATUS "Detected a Linux Red Hat machine" )
     set(DISTRO "RED_HAT")
  elseif( ${SYS_RELEASE} MATCHES "Fedora" )
     message( STATUS "Detected a Linux Fedora machine" )
     set(DISTRO "FEDORA")
  elseif( ${SYS_RELEASE} MATCHES "SLES" )
     message( STATUS "Detected a Linux SLES machine" )
     set(DISTRO "SLES")
     set(LIBEXECDIR "/${CMAKE_INSTALL_PREFIX}/lib")
  elseif( ${SYS_RELEASE} MATCHES "openSUSE Leap" )
     message( STATUS "Detected a Linux openSUSE Leap machine" )
     set(DISTRO "SLES")
     set(LIBEXECDIR "/${CMAKE_INSTALL_PREFIX}/lib")
  elseif( ${SYS_RELEASE} MATCHES "openSUSE Tumbleweed" )
     message( STATUS "Detected a Linux openSUSE Tumbleweed machine" )
     set(DISTRO "SLES")
     set(LIBEXECDIR "/${CMAKE_INSTALL_PREFIX}/lib")
  elseif( (${SYS_RELEASE} MATCHES "Debian GNU/Linux") OR (${SYS_RELEASE} MATCHES "Ubuntu") )
     message( STATUS "Detected a Linux Debian base machine" )
     set(DISTRO "DEBIAN")
     set(LIBEXECDIR "/${CMAKE_INSTALL_PREFIX}/lib")
  else( ${SYS_RELEASE} MATCHES "Red Hat" )
     if( ${ID_LIKE} MATCHES "suse" )
         message( STATUS "Detected a SUSE Build server machine" )
         set(DISTRO "SLES")
         set(LIBEXECDIR "/usr/lib")
     else( ${ID_LIKE} MATCHES "suse" )
         message( STATUS "Detected an UNKNOWN Linux machine" )
         set(DISTRO "UNKNOWN")
     endif( ${ID_LIKE} MATCHES "suse" )
  endif( ${SYS_RELEASE} MATCHES "Red Hat" )
endif(${CMAKE_SYSTEM_NAME} MATCHES "Linux")

if(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")
  set(BSDBASED ON)
  set(FREEBSD ON)
  set(UNIX ON)
# On FreeBSD libc doesn't directly provide libexecinfo, so we have to find it
  set(USE_EXECINFO ON)
  set(LIBEXECDIR "/${CMAKE_INSTALL_PREFIX}/libexec")
endif(${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD")

if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
  set(BSDBASED ON)
  set(DARWIN ON)
  set(UNIX ON)
  set(LIBEXECDIR "/${CMAKE_INSTALL_PREFIX}/libexec")
endif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")

if(${CMAKE_SYSTEM_NAME} MATCHES "Windows")
  set(WINDOWS ON)
endif(${CMAKE_SYSTEM_NAME} MATCHES "Windows")

if(DARWIN)
  # Apple's /usr/bin/ld doesn't use the same flags for specifying treatment of
  # undefined symbols, and its defaults are opposite of GNU's and LLVM's ld.
  set(LDFLAG_ALLOW_UNDEF "-Wl,-undefined,suppress")
  set(LDFLAG_DISALLOW_UNDEF "-Wl,-undefined,error")
elseif(FREEBSD OR LINUX)
  # llvm-ld seems to be missing a flag to explicitly allow undefined, but this
  # is the default anyway for both llvm-ld and GNU ld.
  set(LDFLAG_ALLOW_UNDEF "")
  set(LDFLAG_DISALLOW_UNDEF "-Wl,--no-undefined")
endif(DARWIN)

# Identify the host we are building on
EXECUTE_PROCESS( COMMAND hostname
  OUTPUT_VARIABLE BUILD_HOST_NAME
  OUTPUT_STRIP_TRAILING_WHITESPACE
  )

find_package(Toolchain REQUIRED)
find_package(Sanitizers)

# Add maintainer mode for (mainly) strict builds
include(${GANESHA_TOP_CMAKE_DIR}/cmake/maintainer_mode.cmake)

# For libraries that provide pkg-config files
include(FindPkgConfig)

# For our option system
include(${GANESHA_TOP_CMAKE_DIR}/cmake/goption.cmake)

goption(USE_RELATIVE_FILE_PATHS_IN_LOGS "Use relative file paths in log files" ON)
gopt_test(USE_RELATIVE_FILE_PATHS_IN_LOGS)

include(CheckCCompilerFlag)
CHECK_C_COMPILER_FLAG("-fmacro-prefix-map=old=new" HAS_MACRO_PREFIX_MAP_FLAG)

if(HAS_MACRO_PREFIX_MAP_FLAG AND USE_RELATIVE_FILE_PATHS_IN_LOGS)
  add_compile_options(-fmacro-prefix-map=${GANESHA_TOP_CMAKE_DIR}/=./)
endif()

# If we are in a git tree, then this CMakeLists.txt is in "src/" and go .git is in "src/.."
IF( EXISTS ${GANESHA_TOP_CMAKE_DIR}/../.git/HEAD  )
  message( STATUS "Compilation from within a git repository. Using git rev-parse HEAD")
  EXECUTE_PROCESS( COMMAND git rev-parse HEAD
		   WORKING_DIRECTORY ${GANESHA_TOP_CMAKE_DIR}
		   OUTPUT_STRIP_TRAILING_WHITESPACE
		   ERROR_QUIET
                   OUTPUT_VARIABLE _GIT_HEAD_COMMIT)
  EXECUTE_PROCESS( COMMAND git describe --long
                   WORKING_DIRECTORY  ${GANESHA_TOP_CMAKE_DIR}
		   OUTPUT_STRIP_TRAILING_WHITESPACE
		   ERROR_QUIET
                   OUTPUT_VARIABLE _GIT_DESCRIBE)

ELSE( EXISTS ${GANESHA_TOP_CMAKE_DIR}/../.git/HEAD  )
  message( STATUS "Outside a git repository, use saved data" )
  EXECUTE_PROCESS( COMMAND ${GANESHA_TOP_CMAKE_DIR}/cmake/githead_from_path.sh  ${GANESHA_TOP_CMAKE_DIR}
		   WORKING_DIRECTORY ${GANESHA_TOP_CMAKE_DIR}
		   OUTPUT_STRIP_TRAILING_WHITESPACE
		   ERROR_QUIET
                   OUTPUT_VARIABLE _GIT_HEAD_COMMIT)

  EXECUTE_PROCESS( COMMAND ${GANESHA_TOP_CMAKE_DIR}/cmake/gitdesc_from_path.sh ARGS ${GANESHA_TOP_CMAKE_DIR}
		   WORKING_DIRECTORY ${GANESHA_TOP_CMAKE_DIR}
		   OUTPUT_STRIP_TRAILING_WHITESPACE
		   ERROR_QUIET
                   OUTPUT_VARIABLE _GIT_DESCRIBE)

ENDIF( EXISTS ${GANESHA_TOP_CMAKE_DIR}/../.git/HEAD  )

STRING(SUBSTRING ${_GIT_HEAD_COMMIT} 0  7 _GIT_HEAD_COMMIT_ABBREV )

if (BSDBASED)
#default gcc doesn't like using -Wuninitialized without -O on FreeBSD
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O2 -ggdb")
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-omit-frame-pointer")
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-optimize-sibling-calls")
endif(BSDBASED)

if (FREEBSD)
    set(PLATFORM "FREEBSD")
    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--export-dynamic")
    set(OS_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/include/os/freebsd")
endif(FREEBSD)

if (DARWIN)
    set(PLATFORM "DARWIN")
    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-export_dynamic")
    set(OS_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/include/os/darwin")
endif(DARWIN)

if (LINUX)
    set(PLATFORM "LINUX")
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -D_LARGEFILE64_SOURCE -D_FILE_OFFSET_BITS=64")
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fno-strict-aliasing")
    set(OS_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/include/os/linux")
endif(LINUX)

if (MSVC)
   add_definitions(-D_CRT_SECURE_NO_WARNINGS)
endif(MSVC)

# Library path name
get_property(USE_LIB64 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS)
if (USE_LIB64)
	set(LIB_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/lib64 CACHE PATH
		"Specify name of libdir inside install path")
else (USE_LIB64)
	set(LIB_INSTALL_DIR ${CMAKE_INSTALL_PREFIX}/lib CACHE PATH
		"Specify name of libdir inside install path")
endif (USE_LIB64)

IF(FSAL_DESTINATION)
    set( FSAL_DESTINATION ${FSAL_DESTINATION} )
ELSE()
    set( FSAL_DESTINATION "${LIB_INSTALL_DIR}/ganesha")
ENDIF()

if (CMAKE_SYSTEM_PROCESSOR MATCHES "unknown")
  # uname -p is broken on this system.  Try uname -m
  EXECUTE_PROCESS( COMMAND uname -m
		   OUTPUT_STRIP_TRAILING_WHITESPACE
		   ERROR_QUIET
		   OUTPUT_VARIABLE ARCH)
else (CMAKE_SYSTEM_PROCESSOR MATCHES "unknown")
  set(ARCH ${CMAKE_SYSTEM_PROCESSOR})
endif (CMAKE_SYSTEM_PROCESSOR MATCHES "unknown")

if (ARCH MATCHES "x86_64")
  # Nothing special to do for x86_64
elseif (ARCH MATCHES "i386")
  # Nothing special to do for i386
elseif (ARCH MATCHES "mips")
  set(SYSTEM_LIBRARIES "-latomic" ${SYSTEM_LIBRARIES})
else()
  message(WARNING "Unhandled architecture ${ARCH}")
endif ()

# FSAL selection
# FSALs which are enabled by default but could be disabled
# during the build
goption(USE_FSAL_PROXY_V4 "build PROXY_V4 FSAL shared library" ON)
goption(USE_FSAL_PROXY_V3 "build PROXY_V3 FSAL shared library" ON)
goption(USE_FSAL_VFS "build VFS FSAL shared library" ON)
goption(USE_FSAL_LUSTRE "build LUSTRE FSAL shared library" ON)
goption(USE_FSAL_LIZARDFS "build LIZARDFS FSAL shared library" ON)
goption(USE_FSAL_KVSFS "build KVSFS FSAL shared library" ON)
goption(USE_FSAL_CEPH "build CEPH FSAL shared library" ON)
goption(USE_FSAL_GPFS "build GPFS FSAL" ON)
goption(USE_FSAL_XFS "build XFS support in VFS FSAL" ON)
goption(USE_FSAL_GLUSTER "build GLUSTER FSAL shared library" ON)
goption(USE_FSAL_NULL "build NULL FSAL shared library" ON)
goption(USE_FSAL_RGW "build RGW FSAL shared library" ON)
goption(USE_FSAL_MEM "build Memory FSAL shared library" ON)
goption(USE_FSAL_SAUNAFS "build SAUNAFS FSAL shared library" ON)

# Internal capability required by some FSALs
option(GSH_CAN_HOST_LOCAL_FS "Ganesha supports hosting local filesystems" ON)

# Monitoring stack.
goption(USE_MONITORING "Enable monitoring stack" ON)
gopt_test(USE_MONITORING)

# nTIRPC
option(USE_SYSTEM_NTIRPC "Use the system nTIRPC, rather than the submodule" OFF)
option (USE_GSS "enable RPCSEC_GSS support" ON)
option(TIRPC_EPOLL "platform supports EPOLL or emulation" ON)

# Build configure options
goption(USE_DBUS "enable DBUS protocol support" ON)

# Various DBUS enabled features
option(USE_CB_SIMULATOR "enable callback simulator thread" OFF)

goption(USE_NFSIDMAP "Use of libnfsidmap for name resolution" ON)
option(ENABLE_ERROR_INJECTION "enable error injection" OFF)
goption(ENABLE_VFS_POSIX_ACL "Enable NFSv4 to POSIX ACL mapping for VFS" OFF)
option(ENABLE_VFS_DEBUG_ACL "Enable debug ACL store for VFS" OFF)
option(ENABLE_RFC_ACL "Use all RFC ACL checks" OFF)
option(USE_TOOL_MULTILOCK "build multilock tool" OFF)

# Electric Fence (-lefence) link flag
goption(USE_EFENCE "link with efence memory debug library" OFF)

# These are -D_FOO options, why ???  should be flags??
option(_NO_TCP_REGISTER "disable registration of tcp services on portmapper" OFF)
option(RPCBIND "enable registration with rpcbind" ON)
option(DEBUG_SAL "enable debugging of SAL by keeping list of all locks, stateids, and state owners" OFF)
option(_VALGRIND_MEMCHECK "Initialize buffers passed to GPFS ioctl that valgrind doesn't understand" OFF)
option(ENABLE_LOCKTRACE "Enable lock trace" OFF)
goption(PROXYV4_HANDLE_MAPPING "enable NFSv3 handle mapping for PROXY_V4 FSAL" OFF)
option(DEBUG_MDCACHE "Add various asserts to mdcache" OFF)
option(ENABLE_QOS "QOS feature enablement" OFF)

# Debug symbols (-g) build flag
option(DEBUG_SYMS "include debug symbols to binaries (-g option)" OFF)

# Add coverage information to build tree
option(COVERAGE "add flag to generate coverage data at runtime" OFF)

option(ENFORCE_GCC "enforce gcc as a the C compiler used for the project" OFF)

# Define CPACK component (to deal with sub packages)
set(CPACK_COMPONENTS_ALL daemon fsal headers tools)
set(CPACK_COMPONENT_DAEMON_DISPLAY_NAME "NFS-Ganesha daemon")
if (USE_SYSTEM_NTIRPC)
  # Don't include libntirpc in the tarball
  set(CPACK_SOURCE_IGNORE_FILES "libntirpc")
else(USE_SYSTEM_NTIRPC)
  # Don't include libntirpc's spec file; this can confuse rpmbuild
  set(CPACK_SOURCE_IGNORE_FILES "libntirpc.spec$")
endif(USE_SYSTEM_NTIRPC)

# Include custom config and cpack module
include(${GANESHA_TOP_CMAKE_DIR}/cmake/cpack_config.cmake)
include(CPack)

# MSPAC support -lwbclient link flag
goption(_MSPAC_SUPPORT "enable mspac Winbind support" ON)

# CUnit
goption(USE_CUNIT "Use Cunit test framework" OFF)

# GTest
goption(USE_GTEST "Use Google Test test framework" OFF)
gopt_test(USE_GTEST)
if(USE_GTEST)
  find_package(LTTng ${USE_GTEST_REQUIRED})
  find_package(Gperftools ${USE_GTEST_REQUIRED})
  find_package(GTest ${USE_GTEST_REQUIRED})
  find_package(Boost 1.34.0 ${USE_GTEST_REQUIRED} COMPONENTS filesystem program_options)
  if((NOT LTTNG_FOUND) OR (NOT GPERFTOOLS_FOUND) OR (NOT GTEST_FOUND))
    message(WARNING "Couldn't find GTest dependencies. Disabling USE_GTEST")
    set(USE_GTEST OFF)
  endif((NOT LTTNG_FOUND) OR (NOT GPERFTOOLS_FOUND) OR (NOT GTEST_FOUND))
endif(USE_GTEST)

# Enable NFS Over RDMA Support
option(USE_NFS_RDMA "enable NFS/RDMA support" OFF)

# Enable 9P Support
option(USE_9P "enable 9P support" ON)
option(USE_9P_RDMA "enable 9P_RDMA support" OFF)

# Enable NFSv3 Support
option(USE_NFS3 "enable NFSv3 support" ON)

if(USE_NFS3)
    # Enable NLM Support
    option(USE_NLM "enable NLM support" ON)
    # Enable NFSACL3 protocol extension support
    option(USE_NFSACL3 "enable NFSACLv3 support" ON)
else(USE_NFS3)
    # Disable NLM Support
    set(USE_NLM OFF)
    # Disable NFSACL3 protocol extension support
    set(USE_NFSACL3 OFF)
endif(USE_NFS3)

# Enable RQUOTA support
option(USE_RQUOTA "enable RQUOTA support" ON)

# AF_VSOCK host support (NFS)
option(USE_VSOCK "enable AF_VSOCK listener" OFF)
if(USE_VSOCK)
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DRPC_VSOCK")
endif(USE_VSOCK)

# This option will trigger "long distro name" aka name that contains git information
option(DISTNAME_HAS_GIT_DATA "Distribution package's name carries git data" OFF )

# Build and package Python admin scripts for managing via DBus
goption(USE_ADMIN_TOOLS "Package Admin scripts" OFF)

# Build and package Python gui admin scripts for managing via DBus
goption(USE_GUI_ADMIN_TOOLS "Package GUI Admin scripts" ON)

# Enable LTTng tracing
goption(USE_LTTNG "Enable LTTng tracing" OFF)

# Build man page.
goption(USE_MAN_PAGE "Build MAN page" OFF)

# Enable Rados KV store for recovery
goption(USE_RADOS_RECOV "Enable Rados KV Recovery" ON)

# Enable RADOS URL config file sections
goption(RADOS_URLS "Enable config file inclusion from RADOS objects" ON)

# Enable CephFS POSIX ACL
goption(CEPHFS_POSIX_ACL "Enable CephFS POSIX ACL" ON)

# Enable NFSv4 and POSIX acls mapping
option(USE_ACL_MAPPING "Build NFSv4 to POSIX ACL mapping" OFF)

#
# End build options
#

# Choose a shortcut build config

IF(BUILD_CONFIG)
  INCLUDE(
  ${GANESHA_TOP_CMAKE_DIR}/cmake/build_configurations/${BUILD_CONFIG}.cmake)
ENDIF()

IF(DEBUG_SYMS)
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -O0 -g")
ENDIF(DEBUG_SYMS)

IF(COVERAGE)
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} --coverage")
ENDIF(COVERAGE)

# Set what's needed is GCC is enforced
IF(ENFORCE_GCC)
    set(CMAKE_COMPILER_IS_GNUCXX TRUE)
    set(CMAKE_C_COMPILER gcc)
ENDIF(ENFORCE_GCC)

include(CheckSymbolExists)
check_symbol_exists(__GLIBC__ features.h HAVE_GLIBC)
if(HAVE_GLIBC)
  add_definitions(-D_GNU_SOURCE=1)
endif(HAVE_GLIBC)

IF(USE_FSAL_GLUSTER)
  IF(GLUSTER_PREFIX)
    set(GLUSTER_PREFIX ${GLUSTER_PREFIX} CACHE PATH "Path to Gluster installation")
    LIST(APPEND CMAKE_PREFIX_PATH "${GLUSTER_PREFIX}")
    LIST(APPEND CMAKE_LIBRARY_PATH "${GLUSTER_PREFIX}/lib")
    LIST(APPEND CMAKE_LIBRARY_PATH "${GLUSTER_PREFIX}/local/lib")
    LIST(APPEND CMAKE_LIBRARY_PATH "${GLUSTER_PREFIX}/local/lib64")
    LIST(APPEND CMAKE_REQUIRED_INCLUDES "${GLUSTER_PREFIX}/include")
  ELSE()
    set(GLUSTER_PREFIX "/usr" CACHE PATH "Path to Gluster installation")
  ENDIF()
ENDIF()

IF(KRB5_PREFIX)
  set(KRB5_PREFIX ${KRB5_PREFIX} CACHE PATH "Path to Krb5 installation")
  LIST(APPEND CMAKE_PREFIX_PATH "${KRB5_PREFIX}")
  LIST(APPEND CMAKE_LIBRARY_PATH "${KRB5_PREFIX}/lib")
ENDIF()

if(SAMBA4_PREFIX)
  set(SAMBA4_PREFIX ${SAMBA4_PREFIX} CACHE PATH "Path to Samba4 installation")
  LIST(APPEND CMAKE_PREFIX_PATH "${SAMBA4_PREFIX}")
  LIST(APPEND CMAKE_LIBRARY_PATH "${SAMBA4_PREFIX}/lib")
endif()

IF(MOOSHIKA_PREFIX)
  set(MOOSHIKA_PREFIX ${MOOSHIKA_PREFIX} CACHE PATH "Path to Mooshika installation")
  set(ENV{PKG_CONFIG_PATH} "${PKG_CONFIG_PATH}:${MOOSHIKA_PREFIX}/lib/pkgconfig")
ENDIF()

if(USE_NFS_RDMA OR USE_9P_RDMA)
  check_library_exists(rdmacm rdma_create_qp "" RDMACM_FOUND)
  check_library_exists(ibverbs ibv_alloc_pd "" IBVERBS_FOUND)
  if(RDMACM_FOUND AND IBVERBS_FOUND)
    find_package(RDMA REQUIRED)
    include_directories(${RDMA_INCLUDE_DIR})
    set(SYSTEM_LIBRARIES ${SYSTEM_LIBRARIES} ${RDMA_LIBRARY})
  else(RDMACM_FOUND AND IBVERBS_FOUND)
    set(USE_NFS_RDMA OFF)
    set(USE_9P_RDMA OFF)
    message(WARNING "Could not find RDMA dependencies(RDMACM=${RDMACM_FOUND} IBVERBS=${IBVERBS_FOUND}), disabling RDMA Support")
  endif(RDMACM_FOUND AND IBVERBS_FOUND)
endif(USE_NFS_RDMA OR USE_9P_RDMA)

if(USE_9P_RDMA AND NOT USE_9P)
  message(WARNING "The support of 9P/RDMA needs 9P protocol support. Enabling 9P")
  set(USE_9P ON)
endif(USE_9P_RDMA AND NOT USE_9P)

IF(ALLOCATOR)
  set(ALLOCATOR ${ALLOCATOR} CACHE STRING "memory allocator: jemalloc|tcmalloc|libc")
ELSE()
  if( "${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" VERSION_GREATER "2.6" )
    set(ALLOCATOR "jemalloc" CACHE STRING
      "specify the memory allocator to use: jemalloc|tcmalloc|libc")
  else("${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" VERSION_GREATER "2.6" )
    set(ALLOCATOR "libc" CACHE STRING
      "specify the memory allocator to use: jemalloc|tcmalloc|libc")
  endif( "${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" VERSION_GREATER "2.6" )
ENDIF()

check_include_files(strings.h HAVE_STRINGS_H)
check_include_files(string.h HAVE_STRING_H)

if(HAVE_STRING_H AND HAVE_STRINGS_H)
  # we have all the libraries and include files to use string.h
  set(HAVE_STRNLEN ON)
endif(HAVE_STRING_H AND HAVE_STRINGS_H)

IF(_VALGRIND_MEMCHECK)
  check_include_files(valgrind/memcheck.h HAVE_MEMCHECK_H)
  if(NOT HAVE_MEMCHECK_H)
	  message(FATAL_ERROR "Cannot find valgrind/memcheck.h, install valgrind-devel package to enable _VALGRIND_MEMCHECK")
  ENDIF(NOT HAVE_MEMCHECK_H)
ENDIF(_VALGRIND_MEMCHECK)

TEST_BIG_ENDIAN(BIGENDIAN)
if(NOT ${BIGENDIAN})
  set(LITTLEEND ON)
endif(NOT ${BIGENDIAN})

if( "${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" VERSION_GREATER "2.6" )
  find_package(Threads REQUIRED)
endif( "${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" VERSION_GREATER "2.6" )

if (USE_GSS)
  find_package(Krb5 REQUIRED gssapi)
  check_include_files(gssapi.h HAVE_GSSAPI_H)
  if (NOT HAVE_GSSAPI_H)
    # Debian/Ubuntu 12 magic
    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -I/usr/include/mit-krb5/")
    check_include_files(gssapi.h HAVE_GSSAPI_H)
  endif(NOT HAVE_GSSAPI_H)

  if(KRB5_FOUND AND HAVE_GSSAPI_H)
    set(HAVE_KRB5 ON)
    set(_HAVE_GSSAPI ON)
  else(KRB5_FOUND AND HAVE_GSSAPI_H)
    if (NOT KRB5_FOUND)
      message(FATAL_ERROR "Cannot find kerberos libraries")
    endif(NOT KRB5_FOUND)
    if (NOT HAVE_GSSAPI_H)
      message(FATAL_ERROR "Cannot find GSS libraries")
    endif (NOT HAVE_GSSAPI_H)
  endif(KRB5_FOUND AND HAVE_GSSAPI_H)
endif(USE_GSS)

set(WITH_PYTHON3 "3" CACHE STRING "build with specified python3 version")
gopt_test(USE_ADMIN_TOOLS)
if (USE_ADMIN_TOOLS)
  find_package (Python3 ${WITH_PYTHON3} EXACT REQUIRED COMPONENTS Interpreter)
  if (NOT Python3_Interpreter_FOUND)
    message(WARNING "Cannot find python. Disablin admin tools")
    set(USE_ADMIN_TOOLS OFF)
  endif (NOT Python3_Interpreter_FOUND)
endif (USE_ADMIN_TOOLS)

gopt_test(USE_GUI_ADMIN_TOOLS)
if (USE_ADMIN_TOOLS)
  if (USE_GUI_ADMIN_TOOLS)
    set(PYQTX PyQt5)
    find_program(PYUIC NAMES pyuic5 DOC "PyQT UI-compiler executable")
    if (NOT PYUIC)
      set(PYQTX PyQt4)
      find_program(PYUIC NAMES pyuic4 DOC "PyQT UI-compiler executable")
    endif (NOT PYUIC)
    if (NOT PYUIC)
      if (USE_GUI_ADMIN_TOOLS_REQUIRED)
	message(FATAL_ERROR "Cannot find PyQt but GUI admin tools requested on command line")
      else (USE_GUI_ADMIN_TOOLS_REQUIRED)
	message(WARNING "Cannot find PyQt4 or PyQt5.  Disabling GUI admin tools")
	set(USE_GUI_ADMIN_TOOLS OFF)
      endif (USE_GUI_ADMIN_TOOLS_REQUIRED)
    endif (NOT PYUIC)
  endif (USE_GUI_ADMIN_TOOLS)
endif (USE_ADMIN_TOOLS)

gopt_test(USE_MAN_PAGE)
if (USE_MAN_PAGE)
  find_program(SPHINX_BUILD sphinx-build)
  if(NOT SPHINX_BUILD)
    find_program(SPHINX_BUILD sphinx-build-3)
  endif(NOT SPHINX_BUILD)
  if(NOT SPHINX_BUILD)
    if (USE_MAN_PAGE_REQUIRED)
      message(FATAL_ERROR "Can't find sphinx-build but man pages requested on command line")
    else (USE_MAN_PAGE_REQUIRED)
      message(WARNING "Can't find sphinx-build. Disabling man pages")
      set(USE_MAN_PAGE OFF)
    endif (USE_MAN_PAGE_REQUIRED)
  endif(NOT SPHINX_BUILD)
endif(USE_MAN_PAGE)

# POSIX ACLs - these may be used in multiple places
find_package(LibACL)
if (NOT HAVE_LIBACL)
      message(FATAL_ERROR "Can't find libacl")
endif (NOT HAVE_LIBACL)

# Validate fsal dependencies

gopt_test(USE_FSAL_PROXY_V4)
if (USE_FSAL_PROXY_V4)
  # PROXY_V4 has no deps of it's own, but it has a dependent option
  # PROXY_V4 handle mapping needs sqlite3
  gopt_test(PROXYV4_HANDLE_MAPPING)
  if(PROXYV4_HANDLE_MAPPING)
    check_include_files(sqlite3.h HAVE_SQLITE3_H)
    check_library_exists(
      sqlite3
      sqlite3_open
      ""
      HAVE_SQLITE3
      )
    if(NOT HAVE_SQLITE3 OR NOT HAVE_SQLITE3_H)
      if(PROXYV4_HANDLE_MAPPING_REQUIRED)
	message(FATAL_ERROR "Cannot find sqlite3.h or the library but proxyv4 handle mapping requested on command line")
      else(PROXYV4_HANDLE_MAPPING_REQUIRED)
	message(WARNING "Cannot find sqlite3.h or the library. Disabling proxyv4 handle mapping")
	set(PROXYV4_HANDLE_MAPPING OFF)
      endif(PROXYV4_HANDLE_MAPPING_REQUIRED)
    endif(NOT HAVE_SQLITE3 OR NOT HAVE_SQLITE3_H)
  endif(PROXYV4_HANDLE_MAPPING)
endif (USE_FSAL_PROXY_V4)

gopt_test(USE_FSAL_VFS)
if(USE_FSAL_VFS)
  # VFS has an optional dependency for libbtrfsutil
  find_library(BTRFSUTIL_LIB btrfsutil)
  if (BTRFSUTIL_LIB)
    message(STATUS "Found BTRFS Util library: ${BTRFSUTIL_LIB}")
    set(USE_BTRFSUTIL ON)
    set(SYSTEM_LIBRARIES ${BTRFSUTIL_LIB} ${SYSTEM_LIBRARIES})
  endif (BTRFSUTIL_LIB)
  if(ENABLE_VFS_DEBUG_ACL)
    set(ENABLE_VFS_ACL ON)
    if(ENABLE_VFS_POSIX_ACL)
      set(ENABLE_VFS_POSIX_ACL OFF)
      message(WARNING "ENABLE_VFS_DEBUG_ACL is on, so disabling ENABLE_VFS_POSIX_ACL")
    endif(ENABLE_VFS_POSIX_ACL)
  else(ENABLE_VFS_DEBUG_ACL)
    # POSIX ACL support?
    gopt_test(ENABLE_VFS_POSIX_ACL)
    if(ENABLE_VFS_POSIX_ACL)
      if(NOT HAVE_LIBACL)
	set(ENABLE_VFS_POSIX_ACL OFF)
	message(WARNING "Could not find libacl")
      endif(NOT HAVE_LIBACL)
      if(NOT HAVE_SYS_ACL_H)
	set(ENABLE_VFS_POSIX_ACL OFF)
	message(WARNING "Could not find sys/acl.h")
      endif(NOT HAVE_SYS_ACL_H)
      if(NOT (HAVE_ACL_GET_FD_NP OR LINUX))
	set(ENABLE_VFS_POSIX_ACL OFF)
	message(WARNING "Could not find acl_get_fd_np() and not Linux")
      endif(NOT (HAVE_ACL_GET_FD_NP OR LINUX))
      if(NOT (HAVE_ACL_SET_FD_NP OR LINUX))
	set(ENABLE_VFS_POSIX_ACL OFF)
	message(WARNING "Could not find acl_set_fd_np() and not Linux")
      endif(NOT (HAVE_ACL_SET_FD_NP OR LINUX))
      if(ENABLE_VFS_POSIX_ACL)
	set(ENABLE_VFS_ACL ON)
	set(USE_ACL_MAPPING ON)
	# libacl only required on Linux
	set(LibACL_FIND_REQUIRED HAVE_LIBACL)
      else(ENABLE_VFS_POSIX_ACL)
	if(ENABLE_VFS_POSIX_ACL_REQUIRED)
	  message(FATAL_ERROR "Missing VFS FSAL prerequisites, but requested on command line")
	else(ENABLE_VFS_POSIX_ACL_REQUIRED)
	  message(WARNING "Missing VFS FSAL prerequisites, disabling ENABLE_VFS_POSIX_ACL")
	endif(ENABLE_VFS_POSIX_ACL_REQUIRED)
      endif(ENABLE_VFS_POSIX_ACL)
    endif(ENABLE_VFS_POSIX_ACL)
  endif(ENABLE_VFS_DEBUG_ACL)
endif(USE_FSAL_VFS)

gopt_test(USE_FSAL_LUSTRE)
if(USE_FSAL_LUSTRE)
    ########### lustre hsm version test ##########
    # Lustre/HSM feature needs Lustre 2.5.0.
    # As some hsm calls were already landed as empty nutshells in 2.4
    # we rely on this new call of 2.5.0: llapi_hsm_state_get_fd().
    ##############################################
    CHECK_LIBRARY_EXISTS(lustreapi llapi_hsm_state_get_fd "" USE_LLAPI)
    if(NOT USE_LLAPI)
      if(USE_FSAL_LUSTRE_REQUIRED)
	message(FATAL_ERROR "Cannot find lustreapi, but requested on command line")
      else(USE_FSAL_LUSTRE_REQUIRED)
	message(WARNING "Cannot find lustreapi. We will only build a dummy lustre fsal.")
      endif(USE_FSAL_LUSTRE_REQUIRED)
    endif(NOT USE_LLAPI)
endif(USE_FSAL_LUSTRE)

gopt_test(USE_FSAL_LIZARDFS)
if(USE_FSAL_LIZARDFS)
  find_library(LIZARDFS_CLIENT_LIB lizardfs-client)
  if (LIZARDFS_CLIENT_LIB)
    message(STATUS "Found LizardFS client library: ${LIZARDFS_CLIENT_LIB}")
  else(LIZARDFS_CLIENT_LIB)
    message(WARNING "Cannot find LizardFS client lib. Disabling lizardfs fsal")
    set(USE_FSAL_LIZARDFS OFF)
  endif(LIZARDFS_CLIENT_LIB)
endif(USE_FSAL_LIZARDFS)

gopt_test(USE_FSAL_KVSFS)
if(USE_FSAL_KVSFS)
  find_library(KVSNS_LIB kvsns)
  if (KVSNS_LIB)
    message(STATUS "Found KVSNS library: ${KVSNS_LIB}")
  else (KVSNS_LIB)
    message(WARNING "Cannot find libkvsns. Disabling KVSNS fsal")
    set(USE_FSAL_KVSFS OFF)
  endif (KVSNS_LIB)
endif(USE_FSAL_KVSFS)

gopt_test(USE_FSAL_CEPH)
if(USE_FSAL_CEPH)
  message(STATUS ${USE_FSAL_CEPH_REQUIRED})
  find_package(CEPHFS ${USE_FSAL_CEPH_REQUIRED})
  if(NOT CEPHFS_FOUND)
    message(WARNING "Cannot find CEPH runtime.  Disabling CEPH fsal build")
    set(USE_FSAL_CEPH OFF)
  endif(NOT CEPHFS_FOUND)
  gopt_test(CEPHFS_POSIX_ACL)
  if(CEPHFS_POSIX_ACL)
    if(HAVE_LIBACL)
      set(USE_ACL_MAPPING ON)
    else(HAVE_LIBACL)
      set(CEPHFS_POSIX_ACL OFF)
      message(STATUS "Could not find libacl, disabling CephFS POSIX ACL")
    endif(HAVE_LIBACL)
  endif(CEPHFS_POSIX_ACL)
endif(USE_FSAL_CEPH)

gopt_test(USE_NFSACL3)
  if(USE_NFSACL3)
    if(HAVE_LIBACL)
      set(USE_ACL_MAPPING ON)
    else(HAVE_LIBACL)
      set(USE_NFSACL3 OFF)
      message(STATUS "Could not find libacl, disabling USE_NFSACL3")
    endif(HAVE_LIBACL)
  endif(USE_NFSACL3)

gopt_test(USE_FSAL_GPFS)

gopt_test(USE_FSAL_XFS)
if(USE_FSAL_XFS)
  if(EXISTS /lib/libhandle.so)
    check_library_exists(handle "open_by_handle" "/./lib" HAVE_XFS_LIB)
    if(HAVE_XFS_LIB)
      set(PATH_LIBHANDLE "/lib/libhandle.so" CACHE INTERNAL "debian stretch and ubuntu xenial hack")
    endif(HAVE_XFS_LIB)
  else(EXISTS /lib/libhandle.so)
    check_library_exists(handle "open_by_handle" "" HAVE_XFS_LIB)
  endif(EXISTS /lib/libhandle.so)
  check_include_files("xfs/xfs.h" HAVE_XFS_H)
  if((NOT HAVE_XFS_LIB) OR (NOT HAVE_XFS_H))
    if(USE_FSAL_XFS_REQUIRED)
      message(FATAL_ERROR "Cannot find XFS runtime, but requested on command line.")
    else(USE_FSAL_XFS_REQUIRED)
      message(WARNING "Cannot find XFS runtime. Disabling XFS build")
      set(USE_FSAL_XFS OFF)
    endif(USE_FSAL_XFS_REQUIRED)
  endif((NOT HAVE_XFS_LIB) OR (NOT HAVE_XFS_H))
endif(USE_FSAL_XFS)

# VFS, GPFS, LUSTRE, and XFS require GSH_CAN_HOST_LOCAL_FS
if(NOT GSH_CAN_HOST_LOCAL_FS)
  if((USE_FSAL_VFS AND USE_FSAL_VFS_REQUIRED) OR
     (USE_FSAL_GPFS AND USE_FSAL_GPFS_REQUIRED) OR
     (USE_FSAL_LUSTRE AND USE_FSAL_LUSTRE_REQUIRED) OR
     (USE_FSAL_XFS AND USE_FSAL_XFS_REQUIRED))
    message(FATAL_ERROR "USE_FSAL_VFS, _GPFS, _LUSTRE, or _XFS requested but local FS hosting is not enabled")
  endif((USE_FSAL_VFS AND USE_FSAL_VFS_REQUIRED) OR
        (USE_FSAL_GPFS AND USE_FSAL_GPFS_REQUIRED) OR
        (USE_FSAL_LUSTRE AND USE_FSAL_LUSTRE_REQUIRED) OR
        (USE_FSAL_XFS AND USE_FSAL_XFS_REQUIRED))

  set(USE_FSAL_VFS OFF)
  set(USE_FSAL_GPFS OFF)
  set(USE_FSAL_LUSTRE OFF)
  set(USE_FSAL_XFS OFF)
endif(NOT GSH_CAN_HOST_LOCAL_FS)

gopt_test(USE_FSAL_GLUSTER)
if(USE_FSAL_GLUSTER)
  find_package(PkgConfig)
  IF(GLUSTER_PREFIX)
    set(ENV{PKG_CONFIG_PATH} "${PKG_CONFIG_PATH}:${GLUSTER_PREFIX}/lib/pkgconfig")
  ENDIF(GLUSTER_PREFIX)
  # pkg_check_modules doesn't fatal error on REQUIRED, so handle it ourselves
  pkg_check_modules(GFAPI glusterfs-api>=7.6.6)
  if(NOT GFAPI_FOUND)
    if(USE_FSAL_GLUSTER_REQUIRED)
      message(FATAL_ERROR "Cannot find GLUSTER GFAPI runtime but requested on command line")
    else(USE_FSAL_GLUSTER_REQUIRED)
      message(WARNING "Cannot find GLUSTER GFAPI runtime. Disabling GLUSTER fsal build")
      set(USE_FSAL_GLUSTER OFF)
    endif(USE_FSAL_GLUSTER_REQUIRED)
  else(NOT GFAPI_FOUND)
    message(STATUS "GFAPI_INCLUDE_DIRS=${GFAPI_INCLUDE_DIRS}")
    message(STATUS "GFAPI_LIBRARY_DIRS=${GFAPI_LIBRARY_DIRS}")
    message(STATUS "GFAPI_LIBDIR=${GFAPI_LIBDIR}")
    include_directories(${GFAPI_INCLUDE_DIRS})
    # missing directory not provided by current version of GlusterFS
    include_directories(${GFAPI_PREFIX}/include)
    link_directories (${GFAPI_LIBRARY_DIRS})
    pkg_check_modules(STAT_FETCH_GFAPI glusterfs-api>=7.6)
    if(STAT_FETCH_GFAPI_FOUND)
        set(USE_GLUSTER_STAT_FETCH_API ON)
    else()
        set(USE_GLUSTER_STAT_FETCH_API OFF)
        message(STATUS "turning off stat api's")
    endif(STAT_FETCH_GFAPI_FOUND)
  endif(NOT GFAPI_FOUND)

  if(USE_FSAL_GLUSTER)
    check_include_files("unistd.h;sys/xattr.h" HAVE_SYS_XATTR_H)
    if(NOT HAVE_SYS_XATTR_H)
      if(USE_FSAL_GLUSTER_REQUIRED)
	message(FATAL_ERROR "Can not find sys/xattr.h, but GLUSTER requested on command line")
      else(USE_FSAL_GLUSTER_REQUIRED)
        message(WARNING "Can not find sys/xattr.h, disabling GLUSTER fsal build")
        set(USE_FSAL_GLUSTER OFF)
      endif(USE_FSAL_GLUSTER_REQUIRED)
    endif(NOT HAVE_SYS_XATTR_H)
    if(HAVE_LIBACL)
	set(USE_POSIX_ACLS ON)
	set(USE_ACL_MAPPING ON)
    else(HAVE_LIBACL)
	set(USE_POSIX_ACLS OFF)
	set(USE_FSAL_GLUSTER OFF)
	message(STATUS "Could not find libacl, disabling GLUSTER fsal build")
    endif(HAVE_LIBACL)
    check_library_exists(gfapi glfs_xreaddirplus_r ${GFAPI_LIBDIR} HAVE_XREADDIRPLUS)
    if(HAVE_XREADDIRPLUS)
        set(USE_GLUSTER_XREADDIRPLUS ON)
    else()
        set(USE_GLUSTER_XREADDIRPLUS OFF)
        message(STATUS "Could not find glfs_xreaddirplus, switching to glfs_readdir_r")
    endif(HAVE_XREADDIRPLUS)
    check_library_exists(gfapi glfs_fd_set_lkowner ${GFAPI_LIBDIR} HAVE_LKOWNER)
    if(HAVE_LKOWNER)
	set(USE_LKOWNER ON)
    else()
	set(USE_LKOWNER OFF)
	set(USE_FSAL_GLUSTER OFF)
	message(STATUS "lkowner support is needed to enable GLUSTER build")
    endif(HAVE_LKOWNER)
    check_library_exists(gfapi glfs_upcall_register ${GFAPI_LIBDIR} HAVE_REGISTER_UPCALL)
    if(HAVE_REGISTER_UPCALL)
        set(USE_GLUSTER_UPCALL_REGISTER ON)
    else()
        set(USE_GLUSTER_UPCALL_REGISTER OFF)
        message(STATUS "Could not find glfs_upcall_register, switching to glfs_h_poll_upcall")
    endif(HAVE_REGISTER_UPCALL)
    check_library_exists(gfapi glfs_upcall_lease_get_object ${GFAPI_LIBDIR} HAVE_DELEG)
    if(HAVE_DELEG)
        set(USE_GLUSTER_DELEGATION ON)
    else()
        set(USE_GLUSTER_DELEGATION OFF)
        message(STATUS "Could not find glfs_upcall_lease_get_object, switching off delegations")
    endif(HAVE_DELEG)
  endif(USE_FSAL_GLUSTER)
endif(USE_FSAL_GLUSTER)

gopt_test(USE_FSAL_NULL)
# NULL has no dependencies

gopt_test(USE_FSAL_RGW)
if(USE_FSAL_RGW)
  # require RGW w/API version 1.2.1
  find_package(RGW 1.2.1 ${USE_FSAL_RGW_REQUIRED})
  if(NOT RGW_FOUND)
    message(WARNING "Cannot find supported RGW runtime.  Disabling RGW fsal build")
    set(USE_FSAL_RGW OFF)
  endif(NOT RGW_FOUND)
endif(USE_FSAL_RGW)

gopt_test(USE_FSAL_SAUNAFS)

gopt_test(USE_FSAL_MEM)
# MEM has no dependencies

# sort out which allocator to use
if(${ALLOCATOR} STREQUAL "jemalloc")
  find_package(JeMalloc)
  if(JEMALLOC_FOUND)
    set(SYSTEM_LIBRARIES ${JEMALLOC_LIBRARIES} ${SYSTEM_LIBRARIES})
  else(JEMALLOC_FOUND)
    message(WARNING "jemalloc not found, falling back to libc")
    set(ALLOCATOR "libc")
  endif(JEMALLOC_FOUND)
elseif(${ALLOCATOR} STREQUAL "tcmalloc")
  find_package(TcMalloc)
  if(TCMALLOC_FOUND)
    set(SYSTEM_LIBRARIES ${TCMALLOC_LIBRARIES} ${SYSTEM_LIBRARIES})
  else(TCMALLOC_FOUND)
    message(WARNING "tcmalloc not found, falling back to libc")
    set(ALLOCATOR "libc")
  endif(TCMALLOC_FOUND)
else()
  if(NOT ${ALLOCATOR} STREQUAL "libc")
    message(SEND_ERROR "${ALLOCATOR} is not a valid option. Valid allocators are: jemalloc|tcmalloc|libc")
  endif()
endif()

# Find optional libraries/packages

if (USE_ACL_MAPPING)
  if(HAVE_LIBACL)
    set(SYSTEM_LIBRARIES ${LIBACL_LIBRARY} ${SYSTEM_LIBRARIES})
  else(HAVE_LIBACL)
    set(USE_ACL_MAPPING OFF)
    # HAVE_LIBACL must be set before setting USE_ACL_MAPPING
    message(FATAL_ERROR "Could not find libacl, disabling ACL mapping build")
  endif(HAVE_LIBACL)
endif(USE_ACL_MAPPING)

gopt_test(USE_EFENCE)
if(USE_EFENCE)
  find_library(LIBEFENCE efence)
  if(LIBEFENCE_FOUND)
    set(SYSTEM_LIBRARIES ${LIBEFENCE} ${SYSTEM_LIBRARIES})
  else(LIBEFENCE_FOUND)
    if(USE_EFENCE_REQUIRED)
      message(FATAL_ERROR "Cannot find efence libs but requested on command line")
    else(USE_EFENCE_REQUIRED)
      message(WARNING "Cannot find efence libs. Disabling efence support")
    endif(USE_EFENCE_REQUIRED)
    set(USE_EFENCE OFF)
  endif(LIBEFENCE_FOUND)
endif(USE_EFENCE)

gopt_test(USE_DBUS)
if(USE_DBUS)
  find_package(PkgConfig)
  # pkg_check_modules doesn't fatal error on REQUIRED, so handle it ourselves
  pkg_check_modules(DBUS ${USE_DBUS_REQUIRED} dbus-1)
  if(NOT DBUS_FOUND)
    if(USE_DBUS_REQUIRED)
      message(FATAL_ERROR "Cannot find DBUS libs but requested on command line")
    else(USE_DBUS_REQUIRED)
      message(WARNING "Cannot find DBUS libs. Disabling DBUS support")
      set(USE_DBUS OFF)
    endif(USE_DBUS_REQUIRED)
  else(NOT DBUS_FOUND)
    set(SYSTEM_LIBRARIES ${DBUS_LIBRARIES} ${SYSTEM_LIBRARIES})
    LIST(APPEND CMAKE_LIBRARY_PATH ${DBUS_LIBRARY_DIRS})
    link_directories (${DBUS_LIBRARY_DIRS})
  endif(NOT DBUS_FOUND)
endif(USE_DBUS)

if(USE_CB_SIMULATOR AND NOT USE_DBUS)
  message(WARNING "The callback simulator needs DBUS.  Disabling callback simulator")
  set(USE_CB_SIMULATOR OFF)
endif(USE_CB_SIMULATOR AND NOT USE_DBUS)

gopt_test(USE_NFSIDMAP)
if(USE_NFSIDMAP)
  find_package(NfsIdmap ${USE_NFSIDMAP_REQUIRED})
  if(NFSIDMAP_FOUND)
    set(SYSTEM_LIBRARIES ${NFSIDMAP_LIBRARY} ${SYSTEM_LIBRARIES})
  else(NFSIDMAP_FOUND)
    message(WARNING "libnfsidmap not found, disabling USE_NFSIDMAP")
    set(USE_NFSIDMAP OFF)
  endif(NFSIDMAP_FOUND)
endif(USE_NFSIDMAP)

if(USE_EXECINFO)
  find_package(ExecInfo REQUIRED)
  set(SYSTEM_LIBRARIES ${EXECINFO_LIBRARY} ${SYSTEM_LIBRARIES})
endif(USE_EXECINFO)

gopt_test(USE_CUNIT)
if(USE_CUNIT)
  find_package(CUnit ${USE_CUNIT_REQUIRED})
  if (CUNIT_FOUND)
    set(SYSTEM_LIBRARIES ${CUNIT_LIBRARIES} ${SYSTEM_LIBRARIES})
  else (CUNIT_FOUND)
    message(WARNING "CUnit not found.  Disabling USE_CUNIT")
    set(USE_CUNIT OFF)
  endif (CUNIT_FOUND)
endif(USE_CUNIT)

gopt_test(_MSPAC_SUPPORT)
if(_MSPAC_SUPPORT)
  find_package(WBclient ${_MSPAC_SUPPORT_REQUIRED})
  if(WBCLIENT_FOUND)
    set(SYSTEM_LIBRARIES ${WBCLIENT_LIBRARIES} ${SYSTEM_LIBRARIES})
  else(WBCLIENT_FOUND)
    message(WARNING "Samba 4 wbclient not found.  Disabling MSPAC_SUPPORT")
    set(_MSPAC_SUPPORT OFF)
  endif(WBCLIENT_FOUND)
endif(_MSPAC_SUPPORT)

gopt_test(USE_LTTNG)
if(USE_LTTNG)
  # Set LTTNG_PATH_HINT on the command line
  # if your LTTng is not in a standard place
  find_package(LTTng ${USE_LTTNG_REQUIRED})
  if(LTTNG_FOUND)

    if(NOT CMAKE_EXPORT_COMPILE_COMMANDS)
      # We must create compile_commands.json for lttng trace generation
      set(CMAKE_EXPORT_COMPILE_COMMANDS 1)
    endif(NOT CMAKE_EXPORT_COMPILE_COMMANDS)

    set(CMAKE_C_STANDARD_INCLUDE_DIRECTORIES ${CMAKE_C_IMPLICIT_INCLUDE_DIRECTORIES})

    execute_process(
	COMMAND ${CMAKE_COMMAND} -E make_directory
		"${CMAKE_CURRENT_BINARY_DIR}/gsh_generated_include/gsh_lttng/generated_traces/"
	COMMAND_ERROR_IS_FATAL ANY
    )

    include_directories(
      ${LTTNG_INCLUDE_DIR}
      "${CMAKE_CURRENT_SOURCE_DIR}/libntirpc/src/lttng/generator/include/"
      "${CMAKE_CURRENT_BINARY_DIR}/gsh_generated_include/"
      "${CMAKE_CURRENT_BINARY_DIR}/libntirpc/ntirpc_generated_include/"
    )
    add_definitions(-DUSE_LTTNG)

    # Generate build rules for trace generator
    execute_process(
      COMMAND bash -c "${CMAKE_CURRENT_SOURCE_DIR}/libntirpc/src/lttng/generator/generate_cmake_rules.py \
          --project_path ${CMAKE_CURRENT_SOURCE_DIR} \
          --provider_include_base_path gsh_lttng/generated_traces/ \
          --unique_prefix gsh \
          --filter_out libntirpc \
          --traces_output_dir ${CMAKE_CURRENT_BINARY_DIR}/gsh_generated_include/gsh_lttng/generated_traces/ \
          --include_path ${CMAKE_CURRENT_SOURCE_DIR}/include:${CMAKE_CURRENT_SOURCE_DIR}/libntirpc/ntirpc:${CMAKE_CURRENT_SOURCE_DIR}/libntirpc/src/lttng/generator/include/:${CMAKE_CURRENT_BINARY_DIR}/gsh_generated_include/:${CMAKE_CURRENT_BINARY_DIR}/libntirpc/ntirpc_generated_include/ \
          --targets_output_path ${CMAKE_CURRENT_BINARY_DIR}/gsh_lttng_generation_rules.cmake \
          --file_properties_output_path ${CMAKE_BINARY_DIR}/gsh_lttng_generation_file_properties.cmake"

      COMMAND_ERROR_IS_FATAL ANY
    )

    include("${CMAKE_CURRENT_BINARY_DIR}/gsh_lttng_generation_rules.cmake")
    include("${CMAKE_BINARY_DIR}/gsh_lttng_generation_file_properties.cmake")
  else(LTTNG_FOUND)
    message(WARNING "LTTng libraries not found. Disabling USE_LTTNG")
    set(USE_LTTNG OFF)
  endif(LTTNG_FOUND)
endif(USE_LTTNG)

gopt_test(USE_RADOS_RECOV)
if(USE_RADOS_RECOV)
  find_package(RADOS ${USE_RADOS_RECOV_REQUIRED})
  if(NOT RADOS_FOUND)
    message(WARNING "Rados libraries not found. Disabling USE_RADOS_RECOV")
    set(USE_RADOS_RECOV OFF)
  endif(NOT RADOS_FOUND)
endif(USE_RADOS_RECOV)

gopt_test(RADOS_URLS)
if(RADOS_URLS)
  find_package(RADOS ${RADOS_URLS_REQUIRED})
  if(NOT RADOS_FOUND)
    message(WARNING "Rados libraries not found. Disabling RADOS_URLS")
    set(RADOS_URLS OFF)
  endif(NOT RADOS_FOUND)
endif(RADOS_URLS)

# Cmake 2.6 has issue in managing BISON and FLEX
if( "${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" VERSION_LESS "2.8" )
   message( status "CMake 2.6 detected, using portability hooks" )
   set(CMAKE_CURRENT_LIST_DIR /usr/share/cmake/Modules )
   set(CMAKE_MODULE_PATH ${GANESHA_TOP_CMAKE_DIR}/cmake/portability_cmake_2.8  /usr/share/cmake/Modules ${CMAKE_MODULE_PATH})
endif( "${CMAKE_MAJOR_VERSION}.${CMAKE_MINOR_VERSION}" VERSION_LESS "2.8" )

include_directories(
  "${PROJECT_BINARY_DIR}/include"
  "${PROJECT_SOURCE_DIR}/include"
  "${PROJECT_BINARY_DIR}/libntirpc/src/monitoring/include"
  "${PROJECT_SOURCE_DIR}/libntirpc/src/monitoring/include"
  "${PROJECT_BINARY_DIR}/monitoring/include"
  "${PROJECT_SOURCE_DIR}/monitoring/include"
  "${OS_INCLUDE_DIR}"
)

if (HAVE_KRB5)
  include_directories(
    "${KRB5_INCLUDE_DIRS}"
    )
endif (HAVE_KRB5)

# check for d_off support, FreeBSD doesn't support it before 1200500
if(LINUX)
  add_definitions(-DHAS_DOFF)
elseif(FREEBSD)
  EXECUTE_PROCESS(
    COMMAND uname -K
    OUTPUT_VARIABLE FREEBSD_VERSION
    ERROR_QUIET
  )
  if (FREEBSD_VERSION GREATER 1200500)
    add_definitions(-DHAS_DOFF)
  endif()
elseif(DARWIN)
  # d_off unavailable on macOS
else() # d_off is on by default for other cases
  add_definitions(-DHAS_DOFF)
endif()

# Fixup loose bits of autotools legacy
set(_USE_9P ${USE_9P})
set(_USE_9P_RDMA ${USE_9P_RDMA})
set(_USE_NFS3 ${USE_NFS3})
set(_USE_NLM ${USE_NLM})
set(_USE_RQUOTA ${USE_RQUOTA})
set(_USE_CB_SIMULATOR ${USE_CB_SIMULATOR})

########### add a "make dist" and a "make rpm"  ###############

set( PKG_NAME "${CPACK_PACKAGE_NAME}-${CPACK_PACKAGE_VERSION}.tar.gz")
add_custom_target(dist COMMAND ${CMAKE_MAKE_PROGRAM} package_source)

# Find misc system libs

goption(USE_CAPS "Enable capability management" ON)
gopt_test(USE_CAPS)
if(USE_CAPS)
  find_package(Caps ${USE_CAPS_REQUIRED})
  if (CAPS_FOUND)
    set(SYSTEM_LIBRARIES ${SYSTEM_LIBRARIES} ${CAPS_LIBRARIES})
  else (CAPS_FOUND)
    message(WARNING "Capability libraries not found. Disabling USE_CAPS")
    set(USE_CAPS OFF)
  endif (CAPS_FOUND)
endif(USE_CAPS)

# default to ON so that it does the right thing in the CentOS CI
goption(USE_LEGACY_PYTHON_INSTALL "Use 'python setup.py install'" ON)

# Check if we have libblkid and libuuid, will just be reported under one
# flag USE_BLKID

check_include_files("blkid/blkid.h" HAVE_LIBBLKID_H)
find_library(LIBBLKID blkid)  # Management of Capabilities
check_library_exists(
	blkid
	blkid_devno_to_devname
	""
	HAVE_LIBBLKID
	)

check_include_files("uuid/uuid.h" HAVE_LIBUUID_H)
find_library(LIBUUID uuid)  # Management of Capabilities
check_library_exists(
	uuid
	uuid_parse
	""
	HAVE_LIBUUID
	)

if(HAVE_LIBBLKID AND HAVE_LIBUUID AND HAVE_LIBBLKID_H AND HAVE_LIBUUID_H)
  # we have all the libraries and include files to use libblkid and libuuid
  set(SYSTEM_LIBRARIES ${SYSTEM_LIBRARIES} ${LIBBLKID} ${LIBUUID})
  set(USE_BLKID ON)
else(HAVE_LIBBLKID AND HAVE_LIBUUID AND HAVE_LIBBLKID_H AND HAVE_LIBUUID_H)
  # we are missing something and can't use libblkid and libuuid
  set(USE_BLKID OFF)
  if(NOT HAVE_LIBBLKID)
    message(STATUS "Could not find blkid library, disabling USE_BLKID")
  elseif(NOT HAVE_LIBUUID)
    message(STATUS "Could not find uuid library, disabling USE_BLKID")
  elseif(NOT HAVE_LIBBLKID_H)
    message(STATUS "Could not find blkid header files, disabling USE_BLKID")
  else(NOT HAVE_LIBBLKID)
    message(STATUS "Could not find uuid header files, disabling USE_BLKID")
  endif(NOT HAVE_LIBBLKID)
endif(HAVE_LIBBLKID AND HAVE_LIBUUID AND HAVE_LIBBLKID_H AND HAVE_LIBUUID_H)

# check is daemon exists
# I use check_library_exists there to be portab;e
check_library_exists(
	c
	daemon
	""
	HAVE_DAEMON
	)

# Needs to be before ntirpc
add_custom_target( rpm DEPENDS dist)
add_custom_command(TARGET rpm
                  COMMAND sh -c "rpmbuild -ta ${PKG_NAME}"
		  VERBATIM
		  DEPENDS dist)

set(RPMDEST "--define '_srcrpmdir ${CMAKE_CURRENT_BINARY_DIR}'")
add_custom_target( srpm DEPENDS dist)
add_custom_command(TARGET srpm
                  COMMAND sh -c "rpmbuild ${RPMDEST} -ts ${PKG_NAME}"
		  VERBATIM
		  DEPENDS dist)

# Roll up required libraries

# enable libunwind if available
goption(USE_UNWIND "Enable libunwind" ON)
gopt_test(USE_UNWIND)
if (USE_UNWIND)
  find_package(Unwind)
  if (UNWIND_FOUND)
    set(SYSTEM_LIBRARIES ${UNWIND_LIBRARIES} ${SYSTEM_LIBRARIES})
    include_directories(${UNWIND_INCLUDE_DIR})
    message(STATUS "libunwind found: ${UNWIND_LIBRARIES}")
  else (UNWIND_FOUND)
    message(WARNING "libunwind not found. Disabling USE_UNWIND")
    set(USE_UNWIND OFF)
  endif (UNWIND_FOUND)
endif(USE_UNWIND)
goption(USE_UNWIND_ENRICHED_BT "Enable libunwind enriched bt" OFF)
gopt_test(USE_UNWIND_ENRICHED_BT)

if(USE_9P_RDMA)
  find_package(PkgConfig)
  pkg_check_modules(MOOSHIKA REQUIRED libmooshika>=0.6)

  include_directories(${MOOSHIKA_INCLUDE_DIRS})
  link_directories (${MOOSHIKA_LIBRARY_DIRS})
endif(USE_9P_RDMA)

set(NTIRPC_MIN_VERSION 5.0)
if (USE_SYSTEM_NTIRPC)
  find_package(NTIRPC ${NTIRPC_MIN_VERSION} REQUIRED)
  if (USE_LTTNG)
    set(NTIRPC_LIBRARY ${NTIRPC_LIBRARY} ${NTIRPC_LTTNG})
    set(USE_LTTNG_NTIRPC ON)
  endif (USE_LTTNG)
  if (USE_MONITORING)
    set(NTIRPC_LIBRARY ${NTIRPC_LIBRARY} ${NTIRPC_MONITORING})
  endif (USE_MONITORING)
else (USE_SYSTEM_NTIRPC)
  # Set options for submodule
  set(USE_RPC_RDMA ${USE_NFS_RDMA} CACHE BOOL "Use RDMA")
  set(TIRPC_EPOLL ${TIRPC_EPOLL} CACHE BOOL "Use EPOLL")
  set(USE_GSS ${USE_GSS} CACHE BOOL "Use GSS")
  set(USE_MONITORING ${USE_MONITORING} CACHE BOOL "Use Monitoring")
  set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH}
	  "${GANESHA_TOP_CMAKE_DIR}/libntirpc/cmake/modules/")
  add_subdirectory(libntirpc)
  set(NTIRPC_LIBRARY ntirpc)
  if (USE_LTTNG)
    set(NTIRPC_LIBRARY ${NTIRPC_LIBRARY} ntirpc_lttng)
  endif (USE_LTTNG)
  set(NTIRPC_INCLUDE_DIR "${PROJECT_SOURCE_DIR}/libntirpc/ntirpc/")
  message(STATUS "Using ntirpc submodule")
endif (USE_SYSTEM_NTIRPC)
message(${NTIRPC_INCLUDE_DIR})
include_directories(${NTIRPC_INCLUDE_DIR})

find_library(LIBURCU_LIB urcu-bp)
if (NOT LIBURCU_LIB)
  message(FATAL_ERROR "userspace-rcu library not found!")
endif(NOT LIBURCU_LIB)

find_path(LIBURCU_INC urcu-bp.h)
if (NOT LIBURCU_INC)
  message(FATAL_ERROR "userspace-rcu includes not found!")
endif(NOT LIBURCU_INC)
check_symbol_exists(urcu_ref_get_unless_zero urcu/ref.h HAVE_URCU_REF_GET_UNLESS_ZERO)

# All the plumbing in the basement
set(SYSTEM_LIBRARIES
  ${NTIRPC_LIBRARY}
  ${SYSTEM_LIBRARIES}
  ${CMAKE_DL_LIBS}
  ${KRB5_LIBRARIES}
  ${CMAKE_THREAD_LIBS_INIT}
  ${LIBURCU_LIB}
)

include_directories(${LIBURCU_INC})

# Config file; make sure it doesn't clobber an existing one
include(${GANESHA_TOP_CMAKE_DIR}/cmake/modules/InstallPackageConfigFile.cmake)
InstallPackageConfigFile(${GANESHA_TOP_CMAKE_DIR}/config_samples/ganesha.conf.example ${SYSCONFDIR}/ganesha ganesha.conf)

add_subdirectory(log)
add_subdirectory(config_parsing)
add_subdirectory(test)
add_subdirectory(avl)
add_subdirectory(hashtable)
add_subdirectory(SAL)
add_subdirectory(RPCAL)
add_subdirectory(Protocols)
add_subdirectory(support)
add_subdirectory(os)
if (USE_MONITORING)
  add_subdirectory(monitoring)
endif (USE_MONITORING)

add_subdirectory(FSAL)
add_subdirectory(idmapper)

add_subdirectory(MainNFSD)
add_subdirectory(tools)

if(USE_GTEST)
  add_subdirectory(gtest)
endif(USE_GTEST)

if(USE_DBUS)
  add_subdirectory(dbus)
endif(USE_DBUS)

if(USE_LTTNG)
  add_subdirectory(tracing)
endif(USE_LTTNG)

add_subdirectory(scripts)
add_subdirectory(doc)
# display configuration vars

message(STATUS)
message(STATUS "-------------------------------------------------------")
message(STATUS "PLATFORM = ${PLATFORM}")
message(STATUS "ARCH = ${ARCH}")
message(STATUS "VERSION = ${GANESHA_VERSION}")
message(STATUS "BUILD HOST = ${BUILD_HOST_NAME}")
message(STATUS "C COMPILER = ${CMAKE_CXX_COMPILER_ID}")
message(STATUS "C COMPILER VERSION = ${CMAKE_C_COMPILER_VERSION}")
message(STATUS "-------------------------------------------------------")
message(STATUS "USE_FSAL_PROXY_V4 = ${USE_FSAL_PROXY_V4}")
message(STATUS "USE_FSAL_PROXY_V3 = ${USE_FSAL_PROXY_V3}")
message(STATUS "USE_FSAL_VFS = ${USE_FSAL_VFS}")
message(STATUS "USE_FSAL_LUSTRE = ${USE_FSAL_LUSTRE}")
message(STATUS "USE_FSAL_LIZARDFS = ${USE_FSAL_LIZARDFS}")
message(STATUS "USE_FSAL_KVSFS = ${USE_FSAL_KVSFS}")
message(STATUS "USE_FSAL_CEPH = ${USE_FSAL_CEPH}")
message(STATUS "USE_FSAL_CEPH_MKNOD = ${USE_FSAL_CEPH_MKNOD}")
message(STATUS "USE_FSAL_CEPH_SETLK = ${USE_FSAL_CEPH_SETLK}")
message(STATUS "USE_FSAL_CEPH_LL_LOOKUP_ROOT = ${USE_FSAL_CEPH_LL_LOOKUP_ROOT}")
message(STATUS "USE_FSAL_CEPH_STATX = ${USE_FSAL_CEPH_STATX}")
message(STATUS "USE_FSAL_CEPH_LL_DELEGATION = ${USE_FSAL_CEPH_LL_DELEGATION}")
message(STATUS "USE_FSAL_CEPH_LL_SYNC_INODE = ${USE_FSAL_CEPH_LL_SYNC_INODE}")
message(STATUS "USE_FSAL_CEPH_ABORT_CONN = ${USE_FSAL_CEPH_ABORT_CONN}")
message(STATUS "USE_FSAL_CEPH_RECLAIM_RESET = ${USE_FSAL_CEPH_RECLAIM_RESET}")
message(STATUS "USE_FSAL_CEPH_GET_FS_CID = ${USE_FSAL_CEPH_GET_FS_CID}")
message(STATUS "USE_FSAL_CEPH_STATX = ${USE_FSAL_CEPH_STATX}")
message(STATUS "USE_FSAL_CEPH_FS_NONBLOCKING_IO = ${USE_FSAL_CEPH_FS_NONBLOCKING_IO}")
message(STATUS "USE_FSAL_CEPH_FS_ZEROCOPY_IO = ${USE_FSAL_CEPH_FS_ZEROCOPY_IO}")
message(STATUS "USE_FSAL_RGW = ${USE_FSAL_RGW}")
message(STATUS "USE_FSAL_SAUNAFS = ${USE_FSAL_SAUNAFS}")
message(STATUS "USE_FSAL_XFS = ${USE_FSAL_XFS}")
message(STATUS "USE_FSAL_GPFS = ${USE_FSAL_GPFS}")
message(STATUS "USE_FSAL_GLUSTER = ${USE_FSAL_GLUSTER}")
message(STATUS "USE_FSAL_NULL = ${USE_FSAL_NULL}")
message(STATUS "USE_FSAL_MEM = ${USE_FSAL_MEM}")
message(STATUS "GSH_CAN_HOST_LOCAL_FS = ${GSH_CAN_HOST_LOCAL_FS}")
message(STATUS "USE_SYSTEM_NTIRPC = ${USE_SYSTEM_NTIRPC}")
message(STATUS "USE_DBUS = ${USE_DBUS}")
message(STATUS "USE_CB_SIMULATOR = ${USE_CB_SIMULATOR}")
message(STATUS "USE_BTRFSUTIL = ${USE_BTRFSUTIL}")
message(STATUS "USE_NFSIDMAP = ${USE_NFSIDMAP}")
message(STATUS "USE_RELATIVE_FILE_PATHS_IN_LOGS = ${USE_RELATIVE_FILE_PATHS_IN_LOGS}")
message(STATUS "ENABLE_ERROR_INJECTION = ${ENABLE_ERROR_INJECTION}")
message(STATUS "ENABLE_VFS_POSIX_ACL = ${ENABLE_VFS_POSIX_ACL}")
message(STATUS "ENABLE_VFS_DEBUG_ACL = ${ENABLE_VFS_DEBUG_ACL}")
message(STATUS "ENABLE_RFC_ACL = ${ENABLE_RFC_ACL}")
message(STATUS "CEPHFS_POSIX_ACL = ${CEPHFS_POSIX_ACL}")
message(STATUS "USE_MONITORING = ${USE_MONITORING}")
message(STATUS "USE_CAPS = ${USE_CAPS}")
message(STATUS "USE_BLKID = ${USE_BLKID}")
message(STATUS "DISTNAME_HAS_GIT_DATA = ${DISTNAME_HAS_GIT_DATA}" )
message(STATUS "_MSPAC_SUPPORT = ${_MSPAC_SUPPORT}")
message(STATUS "USE_EFENCE = ${USE_EFENCE}")
message(STATUS "_NO_TCP_REGISTER = ${_NO_TCP_REGISTER}")
message(STATUS "RPCBIND = ${RPCBIND}")
message(STATUS "DEBUG_SAL = ${DEBUG_SAL}")
message(STATUS "_VALGRIND_MEMCHECK = ${_VALGRIND_MEMCHECK}")
message(STATUS "ENABLE_LOCKTRACE = ${ENABLE_LOCKTRACE}")
message(STATUS "PROXYV4_HANDLE_MAPPING = ${PROXYV4_HANDLE_MAPPING}")
message(STATUS "DEBUG_MDCACHE = ${DEBUG_MDCACHE}")
message(STATUS "ENABLE_QOS = ${ENABLE_QOS}")
message(STATUS "DEBUG_SYMS = ${DEBUG_SYMS}")
message(STATUS "COVERAGE = ${COVERAGE}")
message(STATUS "ENFORCE_GCC = ${ENFORCE_GCC}")
message(STATUS "USE_GTEST = ${USE_GTEST}")
message(STATUS "USE_GSS = ${USE_GSS}")
message(STATUS "TIRPC_EPOLL = ${TIRPC_EPOLL}")
message(STATUS "USE_9P = ${USE_9P}")
message(STATUS "_USE_9P = ${_USE_9P}")
message(STATUS "_USE_9P_RDMA = ${_USE_9P_RDMA}")
message(STATUS "USE_NFS_RDMA = ${USE_NFS_RDMA}")
message(STATUS "USE_RPC_RDMA = ${USE_RPC_RDMA}")
message(STATUS "USE_NFS3 = ${USE_NFS3}")
message(STATUS "USE_NLM = ${USE_NLM}")
message(STATUS "USE_NFSACL3 = ${USE_NFSACL3}")
message(STATUS "USE_ACL_MAPPING = ${USE_ACL_MAPPING}")
message(STATUS "KRB5_PREFIX = ${KRB5_PREFIX}")
message(STATUS "CEPH_PREFIX = ${CEPH_PREFIX}")
message(STATUS "RGW_PREFIX = ${RGW_PREFIX}")
message(STATUS "GLUSTER_PREFIX = ${GLUSTER_PREFIX}")
message(STATUS "CMAKE_PREFIX_PATH = ${CMAKE_PREFIX_PATH}")
message(STATUS "_GIT_HEAD_COMMIT = ${_GIT_HEAD_COMMIT}")
message(STATUS "_GIT_HEAD_COMMIT_ABBREV = ${_GIT_HEAD_COMMIT_ABBREV}")
message(STATUS "_GIT_DESCRIBE = ${_GIT_DESCRIBE}")
message(STATUS "ALLOCATOR = ${ALLOCATOR}")
message(STATUS "GOLD_LINKER = ${GOLD_LINKER}")
message(STATUS "CMAKE_INSTALL_PREFIX = ${CMAKE_INSTALL_PREFIX}")
message(STATUS "FSAL_DESTINATION = ${FSAL_DESTINATION}")
message(STATUS "USE_ADMIN_TOOLS = ${USE_ADMIN_TOOLS}")
message(STATUS "USE_GUI_ADMIN_TOOLS = ${USE_GUI_ADMIN_TOOLS}")
message(STATUS "MODULES_PATH = ${MODULES_PATH}")
message(STATUS "USE_LTTNG = ${USE_LTTNG}")
message(STATUS "USE_VSOCK = ${USE_VSOCK}")
message(STATUS "USE_TOOL_MULTILOCK = ${USE_TOOL_MULTILOCK}")
message(STATUS "USE_MAN_PAGE = ${USE_MAN_PAGE}")
message(STATUS "USE_RADOS_RECOV = ${USE_RADOS_RECOV}")
message(STATUS "RADOS_URLS = ${RADOS_URLS}")
message(STATUS "USE_CUNIT = ${USE_CUNIT}")
message(STATUS "USE_UNWIND = ${USE_UNWIND}")
message(STATUS "SANITIZE_ADDRESS = ${SANITIZE_ADDRESS}")

set(USE_CB_SIMULATOR ${USE_CB_SIMULATOR}
  CACHE BOOL
   "enable callback simulator thread"
   FORCE)

set(DEBUG_SAL ${DEBUG_SAL}
  CACHE BOOL
   "enable debug SAL"
   FORCE)

set(_VALGRIND_MEMCHECK ${_VALGRIND_MEMCHECK}
  CACHE BOOL
   "Initialize buffers passed to GPFS ioctl"
   FORCE)

set(ENABLE_ERROR_INJECTION ${ENABLE_ERROR_INJECTION}
  CACHE BOOL
   "enable error injection"
   FORCE)

set(ENABLE_VFS_POSIX_ACL ${ENABLE_VFS_POSIX_ACL}
  CACHE BOOL
   "Enable NFSv4 to POSIX ACL mapping for VFS"
   FORCE)

set(ENABLE_VFS_DEBUG_ACL ${ENABLE_VFS_DEBUG_ACL}
  CACHE BOOL
   "Enable debug ACL store for VFS"
   FORCE)

set(ENABLE_RFC_ACL ${ENABLE_RFC_ACL}
  CACHE BOOL
   "Enable debug ACL store for VFS"
   FORCE)

set( DISTNAME_HAS_GIT_DATA ${DISTNAME_HAS_GIT_DATA}
  CACHE BOOL
  "Distribution package's name carries git data"
  FORCE)

set(USE_9P ${USE_9P}
  CACHE BOOL
   "enable 9P support"
   FORCE)

set(_USE_9P ${_USE_9P}
  CACHE BOOL
   "enable 9P support in config"
   FORCE)

set(_USE_9P_RDMA ${_USE_9P_RDMA}
  CACHE BOOL
   "enable 9P_RDMA support"
   FORCE)

set(USE_NFS3 ${USE_NFS3}
  CACHE BOOL
   "enable NFSv3 support"
   FORCE)

set(USE_NLM ${USE_NLM}
  CACHE BOOL
   "enable NLM support"
   FORCE)

set(USE_NFS_RDMA ${USE_NFS_RDMA}
  CACHE BOOL
  "enable NFS Over RDMA"
  FORCE)

set(_USE_NFS_RDMA ${USE_NFS_RDMA}
  CACHE BOOL
  "enable NFS Over RDMA in config"
  FORCE)

set(USE_ACL_MAPPING ${USE_ACL_MAPPING}
  CACHE BOOL
  "Build NFSv4 to POSIX ACL mapping"
  FORCE)


# Now create a usable config.h
configure_file(
  "${PROJECT_SOURCE_DIR}/include/config-h.in.cmake"
  "${PROJECT_BINARY_DIR}/include/config.h"
)

# Tweak the "%bcond_<with|without> in the specfile for every
# optional feature. Take care on the logic of this syntax
# %bcond_with means you add a "--with" option, default is "without this feature"
# %bcond_without adds a"--without" so the feature is enabled by default
# This has to be coherent with chosen FSALs

if(USE_FSAL_XFS)
    set(BCOND_XFS "%bcond_without")
else(USE_FSAL_XFS)
    set(BCOND_XFS "%bcond_with")
endif(USE_FSAL_XFS)

if(USE_FSAL_LUSTRE AND USE_LLAPI)
    set(BCOND_LUSTRE "%bcond_without")
else(USE_FSAL_LUSTRE AND USE_LLAPI)
    set(BCOND_LUSTRE "%bcond_with")
endif(USE_FSAL_LUSTRE AND USE_LLAPI)

if(USE_FSAL_GPFS)
    set(BCOND_GPFS "%bcond_without")
else(USE_FSAL_GPFS)
    set(BCOND_GPFS "%bcond_with")
endif(USE_FSAL_GPFS)

if(USE_FSAL_LIZARDFS)
    set(BCOND_LIZARDFS "%bcond_without")
else(USE_FSAL_LIZARDFS)
    set(BCOND_LIZARDFS "%bcond_with")
endif(USE_FSAL_LIZARDFS)

if(USE_FSAL_KVSFS)
    set(BCOND_KVSFS "%bcond_without")
else(USE_FSAL_KVSFS)
    set(BCOND_KVSFS "%bcond_with")
endif(USE_FSAL_KVSFS)

if(USE_FSAL_CEPH)
    set(BCOND_CEPH "%bcond_without")
else(USE_FSAL_CEPH)
    set(BCOND_CEPH "%bcond_with")
endif(USE_FSAL_CEPH)

if(USE_FSAL_RGW)
    set(BCOND_RGW "%bcond_without")
else(USE_FSAL_RGW)
    set(BCOND_RGW "%bcond_with")
endif(USE_FSAL_RGW)

if(USE_FSAL_SAUNAFS)
    set(BCOND_SAUNAFS "%bcond_without")
else(USE_FSAL_SAUNAFS)
    set(BCOND_SAUNAFS "%bcond_with")
endif(USE_FSAL_SAUNAFS)

if(USE_FSAL_GLUSTER)
    set(BCOND_GLUSTER "%bcond_without")
else(USE_FSAL_GLUSTER)
    set(BCOND_GLUSTER "%bcond_with")
endif(USE_FSAL_GLUSTER)

if(USE_FSAL_NULL)
    set(BCOND_NULLFS "%bcond_without")
else(USE_FSAL_NULL)
    set(BCOND_NULLFS "%bcond_with")
endif(USE_FSAL_NULL)

if(USE_FSAL_MEM)
    set(BCOND_MEM "%bcond_without")
else(USE_FSAL_MEM)
    set(BCOND_MEM "%bcond_with")
endif(USE_FSAL_MEM)

if(USE_9P)
    set(BCOND_9P "%bcond_without")
    if(USE_9P_RDMA)
        set(BCOND_RDMA "%bcond_without")
    else(USE_9P_RDMA)
        set(BCOND_RDMA "%bcond_with")
    endif(USE_9P_RDMA)
else(USE_9P)
    set(BCOND_9P "%bcond_with")
    set(BCOND_RDMA "%bcond_with")
endif(USE_9P)

if(USE_LTTNG)
    set(BCOND_LTTNG "%bcond_without")
else(USE_LTTNG)
    set(BCOND_LTTNG "%bcond_with")
endif(USE_LTTNG)

if(${ALLOCATOR} STREQUAL "jemalloc")
    set(BCOND_JEMALLOC "%bcond_without")
else(${ALLOCATOR} STREQUAL "jemalloc")
    set(BCOND_JEMALLOC "%bcond_with")
endif(${ALLOCATOR} STREQUAL "jemalloc")

if(${ALLOCATOR} STREQUAL "tcmalloc")
    set(BCOND_TCMALLOC "%bcond_without")
else(${ALLOCATOR} STREQUAL "tcmalloc")
    set(BCOND_TCMALLOC "%bcond_with")
endif(${ALLOCATOR} STREQUAL "tcmalloc")

if(USE_ADMIN_TOOLS)
    set(BCOND_UTILS "%bcond_without")
else(USE_ADMIN_TOOLS)
    set(BCOND_UTILS "%bcond_with")
endif(USE_ADMIN_TOOLS)

if(USE_GUI_ADMIN_TOOLS)
    set(BCOND_GUI_UTILS "%bcond_without")
else(USE_GUI_ADMIN_TOOLS)
    set(BCOND_GUI_UTILS "%bcond_with")
endif(USE_GUI_ADMIN_TOOLS)

if (USE_SYSTEM_NTIRPC)
  set(BCOND_NTIRPC "%bcond_without")
else(USE_SYSTEM_NTIRPC)
  set(BCOND_NTIRPC "%bcond_with")
endif(USE_SYSTEM_NTIRPC)

if (USE_MAN_PAGE)
  set(BCOND_MAN_PAGE "%bcond_without")
else(USE_MAN_PAGE)
  set(BCOND_MAN_PAGE "%bcond_with")
endif(USE_MAN_PAGE)

if (ENABLE_QOS)
  set(BCOND_QOS "%bcond_without")
else(ENABLE_QOS)
  set(BCOND_QOS "%bcond_with")
endif(ENABLE_QOS)

if(USE_RADOS_RECOV)
    set(BCOND_RADOS_RECOV "%bcond_without")
else(USE_RADOS_RECOV)
    set(BCOND_RADOS_RECOV "%bcond_with")
endif(USE_RADOS_RECOV)

if(RADOS_URLS)
    set(BCOND_RADOS_URLS "%bcond_without")
else(RADOS_URLS)
    set(BCOND_RADOS_URLS "%bcond_with")
endif(RADOS_URLS)

if(RPCBIND)
    set(BCOND_RPCBIND "%bcond_without")
else(RPCBIND)
    set(BCOND_RPCBIND "%bcond_with")
endif(RPCBIND)

if(ENABLE_QOS)
  set(BCOND_QOS "%bcond_without")
else(ENABLE_QOS)
  set(BCOND_QOS "%bcond_with")
endif(ENABLE_QOS)

if(USE_UNWIND)
    set(BCOND_UNWIND "%bcond_without")
else(USE_UNWIND)
    set(BCOND_UNWIND "%bcond_with")
endif(USE_UNWIND)

if(USE_UNWIND_ENRICHED_BT)
    set(BCOND_UNWIND_ENRICHED_BT "%bcond_without")
else(USE_UNWIND_ENRICHED_BT)
    set(BCOND_UNWIND_ENRICHED_BT "%bcond_with")
endif(USE_UNWIND_ENRICHED_BT)

if(_MSPAC_SUPPORT)
    set(BCOND_MSPAC_SUPPORT "%bcond_without")
else(_MSPAC_SUPPORT)
    set(BCOND_MSPAC_SUPPORT "%bcond_with")
endif(_MSPAC_SUPPORT)

if(SANITIZE_ADDRESS)
    set(BCOND_SANITIZE_ADDRESS "%bcond_without")
else(SANITIZE_ADDRESS)
    set(BCOND_SANITIZE_ADDRESS "%bcond_with")
endif(SANITIZE_ADDRESS)

if(USE_LEGACY_PYTHON_INSTALL)
    set(BCOND_LEGACY_PYTHON_INSTALL "%bcond_without")
else(USE_LEGACY_PYTHON_INSTALL)
    set(BCOND_LEGACY_PYTHON_INSTALL "%bcond_with")
endif(USE_LEGACY_PYTHON_INSTALL)

if(USE_NFSIDMAP)
  set(BCOND_NFSIDMAP "%bcond_without")
else(USE_NFSIDMAP)
  set(BCOND_NFSIDMAP "%bcond_with")
endif(USE_NFSIDMAP)

if(USE_MONITORING)
  set(BCOND_MONITORING "%bcond_without")
else(USE_MONITORING)
  set(BCOND_MONITORING "%bcond_with")
endif(USE_MONITORING)

# Now create a usable specfile
configure_file(
  "${PROJECT_SOURCE_DIR}/nfs-ganesha.spec-in.cmake"
  "${PROJECT_SOURCE_DIR}/nfs-ganesha.spec"
)

configure_file(
  "${PROJECT_SOURCE_DIR}/scripts/systemd/nfs-ganesha-config.service-in.cmake"
  "${PROJECT_SOURCE_DIR}/scripts/systemd/nfs-ganesha-config.service"
)

# Make a docker image
set(DOCKER_TMP_INSTALL_PATH "${PROJECT_BINARY_DIR}/docker/root")
find_package(LSB_release)
if(LSB_RELEASE_EXECUTABLE)
  string(TOLOWER ${LSB_RELEASE_ID_SHORT} DOCKER_DISTRO)
  set(DOCKER_DISTRO_VERSION "${LSB_RELEASE_RELEASE_SHORT}")

  configure_file(
    "${PROJECT_SOURCE_DIR}/scripts/docker/entrypoint.sh-in.cmake"
    "${PROJECT_BINARY_DIR}/docker/entrypoint.sh"
    @ONLY
    )
  configure_file(
    "${PROJECT_SOURCE_DIR}/scripts/docker/Dockerfile-in.cmake"
    "${PROJECT_BINARY_DIR}/docker/Dockerfile"
    @ONLY
    )
  add_custom_target(docker
    COMMAND sh -c "make DESTDIR=${PROJECT_BINARY_DIR}/docker/root install"
    COMMAND sh -c "docker build -t ganesha/dev ${PROJECT_BINARY_DIR}/docker"
    VERBATIM )
  add_dependencies(docker ganesha.nfsd )
endif(LSB_RELEASE_EXECUTABLE)


if(COVERAGE)
	find_program(LCOV_EXEC lcov)
	find_program(GENHTML_EXEC genhtml)
	if(LCOV_EXEC AND GENHTML_EXEC)
		add_custom_target(lcov)
		add_custom_command(TARGET lcov
			COMMAND ${LCOV_EXEC} --capture --directory .
			--output-file coverage.info
			COMMAND ${GENHTML_EXEC} coverage.info
			--output-directory ./coverage_html/
			VERBATIM
			WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
			)
	endif(LCOV_EXEC AND GENHTML_EXEC)
endif(COVERAGE)

########### next target ###############

add_executable(ganesha.nfsd ./MainNFSD/nfs_main.c)
add_sanitizers(ganesha.nfsd)

target_link_libraries(ganesha.nfsd
  ganesha_nfsd
  ${LIBTIRPC_LIBRARIES}
  ${SYSTEM_LIBRARIES}
  ${LTTNG_LIBRARIES}
  ${LDFLAG_DISALLOW_UNDEF}
)
if (USE_MONITORING)
  target_link_libraries(ganesha.nfsd ganesha_monitoring)
endif (USE_MONITORING)
set_target_properties(ganesha.nfsd PROPERTIES COMPILE_FLAGS "-fPIC")
install(TARGETS ganesha.nfsd COMPONENT daemon DESTINATION bin)

########### next target ###############

if (USE_RADOS_RECOV)
  add_executable(ganesha-rados-grace
    ./tools/ganesha-rados-grace.c ./support/rados_grace.c)
  add_sanitizers(ganesha-rados-grace)
  include_directories(${RADOS_INCLUDE_DIR})
  target_link_libraries(ganesha-rados-grace
    ganesha_nfsd
    ${RADOS_LIBRARIES}
    ${LDFLAG_DISALLOW_UNDEF}
  )
  install(TARGETS ganesha-rados-grace COMPONENT tools DESTINATION bin)
endif(USE_RADOS_RECOV)

########### next target ###############

if(LINUX)

  add_executable(sm_notify.ganesha ./Protocols/NLM/sm_notify.c)
  add_sanitizers(sm_notify.ganesha)

  target_link_libraries(sm_notify.ganesha
    ganesha_nfsd
    ${LIBTIRPC_LIBRARIES}
    ${SYSTEM_LIBRARIES}
    ${LTTNG_LIBRARIES}
    ${LDFLAG_DISALLOW_UNDEF}
  )

  if( USE_ADMIN_TOOLS )
    install(TARGETS sm_notify.ganesha COMPONENT daemon DESTINATION bin)
  endif( USE_ADMIN_TOOLS )
endif(LINUX)

########### next target ###############

add_executable(verif_syntax EXCLUDE_FROM_ALL ./config_parsing/verif_syntax.c)
add_sanitizers(verif_syntax)

target_link_libraries(verif_syntax
  ganesha_nfsd
  ${LIBTIRPC_LIBRARIES}
  ${SYSTEM_LIBRARIES}
  ${LTTNG_LIBRARIES}
  ${LDFLAG_DISALLOW_UNDEF}
)

########### next target ###############

add_executable(test_parsing EXCLUDE_FROM_ALL ./config_parsing/test_parse.c)
add_sanitizers(test_parsing)

target_link_libraries(test_parsing
  ganesha_nfsd
  ${LIBTIRPC_LIBRARIES}
  ${SYSTEM_LIBRARIES}
  ${LTTNG_LIBRARIES}
  ${LDFLAG_DISALLOW_UNDEF}
)

########### add a "make doc" target to call Doxygen
find_package(Doxygen)
if(DOXYGEN_FOUND)
  configure_file(${GANESHA_TOP_CMAKE_DIR}/Doxyfile.in
		 ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile @ONLY)
  add_custom_target(doc
    ${DOXYGEN_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/Doxyfile
    WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
    )
endif(DOXYGEN_FOUND)
