blob: 220ab95cb2e37b586b45d8d0a9cf034c582a1b6d [file] [log] [blame]
#
# 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 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)