message (STATUS "Running with CMake ${CMAKE_VERSION}")
cmake_minimum_required (VERSION 3.15)

project (snmp_pp VERSION 4.0.1 LANGUAGES CXX)
enable_language (CXX)

include (CheckIncludeFiles)
include (CheckFunctionExists)
include (CheckSymbolExists)
include (CheckLibraryExists)
include (CheckStructHasMember)
include (CheckTypeSize)

set (CMAKE_CXX_STANDARD 14)

# Provides CMAKE_INSTALL_LIBDIR / BINDIR / INCLUDEDIR
include (GNUInstallDirs)


option (OPTION_SNMPv3  "Enable support for SNMPv3" ON)
option (OPTION_IPv6    "Enable support for IPv6" ON)
option (OPTION_THREADS "Enable support for threads" ON)
option (OPTION_NAMESPACE "Enable using of namespace" ON)
option (OPTION_LOGGING "Enable logging" ON)
option (OPTION_MACADDR "Enable MacAddress class" OFF)
option (OPTION_IPXADDR "Enable IpxAddress class (deprecated)" OFF)
option (OPTION_OPENSSL "Search for OpenSSL library" ON)
option (OPTION_EXTENDED_DEBUG "Enable additional debug messages" OFF)

#add_compile_options(
#  "-Wall" "-Wpedantic" "-Wextra" "-fexceptions" "-O0" "-g3" "-ggdb"
#)

set (LogProfile "original" CACHE STRING
  "Log Profile")

set (LogProfileValues "original;off;quiet;std;events;verbose;full;debug;schwafel" CACHE STRING
  "List of possible values for the Log Profile variable")

set_property (CACHE LogProfile PROPERTY STRINGS ${LogProfileValues})

message (STATUS "LogProfile='${LogProfile}'")

set (VERSION ${PROJECT_VERSION})
set (SNMP_PP_MAJOR_VERSION ${PROJECT_VERSION_MAJOR})
set (SNMP_PP_MINOR_VERSION ${PROJECT_VERSION_MINOR})
set (SNMP_PP_MICRO_VERSION ${PROJECT_VERSION_PATCH})

message (STATUS "snmp++ Version ${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")

check_include_files (sys/types.h CNF_HAVE_SYS_TYPES_H LANGUAGE CXX)
check_include_files (sys/stat.h CNF_HAVE_SYS_STAT_H LANGUAGE CXX)
check_include_files ("cctype;cerrno;climits;csignal;cstddef;cstdio;cstdlib;cstring;ctime" CNF_STDCXX_98_HEADERS LANGUAGE CXX)
check_include_files ("iostream" CNF_HAVE_IOSTREAM LANGUAGE CXX)
check_include_files ("stdlib.h;stddef.h" CNF_STDC_HEADERS LANGUAGE CXX)
check_include_files (stdlib.h CNF_HAVE_STDLIB_H LANGUAGE CXX)
check_include_files (string.h CNF_HAVE_STRING_H LANGUAGE CXX)
check_include_files (memory.h CNF_HAVE_MEMORY_H LANGUAGE CXX)
check_include_files (strings.h CNF_HAVE_STRINGS_H LANGUAGE CXX)
check_include_files (inttypes.h CNF_HAVE_INTTYPES_H LANGUAGE CXX)
check_include_files (ctype.h CNF_HAVE_CTYPE_H LANGUAGE CXX)
check_include_files (signal.h CNF_HAVE_SIGNAL_H LANGUAGE CXX)
check_include_files (errno.h CNF_HAVE_ERRNO_H LANGUAGE CXX)
check_include_files (time.h CNF_HAVE_TIME_H LANGUAGE CXX)
check_include_files (unistd.h CNF_HAVE_UNISTD_H LANGUAGE CXX)
check_include_files (sys/unistd.h CNF_HAVE_SYS_UNISTD_H LANGUAGE CXX)
check_include_files (stdint.h CNF_HAVE_STDINT_H LANGUAGE CXX)
check_include_files (sys/time.h CNF_HAVE_SYS_TIME_H LANGUAGE CXX)
check_include_files (sys/param.h CNF_HAVE_SYS_PARAM_H LANGUAGE CXX)
check_include_files (sys/timeb.h CNF_HAVE_SYS_TIMEB_H LANGUAGE CXX)
check_include_files (winsock2.h CNF_HAVE_WINSOCK2_H LANGUAGE CXX)
check_include_files (ws2tcpip.h CNF_HAVE_WS2TCPIP_H LANGUAGE CXX)
check_include_files (wspiapi.h CNF_HAVE_WSPIAPI_H LANGUAGE CXX)
check_include_files (winsock.h CNF_HAVE_WINSOCK_H LANGUAGE CXX)
check_include_files (netdb.h CNF_HAVE_NETDB_H LANGUAGE CXX)
check_include_files (sys/socket.h CNF_HAVE_SYS_SOCKET_H LANGUAGE CXX)
check_include_files (arpa/inet.h CNF_HAVE_ARPA_INET_H LANGUAGE CXX)
check_include_files (netinet/in.h CNF_HAVE_NETINET_IN_H LANGUAGE CXX)
check_include_files (poll.h CNF_HAVE_POLL_H LANGUAGE CXX)
check_include_files (sys/select.h CNF_HAVE_SYS_SELECT_H LANGUAGE CXX)
check_include_files (io.h CNF_HAVE_IO_H LANGUAGE CXX)
check_include_files (process.h CNF_HAVE_PROCESS_H LANGUAGE CXX)
check_include_files (pthread.h CNF_HAVE_PTHREAD_H LANGUAGE CXX)
check_function_exists ("strcasecmp" CNF_HAVE_STRCASECMP)
check_function_exists ("stricmp" CNF_HAVE_STRICMP)
check_function_exists ("getpid" CNF_HAVE_GETPID)
check_function_exists ("_getpid" CNF_HAVE__GETPID)

check_function_exists ("clock_gettime" HAVE_CLOCK_GETTIME)
check_function_exists ("arc4random" HAVE_ARC4RANDOM)
check_function_exists ("getaddrinfo" HAVE_GETADDRINFO)
check_function_exists ("gethostbyaddr" HAVE_GETHOSTBYADDR)
check_function_exists ("gethostbyaddr_r" HAVE_GETHOSTBYADDR_R)
check_function_exists ("gethostbyname" HAVE_GETHOSTBYNAME)
check_function_exists ("gethostbyname2" HAVE_GETHOSTBYNAME2)
check_function_exists ("gethostbyname_r" HAVE_GETHOSTBYNAME_R)
check_function_exists ("gethostname" HAVE_GETHOSTNAME)
check_function_exists ("getpid" HAVE_GETPID)
check_function_exists ("gettimeofday" HAVE_GETTIMEOFDAY)
check_function_exists ("htonl" HAVE_HTONL)
check_function_exists ("inet_aton" HAVE_INET_ATON)
check_function_exists ("inet_ntoa" HAVE_INET_NTOA)
check_function_exists ("inet_ntop" HAVE_INET_NTOP)
check_function_exists ("inet_pton" HAVE_INET_PTON)
check_include_files (inttypes.h HAVE_INTTYPES_H LANGUAGE CXX)
check_include_files (io.h HAVE_IO_H LANGUAGE CXX)
check_function_exists ("isdigit" HAVE_ISDIGIT)
check_include_files (limits.h HAVE_LIMITS_H LANGUAGE CXX)
check_function_exists ("localtime_r" HAVE_LOCALTIME_R)
check_function_exists ("malloc" HAVE_MALLOC)
check_include_files (memory.h HAVE_MEMORY_H LANGUAGE CXX)
check_function_exists ("memset" HAVE_MEMSET)
check_include_files (netdb.h HAVE_NETDB_H LANGUAGE CXX)
check_include_files (netinet/in.h HAVE_NETINET_IN_H LANGUAGE CXX)
check_function_exists ("poll" HAVE_POLL)
check_include_files (poll.h HAVE_POLL_H LANGUAGE CXX)
check_include_files (process.h HAVE_PROCESS_H LANGUAGE CXX)
check_include_files (pthread.h HAVE_PTHREAD LANGUAGE CXX)
check_function_exists ("realloc" HAVE_REALLOC)
check_function_exists ("select" HAVE_SELECT)
check_include_files (signal.h HAVE_SIGNAL_H LANGUAGE CXX)
check_function_exists ("socket" HAVE_SOCKET)
check_include_files (stdint.h HAVE_STDINT_H LANGUAGE CXX)
check_include_files (stdio.h HAVE_STDIO_H LANGUAGE CXX)
check_include_files (stdlib.h HAVE_STDLIB_H LANGUAGE CXX)
check_function_exists ("strcasecmp" HAVE_STRCASECMP)
check_function_exists ("strchr" HAVE_STRCHR)
check_function_exists ("strerror" HAVE_STRERROR)
check_function_exists ("stricmp" HAVE_STRICMP)
check_include_files (strings.h HAVE_STRINGS_H LANGUAGE CXX)
check_include_files (string.h HAVE_STRING_H LANGUAGE CXX)
check_function_exists ("strstr" HAVE_STRSTR)
check_include_files (sys/param.h HAVE_SYS_PARAM_H LANGUAGE CXX)
check_include_files (sys/select.h HAVE_SYS_SELECT_H LANGUAGE CXX)
check_include_files (sys/socket.h HAVE_SYS_SOCKET_H LANGUAGE CXX)
check_include_files (sys/stat.h HAVE_SYS_STAT_H LANGUAGE CXX)
check_include_files (sys/timeb.h HAVE_SYS_TIMEB_H LANGUAGE CXX)
check_include_files (sys/time.h HAVE_SYS_TIME_H LANGUAGE CXX)
check_include_files (sys/types.h HAVE_SYS_TYPES_H LANGUAGE CXX)
check_include_files (sys/unistd.h HAVE_SYS_UNISTD_H LANGUAGE CXX)
check_include_files (time.h HAVE_TIME_H LANGUAGE CXX)
check_include_files (unistd.h HAVE_UNISTD_H LANGUAGE CXX)
check_include_files (winsock2.h HAVE_WINSOCK2_H LANGUAGE CXX)
check_include_files (winsock.h HAVE_WINSOCK_H LANGUAGE CXX)
check_include_files (ws2tcpip.h HAVE_WS2TCPIP_H LANGUAGE CXX)
check_include_files (wspiapi.h HAVE_WSPIAPI_H LANGUAGE CXX)
check_function_exists ("_getpid" HAVE__GETPID)

check_type_size ("int64_t" SIZEOF_INT64_T LANGUAGE CXX)
check_type_size ("long long" SIZEOF_LONG_LONG LANGUAGE CXX)
check_type_size ("long" SIZEOF_LONG LANGUAGE CXX)
check_type_size ("uint64_t" SIZEOF_UINT64_T LANGUAGE CXX)
check_type_size ("unsigned long long" SIZEOF_ULONG_LONG LANGUAGE CXX)
check_type_size ("unsigned long" SIZEOF_ULONG LANGUAGE CXX)

if (SIZEOF_INT64_T EQUAL "8")
  set (TYPE_INT64_T "int64_t")
elseif (SIZEOF_LONG EQUAL "8")
  set (TYPE_INT64_T "long")
elseif (SIZEOF_LONG_LONG EQUAL "8")
  set (TYPE_INT64_T "long long")
else ()
  message (FATAL_ERROR "Can't find suitable int64_t")
endif ()
message (STATUS "Found int64_t: ${TYPE_INT64_T}")

if (SIZEOF_UINT64_T EQUAL "8")
  set (TYPE_UINT64_T "uint64_t")
elseif (SIZEOF_ULONG EQUAL "8")
  set (TYPE_INT64_T "unsigned long")
elseif (SIZEOF_ULONG_LONG EQUAL "8")
  set (TYPE_INT64_T "unsigned long long")
else ()
  message (FATAL_ERROR "Can't find suitable uint64_t")
endif ()
message (STATUS "Found uint64_t: ${TYPE_UINT64_T}")


set (SOCKADDR_HEADERS)
if (CNF_HAVE_WINSOCK2_H)
   set (SOCKADDR_HEADERS ${SOCKADDR_HEADERS} winsock2.h)
endif ()
if (CNF_HAVE_WS2TCPIP_H)
   set (SOCKADDR_HEADERS ${SOCKADDR_HEADERS} ws2tcpip.h)
endif ()
if (CNF_HAVE_WINSOCK_H)
   set (SOCKADDR_HEADERS ${SOCKADDR_HEADERS} winsock.h)
endif ()
if (CNF_HAVE_NETDB_H)
   set (SOCKADDR_HEADERS ${SOCKADDR_HEADERS} netdb.h)
endif ()
if (CNF_HAVE_SYS_SOCKET_H)
   set (SOCKADDR_HEADERS ${SOCKADDR_HEADERS} sys/socket.h)
endif ()
if (CNF_HAVE_ARPA_INET_H)
   set (SOCKADDR_HEADERS ${SOCKADDR_HEADERS} arpa/inet.h)
endif ()
if (CNF_HAVE_NETINET_IN_H)
   set (SOCKADDR_HEADERS ${SOCKADDR_HEADERS} netinet/in.h)
endif ()

check_struct_has_member ("struct sockaddr_storage"
            ss_family "${SOCKADDR_HEADERS}"
            CNF_HAVE_STRUCT_SOCKADDR_STORAGE_SS_FAMILY LANGUAGE CXX)

check_struct_has_member ("struct sockaddr_storage"
            __ss_family "${SOCKADDR_HEADERS}"
            CNF_HAVE_STRUCT_SOCKADDR_STORAGE___SS_FAMILY LANGUAGE CXX)


if (OPTION_SNMPv3)
  set (_SNMPv3 1)
  set (_NO_SNMPv3 0)
else ()
  set (_SNMPv3 0)
  set (_NO_SNMPv3 1)
endif ()

if (OPTION_IPv6)
   set (WITH_SNMP_PP_IPv6 1)
   set (SNMP_PP_IPv6 1)
else ()
   set (WITH_SNMP_PP_IPv6 0)
   set (SNMP_PP_IPv6 0)
endif ()

if (OPTION_THREADS)
  set (CMAKE_THREAD_PREFER_PTHREAD 1)
  set (THREADS_PREFER_PTHREAD_FLAG ON)
  # Always go through FindThreads so that the imported target Threads::Threads
  # exists on every platform (including Apple) and can be exported by name.
  find_package (Threads REQUIRED)

   set (WITH_THREADS 1)
   if (CNF_HAVE_PTHREAD_H)
      set (WITH_PTHREAD 1)
   else ()
      set (WITH_PTHREAD 0)
   endif ()
else ()
  set (CMAKE_DISABLE_FIND_PACKAGE_Threads ON)
   set (WITH_THREADS 0)
   set (WITH_PTHREAD 0)
endif ()

if (OPTION_NAMESPACE)
   set (WITH_NAMESPACE 1)
else ()
   set (WITH_NAMESPACE 0)
endif ()

if (OPTION_LOGGING)
   set (WITH_LOGGING 1)
else ()
   set (WITH_LOGGING 0)
endif ()

if (OPTION_MACADDR)
   set (WITH_MACADDRESS 1)
else ()
   set (WITH_MACADDRESS 0)
endif ()

if (OPTION_IPXADDR)
   set (WITH_IPXADDRESS 1)
else ()
   set (WITH_IPXADDRESS 0)
endif ()

if (OPTION_EXTENDED_DEBUG)
   set (_DEBUG 1)
else ()
   set (_DEBUG 0)
endif ()


# Dependencies that must appear in the exported link interface. Only IMPORTED
# target names belong here - absolute host paths would be written verbatim into
# the installed snmp++Targets.cmake and make the package non-relocatable.
set (SNMP_PP_CRYPTO_LIBS)

if (OPTION_OPENSSL)
  #set (OPENSSL_ROOT_DIR "/usr/local/opt/openssl")
  find_package (OpenSSL REQUIRED)

  if (OPENSSL_FOUND)
    message (STATUS "Found OpenSSL (include: ${OPENSSL_INCLUDE_DIR}, library: ${OPENSSL_LIBRARIES})")

    list (APPEND SNMP_PP_CRYPTO_LIBS OpenSSL::SSL OpenSSL::Crypto)
  else (OPENSSL_FOUND)
    message (FATAL_ERROR "OpenSSL NOT found")
  endif (OPENSSL_FOUND)

  set (WITH_LIBSSL 1)
else ()
  set (WITH_LIBSSL 0)
endif ()

# The CMake build supports OpenSSL only; libtomcrypt and libdes are deprecated.
# These two variables are still substituted into config_snmp_pp.h.in, which is
# shared with the autoconf build (where both backends remain selectable), so
# they must keep a defined value here - the header uses them in #if directives.
set (WITH_LIBTOMCRYPT 0)
set (WITH_LIBDES 0)


if (${LogProfile} STREQUAL "off")
  set (WITH_LOG_PROFILES 0)
else ()
  set (WITH_LOG_PROFILES 1)
  set (DEFAULT_LOG_PROFILE "${LogProfile}")
endif ()

if (CNF_STDC_HEADERS)
  set (STDC_HEADERS 1)
else ()
  set (STDC_HEADERS 0)
endif ()

if (CNF_STDCXX_98_HEADERS)
  set (STDCXX_98_HEADERS 1)
else ()
  set (STDCXX_98_HEADERS 0)
endif ()


check_type_size (size_t SIZE_T LANGUAGE CXX)
if (NOT HAVE_SIZE_T)
  if ("${CMAKE_SIZEOF_VOID_P}" EQUAL 8)
    set (size_t "uint64_t")
  else ("${CMAKE_SIZEOF_VOID_P}" EQUAL 8)
    set (size_t   "uint32_t")
  endif ("${CMAKE_SIZEOF_VOID_P}" EQUAL 8)
endif ()

# Check if sys/types.h defined pid_t
if (HAVE_SYS_TYPES_H)
  check_type_size (pid_t PID_T LANGUAGE CXX)
endif ()

check_include_files (malloc.h HAVE_MALLOC_H LANGUAGE CXX)
check_include_files ("sys/param.h;sys/mount.h" HAVE_SYS_MOUNT_H LANGUAGE CXX)
check_function_exists ("strcasecmp" HAVE_STRCASECMP)

configure_file (${CMAKE_CURRENT_SOURCE_DIR}/cmake_config.h.in ${CMAKE_CURRENT_SOURCE_DIR}/config.h)
configure_file (${CMAKE_CURRENT_SOURCE_DIR}/cmake_libsnmp.h.in ${CMAKE_CURRENT_SOURCE_DIR}/libsnmp.h)
configure_file (${CMAKE_CURRENT_SOURCE_DIR}/cmake_libsnmp.h.in ${CMAKE_CURRENT_SOURCE_DIR}/include/system/libsnmp.h)
configure_file (${CMAKE_CURRENT_SOURCE_DIR}/include/snmp_pp/config_snmp_pp.h.in ${CMAKE_CURRENT_SOURCE_DIR}/include/snmp_pp/config_snmp_pp.h)

if (MSVC)
    # Warning level 4 (all warnings as errors: /WX)
    add_compile_options (/W4)
    # Disable warnings for deprecated functions
    add_compile_definitions (_CRT_SECURE_NO_WARNINGS)
    add_compile_definitions (_WINSOCK_DEPRECATED_NO_WARNINGS)
else ()
    # Add "-Wextra -pedantic" to get more warnings
    add_compile_options (-Wall)
endif ()

set (MY_HEADER_FILES
  include/snmp_pp/address.h
  include/snmp_pp/asn1.h
  include/snmp_pp/auth_priv.h
  include/snmp_pp/collect.h
  include/snmp_pp/config_snmp_pp.h
  include/snmp_pp/counter.h
  include/snmp_pp/ctr64.h
  include/snmp_pp/eventlist.h
  include/snmp_pp/eventlistholder.h
  include/snmp_pp/gauge.h
  include/snmp_pp/idea.h
  include/snmp_pp/integer.h
  include/snmp_pp/IPv6Utility.h
  include/snmp_pp/log.h
  include/snmp_pp/md5.h
  include/snmp_pp/mp_v3.h
  include/snmp_pp/msec.h
  include/snmp_pp/msgqueue.h
  include/snmp_pp/notifyqueue.h
  include/snmp_pp/octet.h
  include/snmp_pp/oid.h
  include/snmp_pp/oid_def.h
  include/snmp_pp/pdu.h
  include/snmp_pp/reentrant.h
  include/snmp_pp/sha.h
  include/snmp_pp/smi.h
  include/snmp_pp/smival.h
  include/snmp_pp/snmp_pp.h
  include/snmp_pp/security_model.h
  include/snmp_pp/snmperrs.h
  include/snmp_pp/snmpmsg.h
  include/snmp_pp/target.h
  include/snmp_pp/tcp_transport_mapping.h
  include/snmp_pp/timetick.h
  include/snmp_pp/tls_transport_mapping.h
  include/snmp_pp/tls_tm_security_callback.h
  include/snmp_pp/transport_mapping.h
  include/snmp_pp/transport_state_reference.h
  include/snmp_pp/tsm.h
  include/snmp_pp/udp_transport_mapping.h
  include/snmp_pp/userdefined.h
  include/snmp_pp/usertimeout.h
  include/snmp_pp/usm_v3.h
  include/snmp_pp/uxsnmp.h
  include/snmp_pp/v3.h
  include/snmp_pp/vb.h
)

set (MY_HEADER_LIB_FILES
  libsnmp.h
)

set (MY_SRC_FILES
  src/address.cpp
  src/asn1.cpp
  src/auth_priv.cpp
  src/counter.cpp
  src/ctr64.cpp
  src/eventlist.cpp
  src/eventlistholder.cpp
  src/gauge.cpp
  src/idea.cpp
  src/integer.cpp
  src/IPv6Utility.cpp
  src/log.cpp
  src/md5c.cpp
  src/mp_v3.cpp
  src/msec.cpp
  src/msgqueue.cpp
  src/notifyqueue.cpp
  src/octet.cpp
  src/oid.cpp
  src/pdu.cpp
  src/reentrant.cpp
  src/sha.cpp
  src/snmpmsg.cpp
  src/target.cpp
  src/tcp_transport_mapping.cpp
  src/timetick.cpp
  src/tls_transport_mapping.cpp
  src/tsm.cpp
  src/udp_transport_mapping.cpp
  src/userdefined.cpp
  src/usertimeout.cpp
  src/usm_v3.cpp
  src/uxsnmp.cpp
  src/v3.cpp
  src/vb.cpp
)

add_library (snmp++ SHARED
  ${MY_HEADER_FILES}
  ${MY_HEADER_LIB_FILES}
  config.h
  ${MY_SRC_FILES}
)

set_property (TARGET snmp++ PROPERTY POSITION_INDEPENDENT_CODE 1)
# Set .so version as autoconf does: snmp++ version 1.2.3 will go to .so.12.0.3!
set_target_properties (snmp++ PROPERTIES VERSION ${PROJECT_VERSION_MAJOR}${PROJECT_VERSION_MINOR}.0.${PROJECT_VERSION_PATCH} SOVERSION ${PROJECT_VERSION_MAJOR}${PROJECT_VERSION_MINOR})

add_library (snmp++_static STATIC
  ${MY_HEADER_FILES}
  ${MY_SRC_FILES}
)

# ---------------------------------------------------------------------------
# Usage requirements, shared by the shared and the static library.
#
# Note the asymmetry between BUILD_INTERFACE and INSTALL_INTERFACE: in the
# source tree <libsnmp.h> lives in the project root (generated by
# configure_file above) while "snmp_pp/*.h" live under include/, so two build
# directories are needed. Both land under <prefix>/include on install, so a
# single install directory covers them.
# ---------------------------------------------------------------------------
foreach (_snmp_pp_target snmp++ snmp++_static)

  target_include_directories (${_snmp_pp_target}
    PUBLIC
      $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}>
      $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
      $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
  )

  # HAVE_CONFIG_H selects the (non-installed) config.h in libsnmp.h and must
  # NOT leak into the interface.
  target_compile_definitions (${_snmp_pp_target} PRIVATE HAVE_CONFIG_H)

  # PUBLIC: the installed headers include <openssl/ssl.h>, <openssl/x509.h>
  # and <openssl/provider.h> whenever _USE_OPENSSL is set in the installed
  # config_snmp_pp.h, so consumers need the crypto include directory too.
  if (SNMP_PP_CRYPTO_LIBS)
    target_link_libraries (${_snmp_pp_target} PUBLIC ${SNMP_PP_CRYPTO_LIBS})
  endif ()

  if (WITH_THREADS)
    target_link_libraries (${_snmp_pp_target} PUBLIC Threads::Threads)
  endif ()

  if (WIN32)
    target_link_libraries (${_snmp_pp_target} PUBLIC ws2_32)
  endif ()

  # CMAKE_CXX_STANDARD is directory scope and is not exported, so state the
  # requirement on the targets instead.
  target_compile_features (${_snmp_pp_target} PUBLIC cxx_std_14)

endforeach ()
unset (_snmp_pp_target)

if (WIN32)
  set_target_properties (snmp++ PROPERTIES WINDOWS_EXPORT_ALL_SYMBOLS ON)
endif ()

set (EXAMPLE_SOURCE_FILES
  consoleExamples/receive_trap.cpp
  consoleExamples/snmpBulk.cpp
  consoleExamples/snmpDiscover.cpp
  consoleExamples/snmpGet.cpp
  consoleExamples/snmpInform.cpp
  consoleExamples/snmpNext.cpp
  consoleExamples/snmpNextAsync.cpp
  consoleExamples/snmpPasswd.cpp
  consoleExamples/snmpSet.cpp
  consoleExamples/snmpTraps.cpp
  consoleExamples/snmpWalk.cpp
  consoleExamples/test_app.cpp
)
if (NOT WIN32)
  set (EXAMPLE_SOURCE_FILES ${EXAMPLE_SOURCE_FILES} consoleExamples/snmpWalkThreads.cpp)
endif ()


foreach (examplesourcefile ${EXAMPLE_SOURCE_FILES})
    string (REPLACE ".cpp" "" examplename ${examplesourcefile})
    string (REPLACE "consoleExamples/" "" examplename ${examplename})
    add_executable (${examplename} ${examplesourcefile})
    # snmp++_static carries its include directories, HAVE_CONFIG_H is private
    # to the library, so the examples need their own definition.
    target_compile_definitions (${examplename} PRIVATE HAVE_CONFIG_H)
    # Threads::Threads and the crypto libraries arrive transitively as PUBLIC
    # dependencies of snmp++_static.
    target_link_libraries (${examplename} snmp++_static)

endforeach (examplesourcefile ${EXAMPLE_SOURCE_FILES})

# ---------------------------------------------------------------------------
# Installation and package export
# ---------------------------------------------------------------------------
include (CMakePackageConfigHelpers)

set (SNMP_PP_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/snmp++"
     CACHE STRING "Installation directory for the snmp++ CMake package files")

install (TARGETS snmp++ snmp++_static
  EXPORT  snmp++Targets
  RUNTIME DESTINATION "${CMAKE_INSTALL_BINDIR}"     # .dll on Windows
  LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}"     # .so / .dylib
  ARCHIVE DESTINATION "${CMAKE_INSTALL_LIBDIR}"     # .a / .lib
)

install (FILES ${MY_HEADER_LIB_FILES} DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}")
install (FILES ${MY_HEADER_FILES}     DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/snmp_pp")

install (EXPORT snmp++Targets
  FILE        snmp++Targets.cmake
  NAMESPACE   snmp++::
  DESTINATION "${SNMP_PP_INSTALL_CMAKEDIR}"
)

# Build-tree export, so a superproject can find_package(snmp++) against an
# uninstalled build directory.
export (EXPORT snmp++Targets
  FILE      "${CMAKE_CURRENT_BINARY_DIR}/snmp++Targets.cmake"
  NAMESPACE snmp++::
)

configure_package_config_file (
  "${PROJECT_SOURCE_DIR}/cmake/snmp++Config.cmake.in"
  "${CMAKE_CURRENT_BINARY_DIR}/snmp++Config.cmake"
  INSTALL_DESTINATION "${SNMP_PP_INSTALL_CMAKEDIR}"
)

write_basic_package_version_file (
  "${CMAKE_CURRENT_BINARY_DIR}/snmp++ConfigVersion.cmake"
  VERSION       ${PROJECT_VERSION}
  COMPATIBILITY SameMajorVersion
)

install (FILES
  "${CMAKE_CURRENT_BINARY_DIR}/snmp++Config.cmake"
  "${CMAKE_CURRENT_BINARY_DIR}/snmp++ConfigVersion.cmake"
  DESTINATION "${SNMP_PP_INSTALL_CMAKEDIR}"
)
