# # Try to find libpcap. # # To tell this module where to look, a user may set the environment variable # PCAP_ROOT to point cmake to the *root* of a directory with include and # lib subdirectories for pcap.dll (e.g WpdPack or npcap-sdk). # Alternatively, PCAP_ROOT may also be set from cmake command line or GUI # (e.g cmake -DPCAP_ROOT=C:\path\to\pcap [...]) # if(WIN32) # # Building for Windows. # # libpcap isn't set up to install .pc files or pcap-config on Windows, # and it's not clear that either of them would work without a lot # of additional effort. WinPcap doesn't supply them, and neither # does Npcap. # # So just search for them directly. Look for both pcap and wpcap. # Don't bother looking for static libraries; unlike most UN*Xes # (with the exception of AIX), where different extensions are used # for shared and static, Windows uses .lib both for import libraries # for DLLs and for static libraries. # # We don't directly set PCAP_INCLUDE_DIRS or PCAP_LIBRARIES, as # they're not supposed to be cache entries, and find_path() and # find_library() set cache entries. # find_path(PCAP_INCLUDE_DIR pcap.h) # The 64-bit Packet.lib is located under /x64 if(CMAKE_SIZEOF_VOID_P EQUAL 8) # # For the WinPcap and Npcap SDKs, the Lib subdirectory of the top-level # directory contains 32-bit libraries; the 64-bit libraries are in the # Lib/x64 directory. # # The only way to *FORCE* CMake to look in the Lib/x64 directory # without searching in the Lib directory first appears to be to set # CMAKE_LIBRARY_ARCHITECTURE to "x64". # set(CMAKE_LIBRARY_ARCHITECTURE "x64") endif() find_library(PCAP_LIBRARY NAMES pcap wpcap) # # Do the standard arg processing, including failing if it's a # required package. # include(FindPackageHandleStandardArgs) find_package_handle_standard_args(PCAP DEFAULT_MSG PCAP_INCLUDE_DIR PCAP_LIBRARY ) mark_as_advanced( PCAP_INCLUDE_DIR PCAP_LIBRARY ) if(PCAP_FOUND) set(PCAP_LIBRARIES ${PCAP_LIBRARY}) set(PCAP_INCLUDE_DIRS ${PCAP_INCLUDE_DIR}) endif() else(WIN32) # # Building for UN*X. # # See whether we were handed a QUIET argument, so we can pass it on # to pkg_search_module. Do *NOT* pass on the REQUIRED argument, # because, if pkg-config isn't found, or it is but it has no .pc # files for libpcap, that is *not* necessarily an indication that # libpcap isn't available - not all systems ship pkg-config, and # libpcap didn't have .pc files until libpcap 1.9.0. # if(PCAP_FIND_QUIETLY) set(_quiet "QUIET") endif() # # First, try pkg-config. # Before doing so, set the PKG_CONFIG_PATH environment variable # to include all the directories in CMAKE_PREFIX_PATH. # # *If* we were to require CMake 3.1 or later on UN*X, # pkg_search_module() would do this for us, but, for now, # we're not doing that, in case somebody's building with # CMake on some "long-term support" version, predating # CMake 3.1, of an OS that supplies an earlier # version as a package. # # If we ever set a minimum of 3.1 or later on UN*X, we should # remove the environment variable changes. # # This is based on code in the CMake 3.12.4 FindPkgConfig.cmake, # which is "Distributed under the OSI-approved BSD 3-Clause License." # find_package(PkgConfig) # # Get the current PKG_CONFIG_PATH setting. # set(_pkg_config_path "$ENV{PKG_CONFIG_PATH}") # # Save it, so we can restore it after we run pkg-config. # set(_saved_pkg_config_path "${_pkg_config_path}") if(NOT "${CMAKE_PREFIX_PATH}" STREQUAL "") # # Convert it to a CMake-style path, before we add additional # values to it. # if(NOT "${_pkg_config_path}" STREQUAL "") file(TO_CMAKE_PATH "${_pkg_config_path}" _pkg_config_path) endif() # # Turn CMAKE_PREFIX_PATH into a list of extra paths to add # to _pkg_config_path. # set(_extra_paths "") list(APPEND _extra_paths ${CMAKE_PREFIX_PATH}) # Create a list of the possible pkgconfig subfolder (depending on # the system set(_lib_dirs) if(NOT DEFINED CMAKE_SYSTEM_NAME OR (CMAKE_SYSTEM_NAME MATCHES "^(Linux|kFreeBSD|GNU)$" AND NOT CMAKE_CROSSCOMPILING)) if(EXISTS "/etc/debian_version") # is this a debian system ? if(CMAKE_LIBRARY_ARCHITECTURE) list(APPEND _lib_dirs "lib/${CMAKE_LIBRARY_ARCHITECTURE}/pkgconfig") endif() else() # not debian, check the FIND_LIBRARY_USE_LIB32_PATHS and FIND_LIBRARY_USE_LIB64_PATHS properties get_property(uselib32 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB32_PATHS) if(uselib32 AND CMAKE_SIZEOF_VOID_P EQUAL 4) list(APPEND _lib_dirs "lib32/pkgconfig") endif() get_property(uselib64 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS) if(uselib64 AND CMAKE_SIZEOF_VOID_P EQUAL 8) list(APPEND _lib_dirs "lib64/pkgconfig") endif() get_property(uselibx32 GLOBAL PROPERTY FIND_LIBRARY_USE_LIBX32_PATHS) if(uselibx32 AND CMAKE_INTERNAL_PLATFORM_ABI STREQUAL "ELF X32") list(APPEND _lib_dirs "libx32/pkgconfig") endif() endif() endif() if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" AND NOT CMAKE_CROSSCOMPILING) list(APPEND _lib_dirs "libdata/pkgconfig") endif() list(APPEND _lib_dirs "lib/pkgconfig") list(APPEND _lib_dirs "share/pkgconfig") # Check if directories exist and eventually append them to the # pkgconfig path list foreach(_prefix_dir ${_extra_paths}) foreach(_lib_dir ${_lib_dirs}) if(EXISTS "${_prefix_dir}/${_lib_dir}") list(APPEND _pkg_config_path "${_prefix_dir}/${_lib_dir}") list(REMOVE_DUPLICATES _pkg_config_path) endif() endforeach() endforeach() if(NOT "${_pkg_config_path}" STREQUAL "") # remove empty values from the list list(REMOVE_ITEM _pkg_config_path "") file(TO_NATIVE_PATH "${_pkg_config_path}" _pkg_config_path) if(UNIX) string(REPLACE ";" ":" _pkg_config_path "${_pkg_config_path}") string(REPLACE "\\ " " " _pkg_config_path "${_pkg_config_path}") endif() set(ENV{PKG_CONFIG_PATH} "${_pkg_config_path}") endif() endif() pkg_search_module(CONFIG_PCAP ${_quiet} libpcap) set(ENV{PKG_CONFIG_PATH} "${_saved_pkg_config_path}") if(NOT CONFIG_PCAP_FOUND) # # That didn't work. Try pcap-config. # find_program(PCAP_CONFIG pcap-config) if(PCAP_CONFIG) # # We have pcap-config; use it. # if(NOT "${_quiet}" STREQUAL "QUIET") message(STATUS "Found pcap-config") endif() # # If this is a vendor-supplied pcap-config, which we define as # being "a pcap-config in /usr/bin or /usr/ccs/bin" (the latter # is for Solaris and Sun/Oracle Studio), there are some issues. # Work around them. # if("${PCAP_CONFIG}" STREQUAL /usr/bin/pcap-config OR "${PCAP_CONFIG}" STREQUAL /usr/ccs/bin/pcap-config) # # It's vendor-supplied. # if(APPLE) # # This is macOS or another Darwin-based OS. # # That means that /usr/bin/pcap-config it may provide # -I/usr/local/include with --cflags and -L/usr/local/lib # with --libs; if there's no pcap installed under /usr/local, # that will cause the build to fail, and if there is a pcap # installed there, you'll get that pcap even if you don't # want it. Remember that, so we ignore those values. # set(_broken_apple_pcap_config TRUE) elseif(CMAKE_SYSTEM_NAME STREQUAL "SunOS" AND CMAKE_SYSTEM_VERSION MATCHES "5[.][0-9.]*") # # This is Solaris 2 or later, i.e. SunOS 5.x. # # At least on Solaris 11; there's /usr/bin/pcap-config, which # reports -L/usr/lib with --libs, causing the 32-bit libraries # to be found, and there's /usr/bin/{64bitarch}/pcap-config, # where {64bitarch} is a name for the 64-bit version of the # instruction set, which reports -L /usr/lib/{64bitarch}, # causing the 64-bit libraries to be found. # # So if we're building 64-bit targets, we replace PCAP_CONFIG # with /usr/bin/{64bitarch}; we get {64bitarch} as the # output of "isainfo -n". # if(CMAKE_SIZEOF_VOID_P EQUAL 8) execute_process(COMMAND "isainfo" "-n" RESULT_VARIABLE ISAINFO_RESULT OUTPUT_VARIABLE ISAINFO_OUTPUT OUTPUT_STRIP_TRAILING_WHITESPACE ) if(ISAINFO_RESULT EQUAL 0) # # Success - change PCAP_CONFIG. # string(REPLACE "/bin/" "/bin/${ISAINFO_OUTPUT}/" PCAP_CONFIG "${PCAP_CONFIG}") endif() endif() endif() endif() # # Now get the include directories. # execute_process(COMMAND "${PCAP_CONFIG}" "--cflags" RESULT_VARIABLE PCAP_CONFIG_RESULT OUTPUT_VARIABLE PCAP_CONFIG_OUTPUT OUTPUT_STRIP_TRAILING_WHITESPACE ) if(NOT PCAP_CONFIG_RESULT EQUAL 0) message(FATAL_ERROR "pcap-config --cflags failed") endif() separate_arguments(CFLAGS_LIST UNIX_COMMAND ${PCAP_CONFIG_OUTPUT}) set(CONFIG_PCAP_INCLUDE_DIRS "") foreach(_arg IN LISTS CFLAGS_LIST) if(_arg MATCHES "^-I") # # Extract the directory by removing the -I. # string(REGEX REPLACE "-I" "" _dir ${_arg}) # # Work around macOS (and probably other Darwin) brokenness, # by not adding /usr/local/include if it's from the broken # Apple pcap-config. # if(NOT _broken_apple_pcap_config OR NOT "${_dir}" STREQUAL /usr/local/include) # Add it to CONFIG_PCAP_INCLUDE_DIRS list(APPEND CONFIG_PCAP_INCLUDE_DIRS ${_dir}) endif() endif() endforeach() # # Now, get the library directories and libraries for dynamic linking. # execute_process(COMMAND "${PCAP_CONFIG}" "--libs" RESULT_VARIABLE PCAP_CONFIG_RESULT OUTPUT_VARIABLE PCAP_CONFIG_OUTPUT OUTPUT_STRIP_TRAILING_WHITESPACE ) if(NOT PCAP_CONFIG_RESULT EQUAL 0) message(FATAL_ERROR "pcap-config --libs failed") endif() separate_arguments(LIBS_LIST UNIX_COMMAND ${PCAP_CONFIG_OUTPUT}) set(CONFIG_PCAP_LIBRARY_DIRS "") set(CONFIG_PCAP_LIBRARIES "") foreach(_arg IN LISTS LIBS_LIST) if(_arg MATCHES "^-L") # # Extract the directory by removing the -L. # string(REGEX REPLACE "-L" "" _dir ${_arg}) # # Work around macOS (and probably other Darwin) brokenness, # by not adding /usr/local/lib if it's from the broken # Apple pcap-config. # if(NOT _broken_apple_pcap_config OR NOT "${_dir}" STREQUAL /usr/local/lib) # Add this directory to CONFIG_PCAP_LIBRARY_DIRS list(APPEND CONFIG_PCAP_LIBRARY_DIRS ${_dir}) endif() elseif(_arg MATCHES "^-l") string(REGEX REPLACE "-l" "" _lib ${_arg}) list(APPEND CONFIG_PCAP_LIBRARIES ${_lib}) endif() endforeach() # # Now, get the library directories and libraries for static linking. # execute_process(COMMAND "${PCAP_CONFIG}" "--libs" "--static" RESULT_VARIABLE PCAP_CONFIG_RESULT OUTPUT_VARIABLE PCAP_CONFIG_OUTPUT ) if(NOT PCAP_CONFIG_RESULT EQUAL 0) message(FATAL_ERROR "pcap-config --libs --static failed") endif() separate_arguments(LIBS_LIST UNIX_COMMAND ${PCAP_CONFIG_OUTPUT}) set(CONFIG_PCAP_STATIC_LIBRARY_DIRS "") set(CONFIG_PCAP_STATIC_LIBRARIES "") foreach(_arg IN LISTS LIBS_LIST) if(_arg MATCHES "^-L") # # Extract the directory by removing the -L. # string(REGEX REPLACE "-L" "" _dir ${_arg}) # # Work around macOS (and probably other Darwin) brokenness, # by not adding /usr/local/lib if it's from the broken # Apple pcap-config. # if(NOT _broken_apple_pcap_config OR NOT "${_dir}" STREQUAL /usr/local/lib) # Add this directory to CONFIG_PCAP_STATIC_LIBRARY_DIRS list(APPEND CONFIG_PCAP_STATIC_LIBRARY_DIRS ${_dir}) endif() elseif(_arg MATCHES "^-l") string(REGEX REPLACE "-l" "" _lib ${_arg}) # # Try to find that library, so we get its full path, as # we do with dynamic libraries. # list(APPEND CONFIG_PCAP_STATIC_LIBRARIES ${_lib}) endif() endforeach() # # We've set CONFIG_PCAP_INCLUDE_DIRS, CONFIG_PCAP_LIBRARIES, and # CONFIG_PCAP_STATIC_LIBRARIES above; set CONFIG_PCAP_FOUND. # set(CONFIG_PCAP_FOUND YES) endif() endif() # # If CONFIG_PCAP_FOUND is set, we have information from pkg-config and # pcap-config; we need to convert library names to library full paths. # # If it's not set, we have to look for the libpcap headers and library # ourselves. # if(CONFIG_PCAP_FOUND) # # Use CONFIG_PCAP_INCLUDE_DIRS as the value for PCAP_INCLUDE_DIRS. # set(PCAP_INCLUDE_DIRS "${CONFIG_PCAP_INCLUDE_DIRS}") # # CMake *really* doesn't like the notion of specifying # "here are the directories in which to look for libraries" # except in find_library() calls; it *really* prefers using # full paths to library files, rather than library names. # foreach(_lib IN LISTS CONFIG_PCAP_LIBRARIES) find_library(_libfullpath ${_lib} HINTS ${CONFIG_PCAP_LIBRARY_DIRS}) list(APPEND PCAP_LIBRARIES ${_libfullpath}) # # Remove that from the cache; we're using it as a local variable, # but find_library insists on making it a cache variable. # unset(_libfullpath CACHE) endforeach() # # Now do the same for the static libraries. # set(SAVED_CMAKE_FIND_LIBRARY_SUFFIXES "${CMAKE_FIND_LIBRARY_SUFFIXES}") set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") foreach(_lib IN LISTS CONFIG_PCAP_STATIC_LIBRARIES) find_library(_libfullpath ${_lib} HINTS ${CONFIG_PCAP_LIBRARY_DIRS}) list(APPEND PCAP_STATIC_LIBRARIES ${_libfullpath}) # # Remove that from the cache; we're using it as a local variable, # but find_library insists on making it a cache variable. # unset(_libfullpath CACHE) endforeach() set(CMAKE_FIND_LIBRARY_SUFFIXES "${SAVED_CMAKE_FIND_LIBRARY_SUFFIXES}") # # We found libpcap using pkg-config or pcap-config. # set(PCAP_FOUND YES) else(CONFIG_PCAP_FOUND) # # We didn't have pkg-config, or we did but it didn't have .pc files # for libpcap, and we don't have pkg-config, so we have to look for # the headers and libraries ourself. # # We don't directly set PCAP_INCLUDE_DIRS or PCAP_LIBRARIES, as # they're not supposed to be cache entries, and find_path() and # find_library() set cache entries. # # Try to find the header file. # find_path(PCAP_INCLUDE_DIR pcap.h) # # Try to find the library # find_library(PCAP_LIBRARY pcap) # Try to find the static library (XXX - what about AIX?) set(SAVED_CMAKE_FIND_LIBRARY_SUFFIXES "${CMAKE_FIND_LIBRARY_SUFFIXES}") set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") find_library(PCAP_STATIC_LIBRARY pcap) set(CMAKE_FIND_LIBRARY_SUFFIXES "${SAVED_CMAKE_FIND_LIBRARY_SUFFIXES}") # # This will fail if REQUIRED is set and PCAP_INCLUDE_DIR or # PCAP_LIBRARY aren't set. # include(FindPackageHandleStandardArgs) find_package_handle_standard_args(PCAP DEFAULT_MSG PCAP_INCLUDE_DIR PCAP_LIBRARY ) mark_as_advanced( PCAP_INCLUDE_DIR PCAP_LIBRARY PCAP_STATIC_LIBRARY ) if(PCAP_FOUND) set(PCAP_INCLUDE_DIRS ${PCAP_INCLUDE_DIR}) set(PCAP_LIBRARIES ${PCAP_LIBRARY}) set(PCAP_STATIC_LIBRARIES ${PCAP_STATIC_LIBRARY}) endif(PCAP_FOUND) endif(CONFIG_PCAP_FOUND) endif(WIN32)