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 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 a vendor-supplied pcap-config, which we define as 198 # being "a pcap-config in /usr/bin or /usr/ccs/bin" (the latter 199 # is for Solaris and Sun/Oracle Studio), there are some issues. 200 # Work around them. 201 # 202 if("${PCAP_CONFIG}" STREQUAL /usr/bin/pcap-config OR 203 "${PCAP_CONFIG}" STREQUAL /usr/ccs/bin/pcap-config) 204 # 205 # It's vendor-supplied. 206 # 207 if(APPLE) 208 # 209 # This is macOS or another Darwin-based OS. 210 # 211 # That means that /usr/bin/pcap-config it may provide 212 # -I/usr/local/include with --cflags and -L/usr/local/lib 213 # with --libs; if there's no pcap installed under /usr/local, 214 # that will cause the build to fail, and if there is a pcap 215 # installed there, you'll get that pcap even if you don't 216 # want it. Remember that, so we ignore those values. 217 # 218 set(_broken_apple_pcap_config TRUE) 219 elseif(CMAKE_SYSTEM_NAME STREQUAL "SunOS" AND CMAKE_SYSTEM_VERSION MATCHES "5[.][0-9.]*") 220 # 221 # This is Solaris 2 or later, i.e. SunOS 5.x. 222 # 223 # At least on Solaris 11; there's /usr/bin/pcap-config, which 224 # reports -L/usr/lib with --libs, causing the 32-bit libraries 225 # to be found, and there's /usr/bin/{64bitarch}/pcap-config, 226 # where {64bitarch} is a name for the 64-bit version of the 227 # instruction set, which reports -L /usr/lib/{64bitarch}, 228 # causing the 64-bit libraries to be found. 229 # 230 # So if we're building 64-bit targets, we replace PCAP_CONFIG 231 # with /usr/bin/{64bitarch}; we get {64bitarch} as the 232 # output of "isainfo -n". 233 # 234 if(CMAKE_SIZEOF_VOID_P EQUAL 8) 235 execute_process(COMMAND "isainfo" "-n" 236 RESULT_VARIABLE ISAINFO_RESULT 237 OUTPUT_VARIABLE ISAINFO_OUTPUT 238 OUTPUT_STRIP_TRAILING_WHITESPACE 239 ) 240 if(ISAINFO_RESULT EQUAL 0) 241 # 242 # Success - change PCAP_CONFIG. 243 # 244 string(REPLACE "/bin/" "/bin/${ISAINFO_OUTPUT}/" PCAP_CONFIG "${PCAP_CONFIG}") 245 endif() 246 endif() 247 endif() 248 endif() 249 250 # 251 # Now get the include directories. 252 # 253 execute_process(COMMAND "${PCAP_CONFIG}" "--cflags" 254 RESULT_VARIABLE PCAP_CONFIG_RESULT 255 OUTPUT_VARIABLE PCAP_CONFIG_OUTPUT 256 OUTPUT_STRIP_TRAILING_WHITESPACE 257 ) 258 if(NOT PCAP_CONFIG_RESULT EQUAL 0) 259 message(FATAL_ERROR "pcap-config --cflags failed") 260 endif() 261 separate_arguments(CFLAGS_LIST UNIX_COMMAND ${PCAP_CONFIG_OUTPUT}) 262 set(CONFIG_PCAP_INCLUDE_DIRS "") 263 foreach(_arg IN LISTS CFLAGS_LIST) 264 if(_arg MATCHES "^-I") 265 # 266 # Extract the directory by removing the -I. 267 # 268 string(REGEX REPLACE "-I" "" _dir ${_arg}) 269 # 270 # Work around macOS (and probably other Darwin) brokenness, 271 # by not adding /usr/local/include if it's from the broken 272 # Apple pcap-config. 273 # 274 if(NOT _broken_apple_pcap_config OR 275 NOT "${_dir}" STREQUAL /usr/local/include) 276 # Add it to CONFIG_PCAP_INCLUDE_DIRS 277 list(APPEND CONFIG_PCAP_INCLUDE_DIRS ${_dir}) 278 endif() 279 endif() 280 endforeach() 281 282 # 283 # Now, get the library directories and libraries for dynamic linking. 284 # 285 execute_process(COMMAND "${PCAP_CONFIG}" "--libs" 286 RESULT_VARIABLE PCAP_CONFIG_RESULT 287 OUTPUT_VARIABLE PCAP_CONFIG_OUTPUT 288 OUTPUT_STRIP_TRAILING_WHITESPACE 289 ) 290 if(NOT PCAP_CONFIG_RESULT EQUAL 0) 291 message(FATAL_ERROR "pcap-config --libs failed") 292 endif() 293 separate_arguments(LIBS_LIST UNIX_COMMAND ${PCAP_CONFIG_OUTPUT}) 294 set(CONFIG_PCAP_LIBRARY_DIRS "") 295 set(CONFIG_PCAP_LIBRARIES "") 296 foreach(_arg IN LISTS LIBS_LIST) 297 if(_arg MATCHES "^-L") 298 # 299 # Extract the directory by removing the -L. 300 # 301 string(REGEX REPLACE "-L" "" _dir ${_arg}) 302 # 303 # Work around macOS (and probably other Darwin) brokenness, 304 # by not adding /usr/local/lib if it's from the broken 305 # Apple pcap-config. 306 # 307 if(NOT _broken_apple_pcap_config OR 308 NOT "${_dir}" STREQUAL /usr/local/lib) 309 # Add this directory to CONFIG_PCAP_LIBRARY_DIRS 310 list(APPEND CONFIG_PCAP_LIBRARY_DIRS ${_dir}) 311 endif() 312 elseif(_arg MATCHES "^-l") 313 string(REGEX REPLACE "-l" "" _lib ${_arg}) 314 list(APPEND CONFIG_PCAP_LIBRARIES ${_lib}) 315 endif() 316 endforeach() 317 318 # 319 # Now, get the library directories and libraries for static linking. 320 # 321 execute_process(COMMAND "${PCAP_CONFIG}" "--libs" "--static" 322 RESULT_VARIABLE PCAP_CONFIG_RESULT 323 OUTPUT_VARIABLE PCAP_CONFIG_OUTPUT 324 ) 325 if(NOT PCAP_CONFIG_RESULT EQUAL 0) 326 message(FATAL_ERROR "pcap-config --libs --static failed") 327 endif() 328 separate_arguments(LIBS_LIST UNIX_COMMAND ${PCAP_CONFIG_OUTPUT}) 329 set(CONFIG_PCAP_STATIC_LIBRARY_DIRS "") 330 set(CONFIG_PCAP_STATIC_LIBRARIES "") 331 foreach(_arg IN LISTS LIBS_LIST) 332 if(_arg MATCHES "^-L") 333 # 334 # Extract the directory by removing the -L. 335 # 336 string(REGEX REPLACE "-L" "" _dir ${_arg}) 337 # 338 # Work around macOS (and probably other Darwin) brokenness, 339 # by not adding /usr/local/lib if it's from the broken 340 # Apple pcap-config. 341 # 342 if(NOT _broken_apple_pcap_config OR 343 NOT "${_dir}" STREQUAL /usr/local/lib) 344 # Add this directory to CONFIG_PCAP_STATIC_LIBRARY_DIRS 345 list(APPEND CONFIG_PCAP_STATIC_LIBRARY_DIRS ${_dir}) 346 endif() 347 elseif(_arg MATCHES "^-l") 348 string(REGEX REPLACE "-l" "" _lib ${_arg}) 349 # 350 # Try to find that library, so we get its full path, as 351 # we do with dynamic libraries. 352 # 353 list(APPEND CONFIG_PCAP_STATIC_LIBRARIES ${_lib}) 354 endif() 355 endforeach() 356 357 # 358 # We've set CONFIG_PCAP_INCLUDE_DIRS, CONFIG_PCAP_LIBRARIES, and 359 # CONFIG_PCAP_STATIC_LIBRARIES above; set CONFIG_PCAP_FOUND. 360 # 361 set(CONFIG_PCAP_FOUND YES) 362 endif() 363 endif() 364 365 # 366 # If CONFIG_PCAP_FOUND is set, we have information from pkg-config and 367 # pcap-config; we need to convert library names to library full paths. 368 # 369 # If it's not set, we have to look for the libpcap headers and library 370 # ourselves. 371 # 372 if(CONFIG_PCAP_FOUND) 373 # 374 # Use CONFIG_PCAP_INCLUDE_DIRS as the value for PCAP_INCLUDE_DIRS. 375 # 376 set(PCAP_INCLUDE_DIRS "${CONFIG_PCAP_INCLUDE_DIRS}") 377 378 # 379 # CMake *really* doesn't like the notion of specifying 380 # "here are the directories in which to look for libraries" 381 # except in find_library() calls; it *really* prefers using 382 # full paths to library files, rather than library names. 383 # 384 foreach(_lib IN LISTS CONFIG_PCAP_LIBRARIES) 385 find_library(_libfullpath ${_lib} HINTS ${CONFIG_PCAP_LIBRARY_DIRS}) 386 list(APPEND PCAP_LIBRARIES ${_libfullpath}) 387 # 388 # Remove that from the cache; we're using it as a local variable, 389 # but find_library insists on making it a cache variable. 390 # 391 unset(_libfullpath CACHE) 392 endforeach() 393 394 # 395 # Now do the same for the static libraries. 396 # 397 set(SAVED_CMAKE_FIND_LIBRARY_SUFFIXES "${CMAKE_FIND_LIBRARY_SUFFIXES}") 398 set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") 399 foreach(_lib IN LISTS CONFIG_PCAP_STATIC_LIBRARIES) 400 find_library(_libfullpath ${_lib} HINTS ${CONFIG_PCAP_LIBRARY_DIRS}) 401 list(APPEND PCAP_STATIC_LIBRARIES ${_libfullpath}) 402 # 403 # Remove that from the cache; we're using it as a local variable, 404 # but find_library insists on making it a cache variable. 405 # 406 unset(_libfullpath CACHE) 407 endforeach() 408 set(CMAKE_FIND_LIBRARY_SUFFIXES "${SAVED_CMAKE_FIND_LIBRARY_SUFFIXES}") 409 410 # 411 # We found libpcap using pkg-config or pcap-config. 412 # 413 set(PCAP_FOUND YES) 414 else(CONFIG_PCAP_FOUND) 415 # 416 # We didn't have pkg-config, or we did but it didn't have .pc files 417 # for libpcap, and we don't have pkg-config, so we have to look for 418 # the headers and libraries ourself. 419 # 420 # We don't directly set PCAP_INCLUDE_DIRS or PCAP_LIBRARIES, as 421 # they're not supposed to be cache entries, and find_path() and 422 # find_library() set cache entries. 423 # 424 # Try to find the header file. 425 # 426 find_path(PCAP_INCLUDE_DIR pcap.h) 427 428 # 429 # Try to find the library 430 # 431 find_library(PCAP_LIBRARY pcap) 432 433 # Try to find the static library (XXX - what about AIX?) 434 set(SAVED_CMAKE_FIND_LIBRARY_SUFFIXES "${CMAKE_FIND_LIBRARY_SUFFIXES}") 435 set(CMAKE_FIND_LIBRARY_SUFFIXES ".a") 436 find_library(PCAP_STATIC_LIBRARY pcap) 437 set(CMAKE_FIND_LIBRARY_SUFFIXES "${SAVED_CMAKE_FIND_LIBRARY_SUFFIXES}") 438 439 # 440 # This will fail if REQUIRED is set and PCAP_INCLUDE_DIR or 441 # PCAP_LIBRARY aren't set. 442 # 443 include(FindPackageHandleStandardArgs) 444 find_package_handle_standard_args(PCAP 445 DEFAULT_MSG 446 PCAP_INCLUDE_DIR 447 PCAP_LIBRARY 448 ) 449 450 mark_as_advanced( 451 PCAP_INCLUDE_DIR 452 PCAP_LIBRARY 453 PCAP_STATIC_LIBRARY 454 ) 455 456 if(PCAP_FOUND) 457 set(PCAP_INCLUDE_DIRS ${PCAP_INCLUDE_DIR}) 458 set(PCAP_LIBRARIES ${PCAP_LIBRARY}) 459 set(PCAP_STATIC_LIBRARIES ${PCAP_STATIC_LIBRARY}) 460 endif(PCAP_FOUND) 461 endif(CONFIG_PCAP_FOUND) 462endif(WIN32) 463