1# 2# Try to find libpcap. 3# 4# To tell this module where to look, a user may set the environment variable 5# PCAP_ROOT to point cmake to the *root* of a directory with include and 6# lib subdirectories for pcap.dll (e.g WpdPack or npcap-sdk). 7# Alternatively, PCAP_ROOT may also be set from cmake command line or GUI 8# (e.g cmake -DPCAP_ROOT=C:\path\to\pcap [...]) 9# 10 11if(WIN32) 12 # 13 # Building for Windows. 14 # 15 # libpcap isn't set up to install .pc files or pcap-config on Windows, 16 # and it's not clear that either of them would work without a lot 17 # of additional effort. WinPcap doesn't supply them, and neither 18 # does Npcap. 19 # 20 # So just search for them directly. Look for both pcap and wpcap. 21 # Don't bother looking for static libraries; unlike most UN*Xes 22 # (with the exception of AIX), where different extensions are used 23 # for shared and static, Windows uses .lib both for import libraries 24 # for DLLs and for static libraries. 25 # 26 # We don't directly set PCAP_INCLUDE_DIRS or PCAP_LIBRARIES, as 27 # they're not supposed to be cache entries, and find_path() and 28 # find_library() set cache entries. 29 # 30 find_path(PCAP_INCLUDE_DIR pcap.h) 31 32 # The 64-bit Packet.lib is located under /x64 33 if(CMAKE_SIZEOF_VOID_P EQUAL 8) 34 # 35 # For the WinPcap and Npcap SDKs, the Lib subdirectory of the top-level 36 # directory contains 32-bit libraries; the 64-bit libraries are in the 37 # Lib/x64 directory. 38 # 39 # The only way to *FORCE* CMake to look in the Lib/x64 directory 40 # without searching in the Lib directory first appears to be to set 41 # CMAKE_LIBRARY_ARCHITECTURE to "x64". 42 # 43 set(CMAKE_LIBRARY_ARCHITECTURE "x64") 44 endif() 45 find_library(PCAP_LIBRARY NAMES pcap wpcap) 46 47 # 48 # Do the standard arg processing, including failing if it's a 49 # required package. 50 # 51 include(FindPackageHandleStandardArgs) 52 find_package_handle_standard_args(PCAP 53 DEFAULT_MSG 54 PCAP_INCLUDE_DIR 55 PCAP_LIBRARY 56 ) 57 mark_as_advanced( 58 PCAP_INCLUDE_DIR 59 PCAP_LIBRARY 60 ) 61 if(PCAP_FOUND) 62 set(PCAP_LIBRARIES ${PCAP_LIBRARY}) 63 set(PCAP_INCLUDE_DIRS ${PCAP_INCLUDE_DIR}) 64 endif() 65else(WIN32) 66 # 67 # Building for UN*X. 68 # 69 # See whether we were handed a QUIET argument, so we can pass it on 70 # to pkg_search_module. Do *NOT* pass on the REQUIRED argument, 71 # because, if pkg-config isn't found, or it is but it has no .pc 72 # files for libpcap, that is *not* necessarily an indication that 73 # libpcap isn't available - not all systems ship pkg-config, and 74 # libpcap didn't have .pc files until libpcap 1.9.0. 75 # 76 if(PCAP_FIND_QUIETLY) 77 set(_quiet "QUIET") 78 endif() 79 80 # 81 # First, try pkg-config. 82 # Before doing so, set the PKG_CONFIG_PATH environment variable 83 # to include all the directories in CMAKE_PREFIX_PATH. 84 # 85 # *If* we were to require CMake 3.1 or later on UN*X, 86 # pkg_search_module() would do this for us, but, for now, 87 # we're not doing that, in case somebody's building with 88 # CMake on some "long-term support" version, predating 89 # CMake 3.1, of an OS that that supplies an earlier 90 # version as a package. 91 # 92 # If we ever set a minimum of 3.1 or later on UN*X, we should 93 # remove the environment variable changes. 94 # 95 # This is based on code in the CMake 3.12.4 FindPkgConfig.cmake, 96 # which is "Distributed under the OSI-approved BSD 3-Clause License." 97 # 98 find_package(PkgConfig) 99 100 # 101 # Get the current PKG_CONFIG_PATH setting. 102 # 103 set(_pkg_config_path "$ENV{PKG_CONFIG_PATH}") 104 105 # 106 # Save it, so we can restore it after we run pkg-config. 107 # 108 set(_saved_pkg_config_path "${_pkg_config_path}") 109 110 if(NOT "${CMAKE_PREFIX_PATH}" STREQUAL "") 111 # 112 # Convert it to a CMake-style path, before we add additional 113 # values to it. 114 # 115 if(NOT "${_pkg_config_path}" STREQUAL "") 116 file(TO_CMAKE_PATH "${_pkg_config_path}" _pkg_config_path) 117 endif() 118 119 # 120 # Turn CMAKE_PREFIX_PATH into a list of extra paths to add 121 # to _pkg_config_path. 122 # 123 set(_extra_paths "") 124 list(APPEND _extra_paths ${CMAKE_PREFIX_PATH}) 125 126 # Create a list of the possible pkgconfig subfolder (depending on 127 # the system 128 set(_lib_dirs) 129 if(NOT DEFINED CMAKE_SYSTEM_NAME 130 OR (CMAKE_SYSTEM_NAME MATCHES "^(Linux|kFreeBSD|GNU)$" 131 AND NOT CMAKE_CROSSCOMPILING)) 132 if(EXISTS "/etc/debian_version") # is this a debian system ? 133 if(CMAKE_LIBRARY_ARCHITECTURE) 134 list(APPEND _lib_dirs "lib/${CMAKE_LIBRARY_ARCHITECTURE}/pkgconfig") 135 endif() 136 else() 137 # not debian, check the FIND_LIBRARY_USE_LIB32_PATHS and FIND_LIBRARY_USE_LIB64_PATHS properties 138 get_property(uselib32 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB32_PATHS) 139 if(uselib32 AND CMAKE_SIZEOF_VOID_P EQUAL 4) 140 list(APPEND _lib_dirs "lib32/pkgconfig") 141 endif() 142 get_property(uselib64 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS) 143 if(uselib64 AND CMAKE_SIZEOF_VOID_P EQUAL 8) 144 list(APPEND _lib_dirs "lib64/pkgconfig") 145 endif() 146 get_property(uselibx32 GLOBAL PROPERTY FIND_LIBRARY_USE_LIBX32_PATHS) 147 if(uselibx32 AND CMAKE_INTERNAL_PLATFORM_ABI STREQUAL "ELF X32") 148 list(APPEND _lib_dirs "libx32/pkgconfig") 149 endif() 150 endif() 151 endif() 152 if(CMAKE_SYSTEM_NAME STREQUAL "FreeBSD" AND NOT CMAKE_CROSSCOMPILING) 153 list(APPEND _lib_dirs "libdata/pkgconfig") 154 endif() 155 list(APPEND _lib_dirs "lib/pkgconfig") 156 list(APPEND _lib_dirs "share/pkgconfig") 157 158 # Check if directories exist and eventually append them to the 159 # pkgconfig path list 160 foreach(_prefix_dir ${_extra_paths}) 161 foreach(_lib_dir ${_lib_dirs}) 162 if(EXISTS "${_prefix_dir}/${_lib_dir}") 163 list(APPEND _pkg_config_path "${_prefix_dir}/${_lib_dir}") 164 list(REMOVE_DUPLICATES _pkg_config_path) 165 endif() 166 endforeach() 167 endforeach() 168 169 if(NOT "${_pkg_config_path}" STREQUAL "") 170 # remove empty values from the list 171 list(REMOVE_ITEM _pkg_config_path "") 172 file(TO_NATIVE_PATH "${_pkg_config_path}" _pkg_config_path) 173 if(UNIX) 174 string(REPLACE ";" ":" _pkg_config_path "${_pkg_config_path}") 175 string(REPLACE "\\ " " " _pkg_config_path "${_pkg_config_path}") 176 endif() 177 set(ENV{PKG_CONFIG_PATH} "${_pkg_config_path}") 178 endif() 179 endif() 180 pkg_search_module(CONFIG_PCAP ${_quiet} libpcap) 181 set(ENV{PKG_CONFIG_PATH} "${_saved_pkg_config_path}") 182 183 if(NOT CONFIG_PCAP_FOUND) 184 # 185 # That didn't work. Try pcap-config. 186 # 187 find_program(PCAP_CONFIG pcap-config) 188 if(PCAP_CONFIG) 189 # 190 # We have pcap-config; use it. 191 # 192 if(NOT "${_quiet}" STREQUAL "QUIET") 193 message(STATUS "Found pcap-config") 194 endif() 195 196 # 197 # if this is macOS or some other Darwin-based OS, check whether 198 # it's the system-supplied one. 199 # 200 if(APPLE AND "${PCAP_CONFIG}" STREQUAL /usr/bin/pcap-config) 201 # 202 # It is - remember that, so that if it provides -I/usr/local/include 203 # with --cflags, or -L/usr/local/lib with --libs, we ignore it; 204 # the macOS pcap-config does that even though the headers aren't 205 # under /usr/local/include and the library isn't in /usr/local/lib. 206 # 207 set(_broken_apple_pcap_config TRUE) 208 endif() 209 210 # 211 # Now get the include directories. 212 # 213 execute_process(COMMAND "${PCAP_CONFIG}" "--cflags" 214 RESULT_VARIABLE PCAP_CONFIG_RESULT 215 OUTPUT_VARIABLE PCAP_CONFIG_OUTPUT 216 OUTPUT_STRIP_TRAILING_WHITESPACE 217 ) 218 if(NOT PCAP_CONFIG_RESULT EQUAL 0) 219 message(FATAL_ERROR "pcap-config --cflags failed") 220 endif() 221 separate_arguments(CFLAGS_LIST UNIX_COMMAND ${PCAP_CONFIG_OUTPUT}) 222 set(CONFIG_PCAP_INCLUDE_DIRS "") 223 foreach(_arg IN LISTS CFLAGS_LIST) 224 if(_arg MATCHES "^-I") 225 # 226 # Extract the directory by removing the -I. 227 # 228 string(REGEX REPLACE "-I" "" _dir ${_arg}) 229 # 230 # Work around macOS (and probably other Darwin) brokenness, 231 # by not adding /usr/local/include if it's from the broken 232 # Apple pcap-config. 233 # 234 if(NOT _broken_apple_pcap_config OR 235 NOT "${_dir}" STREQUAL /usr/local/include) 236 # Add it to CONFIG_PCAP_INCLUDE_DIRS 237 list(APPEND CONFIG_PCAP_INCLUDE_DIRS ${_dir}) 238 endif() 239 endif() 240 endforeach() 241 242 # 243 # Now, get the library directories and libraries for dynamic linking. 244 # 245 execute_process(COMMAND "${PCAP_CONFIG}" "--libs" 246 RESULT_VARIABLE PCAP_CONFIG_RESULT 247 OUTPUT_VARIABLE PCAP_CONFIG_OUTPUT 248 OUTPUT_STRIP_TRAILING_WHITESPACE 249 ) 250 if(NOT PCAP_CONFIG_RESULT EQUAL 0) 251 message(FATAL_ERROR "pcap-config --libs failed") 252 endif() 253 separate_arguments(LIBS_LIST UNIX_COMMAND ${PCAP_CONFIG_OUTPUT}) 254 set(CONFIG_PCAP_LIBRARY_DIRS "") 255 set(CONFIG_PCAP_LIBRARIES "") 256 foreach(_arg IN LISTS LIBS_LIST) 257 if(_arg MATCHES "^-L") 258 # 259 # Extract the directory by removing the -L. 260 # 261 string(REGEX REPLACE "-L" "" _dir ${_arg}) 262 # 263 # Work around macOS (and probably other Darwin) brokenness, 264 # by not adding /usr/local/lib if it's from the broken 265 # Apple pcap-config. 266 # 267 if(NOT _broken_apple_pcap_config OR 268 NOT "${_dir}" STREQUAL /usr/local/lib) 269 # Add this directory to CONFIG_PCAP_LIBRARY_DIRS 270 list(APPEND CONFIG_PCAP_LIBRARY_DIRS ${_dir}) 271 endif() 272 elseif(_arg MATCHES "^-l") 273 string(REGEX REPLACE "-l" "" _lib ${_arg}) 274 list(APPEND CONFIG_PCAP_LIBRARIES ${_lib}) 275 endif() 276 endforeach() 277 278 # 279 # Now, get the library directories and libraries for static linking. 280 # 281 execute_process(COMMAND "${PCAP_CONFIG}" "--libs" "--static" 282 RESULT_VARIABLE PCAP_CONFIG_RESULT 283 OUTPUT_VARIABLE PCAP_CONFIG_OUTPUT 284 ) 285 if(NOT PCAP_CONFIG_RESULT EQUAL 0) 286 message(FATAL_ERROR "pcap-config --libs --static failed") 287 endif() 288 separate_arguments(LIBS_LIST UNIX_COMMAND ${PCAP_CONFIG_OUTPUT}) 289 set(CONFIG_PCAP_STATIC_LIBRARY_DIRS "") 290 set(CONFIG_PCAP_STATIC_LIBRARIES "") 291 foreach(_arg IN LISTS LIBS_LIST) 292 if(_arg MATCHES "^-L") 293 # 294 # Extract the directory by removing the -L. 295 # 296 string(REGEX REPLACE "-L" "" _dir ${_arg}) 297 # 298 # Work around macOS (and probably other Darwin) brokenness, 299 # by not adding /usr/local/lib if it's from the broken 300 # Apple pcap-config. 301 # 302 if(NOT _broken_apple_pcap_config OR 303 NOT "${_dir}" STREQUAL /usr/local/lib) 304 # Add this directory to CONFIG_PCAP_STATIC_LIBRARY_DIRS 305 list(APPEND CONFIG_PCAP_STATIC_LIBRARY_DIRS ${_dir}) 306 endif() 307 elseif(_arg MATCHES "^-l") 308 string(REGEX REPLACE "-l" "" _lib ${_arg}) 309 # 310 # Try to find that library, so we get its full path, as 311 # we do with dynamic libraries. 312 # 313 list(APPEND CONFIG_PCAP_STATIC_LIBRARIES ${_lib}) 314 endif() 315 endforeach() 316 317 # 318 # We've set CONFIG_PCAP_INCLUDE_DIRS, CONFIG_PCAP_LIBRARIES, and 319 # CONFIG_PCAP_STATIC_LIBRARIES above; set CONFIG_PCAP_FOUND. 320 # 321 set(CONFIG_PCAP_FOUND YES) 322 endif() 323 endif() 324 325 # 326 # If CONFIG_PCAP_FOUND is set, we have information from pkg-config and 327 # pcap-config; we need to convert library names to library full paths. 328 # 329 # If it's not set, we have to look for the libpcap headers and library 330 # ourselves. 331 # 332 if(CONFIG_PCAP_FOUND) 333 # 334 # Use CONFIG_PCAP_INCLUDE_DIRS as the value for PCAP_INCLUDE_DIRS. 335 # 336 set(PCAP_INCLUDE_DIRS "${CONFIG_PCAP_INCLUDE_DIRS}") 337 338 # 339 # CMake *really* doesn't like the notion of specifying 340 # "here are the directories in which to look for libraries" 341 # except in find_library() calls; it *really* prefers using 342 # full paths to library files, rather than library names. 343 # 344 foreach(_lib IN LISTS CONFIG_PCAP_LIBRARIES) 345 find_library(_libfullpath ${_lib} HINTS ${CONFIG_PCAP_LIBRARY_DIRS}) 346 list(APPEND PCAP_LIBRARIES ${_libfullpath}) 347 # 348 # Remove that from the cache; we're using it as a local variable, 349 # but find_library insists on making it a cache variable. 350 # 351 unset(_libfullpath CACHE) 352 endforeach() 353 354 # 355 # Now do the same for the static libraries. 356 # 357 set(SAVED_CMAKE_FIND_LIBRARY_SUFFIXES "${CMAKE_FIND_LIBRARY_SUFFIXES}") 358 set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") 359 foreach(_lib IN LISTS CONFIG_PCAP_STATIC_LIBRARIES) 360 find_library(_libfullpath ${_lib} HINTS ${CONFIG_PCAP_LIBRARY_DIRS}) 361 list(APPEND PCAP_STATIC_LIBRARIES ${_libfullpath}) 362 # 363 # Remove that from the cache; we're using it as a local variable, 364 # but find_library insists on making it a cache variable. 365 # 366 unset(_libfullpath CACHE) 367 endforeach() 368 set(CMAKE_FIND_LIBRARY_SUFFIXES "${SAVED_CMAKE_FIND_LIBRARY_SUFFIXES}") 369 370 # 371 # We found libpcap using pkg-config or pcap-config. 372 # 373 set(PCAP_FOUND YES) 374 else(CONFIG_PCAP_FOUND) 375 # 376 # We didn't have pkg-config, or we did but it didn't have .pc files 377 # for libpcap, and we don't have pkg-config, so we have to look for 378 # the headers and libraries ourself. 379 # 380 # We don't directly set PCAP_INCLUDE_DIRS or PCAP_LIBRARIES, as 381 # they're not supposed to be cache entries, and find_path() and 382 # find_library() set cache entries. 383 # 384 # Try to find the header file. 385 # 386 find_path(PCAP_INCLUDE_DIR pcap.h) 387 388 # 389 # Try to find the library 390 # 391 find_library(PCAP_LIBRARY pcap) 392 393 # Try to find the static library (XXX - what about AIX?) 394 set(SAVED_CMAKE_FIND_LIBRARY_SUFFIXES "${CMAKE_FIND_LIBRARY_SUFFIXES}") 395 set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") 396 find_library(PCAP_STATIC_LIBRARY pcap) 397 set(CMAKE_FIND_LIBRARY_SUFFIXES "${SAVED_CMAKE_FIND_LIBRARY_SUFFIXES}") 398 399 # 400 # This will fail if REQUIRED is set and PCAP_INCLUDE_DIR or 401 # PCAP_LIBRARY aren't set. 402 # 403 include(FindPackageHandleStandardArgs) 404 find_package_handle_standard_args(PCAP 405 DEFAULT_MSG 406 PCAP_INCLUDE_DIR 407 PCAP_LIBRARY 408 ) 409 410 mark_as_advanced( 411 PCAP_INCLUDE_DIR 412 PCAP_LIBRARY 413 PCAP_STATIC_LIBRARY 414 ) 415 416 if(PCAP_FOUND) 417 set(PCAP_INCLUDE_DIRS ${PCAP_INCLUDE_DIR}) 418 set(PCAP_LIBRARIES ${PCAP_LIBRARY}) 419 set(PCAP_STATIC_LIBRARIES ${PCAP_STATIC_LIBRARY}) 420 endif(PCAP_FOUND) 421 endif(CONFIG_PCAP_FOUND) 422endif(WIN32) 423