]> The Tcpdump Group git mirrors - tcpdump/commitdiff
Redo the checks for libpcap.
authorGuy Harris <[email protected]>
Mon, 29 Apr 2019 18:55:27 +0000 (11:55 -0700)
committerGuy Harris <[email protected]>
Mon, 29 Apr 2019 18:55:27 +0000 (11:55 -0700)
On Windows, don't bother with pkg-config or pcap-config.  We make no
effort, in libpcap, to make them work on Windows, we don't install the
.pc files or pcap-config on Windows with the CMake build, and neither
WinPcap nor Npcap install them.

On UN*X:

For pkg-config and pcap-config, set variables named CONFIG_PCAP_xxx.
pkg-config's xxx_LIBRARIES and xxx_STATIC_LIBRARIES variables have only
library names, not library full paths, so we need to use find_library()
to convert them to full paths.  For pcap-config, generate
library-name-only CONFIG_PCAP_LIBRARIES and CONFIG_PCAP_STATIC_LIBRARIES
variables, as well as CONFIG_PCAP_FOUND.

If CONFIG_PCAP_FOUND is true, meaning that either pkg-config or
pcap-config succeeded, copy CONFIG_PCAP_INCLUDE_DIRS to
PCAP_INCLUDE_DIRS, iterate over CONFIG_PCAP_LIBRARIES and
CONFIG_PCAP_STATIC_LIBRARIES to generate full paths for all of the
libraries and put them in PCAP_LIBRARIES and PCAP_STATIC_LIBRARIES, and
set PCAP_FOUND.

If CONFIG_PCAP_FOUND is false, search for headers and libraries
ourselves.

cmake/Modules/FindPCAP.cmake

index 077405e53c3f938092aae53d12c849f8021a1e3d..6b0fbb6ede128a39549e4eb775b5f6f808c26be3 100644 (file)
 # Try to find libpcap.
 #
 
-#
-# First, try pkg-config.
-#
-find_package(PkgConfig)
-pkg_search_module(PCAP libpcap)
-
-if(PCAP_FOUND)
+if(WIN32)
   #
-  # That worked.
-  # Now, for each library, try to find it, so we get its full path.
-  # 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.
+  # Building for Windows.
   #
-  set(_pcap_libraries "${PCAP_LIBRARIES}")
-  set(PCAP_LIBRARIES "")
-  foreach(_lib IN LISTS _pcap_libraries)
-    #
-    # Try to find that library.
+  # 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)
     #
-    find_library(_libfullpath ${_lib} HINTS ${PCAP_LIBRARY_DIRS})
-    list(APPEND PCAP_LIBRARIES ${_libfullpath})
+    # 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.
     #
-    # Remove that from the cache; we're using it as a local variable,
-    # but find_library insists on making it a cache variable.
+    # 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".
     #
-    unset(_libfullpath CACHE)
-  endforeach()
+    set(CMAKE_LIBRARY_ARCHITECTURE "x64")
+  endif()
+  find_library(PCAP_LIBRARY pcap wpcap)
 
   #
-  # Now find the static libraries.
-  # (XXX - what about AIX?)
+  # Do the standard arg processing, including failing if it's a
+  # required package.
   #
-  set(_pcap_static_libraries "${PCAP_STATIC_LIBRARIES}")
-  set(PCAP_STATIC_LIBRARIES "")
-  set(SAVED_CMAKE_FIND_LIBRARY_SUFFIXES "${CMAKE_FIND_LIBRARY_SUFFIXES}")
-  set(CMAKE_FIND_LIBRARY_SUFFIXES ".a")
-  foreach(_lib IN LISTS _pcap_static_libraries)
-    #
-    # Try to find that library, so we get its full path, as
-    # we do with dynamic libraries.
-    #
-    find_library(_libfullpath ${_lib} HINTS ${PCAP_LIBRARY_DIRS})
-    list(APPEND PCAP_STATIC_LIBRARIES ${_libfullpath})
+  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_QUIET)
+    set(_quiet "QUIET")
+  endif()
+
+  #
+  # First, try pkg-config.
+  #
+  find_package(PkgConfig)
+  pkg_search_module(CONFIG_PCAP ${QUIET} libpcap)
+
+  if(NOT CONFIG_PCAP_FOUND)
     #
-    # Remove that from the cache; we're using it as a local variable,
-    # but find_library insists on making it a cache variable.
+    # That didn't work.  Try pcap-config.
     #
-    unset(_libfullpath CACHE)
-  endforeach()
-  set(CMAKE_FIND_LIBRARY_SUFFIXES "${SAVED_CMAKE_FIND_LIBRARY_SUFFIXES}")
-else(PCAP_FOUND)
+    find_program(PCAP_CONFIG pcap-config)
+    if(PCAP_CONFIG)
+      #
+      # We have pcap-config; use it.
+      #
+      # if this is macOS or some other Darwin-based OS, check whether
+      # it's the system-supplied one.
+      #
+      if(APPLE AND "${PCAP_CONFIG}" STREQUAL /usr/bin/pcap-config)
+        #
+        # It is - remember that, so that if it provides -I/usr/local/include
+        # with --cflags, or -L/usr/local/lib with --libs, we ignore it;
+        # the macOS pcap-config does that even though the headers aren't
+        # under /usr/local/include and the library isn't in /usr/local/lib.
+        #
+        set(_broken_apple_pcap_config TRUE)
+      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.
   #
-  # That didn't work.  Try pcap-config.
+  # If it's not set, we have to look for the libpcap headers and library
+  # ourselves.
   #
-  find_program(PCAP_CONFIG pcap-config)
-  if(PCAP_CONFIG)
+  if(CONFIG_PCAP_FOUND)
     #
-    # We have pcap-config; use it.
-    # XXX - what if this is on Windows?  If you're using, for example,
-    # MinGW, that might be the right thing to do, *if* pcap-config
-    # were made to work properly on Windows, but what about MSVC?
+    # Use CONFIG_PCAP_INCLUDE_DIRS as the value for PCAP_INCLUDE_DIRS.
     #
-    # First, get the include directory.
+    set(PCAP_INCLUDE_DIRS "${CONFIG_PCAP_INCLUDE_DIRS}")
+
     #
-    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()
+    # 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()
+
     #
-    # XXX - this assumes that there's only one -I flag in the output
-    # of pcap-config --cflags.  That *should* be the case.
+    # Now do the same for the static libraries.
     #
-    string(REGEX REPLACE "-I" "" _pcap_include_dir "${PCAP_CONFIG_OUTPUT}")
+    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}")
 
-    # Try to find the header
-    # We use what pcap-config provided as a hint, because the
-    # pcap-config that ships with macOS bogusly supplies
-    # -I/usr/local/include even though the header isn't
-    # there (it may be under /usr/include or it may be
-    # buried in the Xcode app bundle).
-    find_path(PCAP_INCLUDE_DIRS pcap.h HINTS ${_pcap_include_dir})
+    #
+    # 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)
 
-    # Now, get the libraries.
-    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(_pcap_library_dirs "")
-    set(PCAP_LIBRARIES "")
-    foreach(_arg IN LISTS LIBS_LIST)
-      if(_arg MATCHES "^-L")
-        # Add this directory to _pcap_library_dirs
-        string(REGEX REPLACE "-L" "" _dir ${_arg})
-        list(APPEND _pcap_library_dirs ${_dir})
-      elseif(_arg MATCHES "^-l")
-        string(REGEX REPLACE "-l" "" _lib ${_arg})
-        #
-        # Try to find that library, so we get its full path.  See the
-        # comment above for why we do this.
-        #
-        # Furthermore, the pcap-config shipped with macOS reports
-        # -I/usr/local/include for --cflags and -L/usr/local/lib for
-        # --libs, rather than reporting the appropriate system (or
-        # Xcode application) directory.
-        #
-        find_library(_libfullpath ${_lib} HINTS ${__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)
-      endif()
-    endforeach()
+    #
+    # Try to find the library
+    #
+    find_library(PCAP_LIBRARY pcap)
 
-    # Now, get the library directories and libraries for static linking.
-    # (XXX - what about AIX?)
-    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(_pcap_static_library_dirs "")
-    set(PCAP_STATIC_LIBRARIES "")
+    # 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")
-    foreach(_arg IN LISTS LIBS_LIST)
-      if(_arg MATCHES "^-L")
-        # Add this directory to _pcap_static_library_dirs
-        string(REGEX REPLACE "-L" "" _dir ${_arg})
-        list(APPEND _pcap_static_library_dirs ${_dir})
-      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.
-        #
-        find_library(_libfullpath ${_lib} HINTS ${__pcap_static_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)
-      endif()
-    endforeach()
+    find_library(PCAP_STATIC_LIBRARY pcap)
     set(CMAKE_FIND_LIBRARY_SUFFIXES "${SAVED_CMAKE_FIND_LIBRARY_SUFFIXES}")
-  else(PCAP_CONFIG)
+
     #
-    # We don't have pcap-config.
-    # Try to find the header by just looking for it in whatever
-    # directories find_path() uses by default.
+    # This will fail if REQUIRED is set and PCAP_INCLUDE_DIR or
+    # PCAP_LIBRARY aren't set.
     #
-    find_path(PCAP_INCLUDE_DIRS pcap.h)
+    include(FindPackageHandleStandardArgs)
+    find_package_handle_standard_args(PCAP
+      DEFAULT_MSG
+      PCAP_INCLUDE_DIR
+      PCAP_LIBRARY
+    )
 
-    # Try to find the library
-    if(WIN32)
-      # 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()
-    endif()
+    mark_as_advanced(
+      PCAP_INCLUDE_DIR
+      PCAP_LIBRARY
+      PCAP_STATIC_LIBRARY
+    )
 
-    find_library(PCAP_LIBRARIES pcap)
-    if(WIN32)
-      if(NOT PCAP_LIBRARIES)
-        #
-        # OK, look for it under the name wpcap.
-        #
-        find_library(PCAP_LIBRARIES wpcap)
-      endif(NOT PCAP_LIBRARIES)
-    endif(WIN32)
-
-    if(NOT WIN32)
-      # 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_LIBRARIES pcap)
-      set(CMAKE_FIND_LIBRARY_SUFFIXES "${SAVED_CMAKE_FIND_LIBRARY_SUFFIXES}")
-    endif(NOT WIN32)
-  endif(PCAP_CONFIG)
-endif(PCAP_FOUND)
-
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(PCAP
-  DEFAULT_MSG
-  PCAP_INCLUDE_DIRS
-  PCAP_LIBRARIES
-)
-
-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)