]> The Tcpdump Group git mirrors - tcpdump/blobdiff - CMakeLists.txt
Detect OS IPv6 support using AF_INET6 only.
[tcpdump] / CMakeLists.txt
index edd5fd19a79e85cc1866fa12ef38a76dadfc80d1..fa865703b6c49bb84fca4d9d67703814f40d482f 100644 (file)
@@ -2,10 +2,11 @@ if(WIN32)
     #
     # We need 3.12 or later, so that we can set policy CMP0074; see
     # below.
+    #
     cmake_minimum_required(VERSION 3.12)
 else(WIN32)
     #
-    # For now, require only 2.8.6, just in case somebody is
+    # For now, require only 2.8.12, just in case somebody is
     # configuring with CMake on a "long-term support" version
     # of some OS and that version supplies an older version of
     # CMake.
@@ -16,7 +17,7 @@ else(WIN32)
     # environment variable when running pkg-config, to make sure
     # it finds any .pc file from there.
     #
-    cmake_minimum_required(VERSION 2.8.6)
+    cmake_minimum_required(VERSION 2.8.12)
 endif(WIN32)
 
 #
@@ -28,12 +29,70 @@ if(POLICY CMP0074)
     cmake_policy(SET CMP0074 NEW)
 endif()
 
-set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules)
+#
+# OK, this is a pain.
+#
+# When building on NetBSD, with a libpcap installed from pkgsrc,
+# a -Wl,-rpath,/usr/pkg/lib option is added to the options when
+# linking tcpdump.  This puts /usr/pkg/lib into the run-time path.
+#
+# However, by default, CMake adds a rule to the install CMake script
+# a CMake command (using an undocumented subcommand of file()) that
+# strips /usr/pkg/lib *out* of the run-time path; the message in the
+# output for the "install" target is
+#
+#    -- Set runtime path of "{target-directory}/tcpdump" to ""
+#
+# I am not certain what the rationale is for doing this, but a
+# *consequence* of this is that, when you run the installed tcpdump,
+# it fails to find libpcap.so:
+#
+#    $ {target-directory}/tcpdump -h
+#    {target-directory}/tcpdump: Shared object "libpcap.so.0" not found
+#
+# It also appears to be the case that, on Ubuntu 22.04, FreeBSD 12,
+# DragonFly BSD 5.8, OpenBSD 6.6, and Solaris 11.4,
+#
+# On Ubuntu and Solaris, even if you have a libpcap in /usr/local, you
+# have to provide not only -I/usr/local/include and -L/usr/local/lib,
+# you also must provide -Wl,-rpath,/usr/local/lib in order to have
+# the run-time linker look in /usr/local/lib for libpcap.  If it's not
+# specified, then, if the shared library major version number of the
+# libpcap in /usr/lib is the same as the shared major version number
+# of the libpcap in /usr/local/lib, the run-time linker will find the
+# libpcap in /usr/lib; if the versions are different, the run-time
+# linker will fail to find the libpcap in /usr/lib, so the program will
+# fail to run.
+#
+# We suppress this by setting CMAKE_INSTALL_RPATH_USE_LINK_PATH to TRUE;
+# as the documentation for that variable says:
+#
+#    Add paths to linker search and installed rpath.
+#
+#    CMAKE_INSTALL_RPATH_USE_LINK_PATH is a boolean that if set to True
+#    will append to the runtime search path (rpath) of installed
+#    binaries any directories outside the project that are in the linker
+#    search path or contain linked library files. The directories are
+#    appended after the value of the INSTALL_RPATH target property.
+#
+# If, for whatever reason, directories in which we search for external
+# libraries, other than the standard system library directories, are
+# added to the executable's rpath in the build process, we most
+# defintely want them in the installed image's rpath if they are
+# necessary in order to find the libraries at run time.
+#
+set(CMAKE_INSTALL_RPATH_USE_LINK_PATH TRUE)
 
-project(tcpdump)
+set(CMAKE_MODULE_PATH ${CMAKE_SOURCE_DIR}/cmake/Modules)
 
 #
-# OK, this is a royal pain.
+# We explicitly indicate what languages are used in tcpdump to avoid
+# checking for a C++ compiler.
+#
+# One reason to avoid that check is that there's no need to waste
+# configuration time performing it.
+#
+# Another reason is that:
 #
 # CMake will try to determine the sizes of some data types, including
 # void *, early in the process of configuration; apparently, it's done
@@ -52,15 +111,14 @@ project(tcpdump)
 # but *not* in CXXFLAGS, the size for C++ will win, and hilarity
 # will ensue.
 #
-# Make sure CMAKE_C_SIZEOF_DATA_PTR and CMAKE_CXX_SIZEOF_DATA_PTR
-# have the same value, and warn if they don't.
-#
-# Yes, we have to do this even though there is currently *NO* C++
-# code in tcpdump....
+# Or if, at least on Solaris, you have a newer version of GCC
+# installed, but *not* a newer version of G++, and you have Oracle
+# Studio installed, it will find GCC, which will default to building
+# 64-bit, and Oracle Studio's C++ compiler, which will default to
+# building 32-bit, the size for C++ will win, and, again, hilarity
+# will ensue.
 #
-if(NOT "${CMAKE_C_SIZEOF_DATA_PTR}" EQUAL "${CMAKE_CXX_SIZEOF_DATA_PTR}")
-    message(FATAL_ERROR "Architecture flags must be set in both CFLAGS and CXXFLAGS")
-endif()
+project(tcpdump C)
 
 #
 # For checking if a compiler flag works and adding it if it does.
@@ -275,22 +333,12 @@ check_include_file(net/if.h HAVE_NET_IF_H)
 if(HAVE_RPC_RPC_H)
     check_include_files("rpc/rpc.h;rpc/rpcent.h" HAVE_RPC_RPCENT_H)
 endif(HAVE_RPC_RPC_H)
-if(NOT WIN32)
-    check_include_files("sys/types.h;sys/socket.h;net/if.h;net/pfvar.h" HAVE_NET_PFVAR_H)
-    if(HAVE_NET_PFVAR_H)
-        check_include_files("sys/types.h;sys/socket.h;net/if.h;net/pfvar.h;net/if_pflog.h" HAVE_NET_IF_PFLOG_H)
-        if(HAVE_NET_IF_PFLOG_H)
-            set(LOCALSRC print-pflog.c ${LOCALSRC})
-        endif(HAVE_NET_IF_PFLOG_H)
-    endif(HAVE_NET_PFVAR_H)
-endif(NOT WIN32)
 
 #
 # Functions.
 #
 check_function_exists(strlcat HAVE_STRLCAT)
 check_function_exists(strlcpy HAVE_STRLCPY)
-check_function_exists(strdup HAVE_STRDUP)
 check_function_exists(strsep HAVE_STRSEP)
 
 #
@@ -323,7 +371,12 @@ else(WIN32)
             if(LIBNSL_HAS_GETHOSTBYADDR)
                 set(TCPDUMP_LINK_LIBRARIES ${TCPDUMP_LINK_LIBRARIES} nsl)
             else(LIBNSL_HAS_GETHOSTBYADDR)
-                message(FATAL_ERROR "gethostbyaddr is required, but wasn't found")
+                check_library_exists(network gethostbyaddr "" LIBNETWORK_HAS_GETHOSTBYADDR)
+                if(LIBNETWORK_HAS_GETHOSTBYADDR)
+                    set(TCPDUMP_LINK_LIBRARIES ${TCPDUMP_LINK_LIBRARIES} network)
+                else(LIBNETWORK_HAS_GETHOSTBYADDR)
+                    message(FATAL_ERROR "gethostbyaddr is required, but wasn't found")
+                endif(LIBNETWORK_HAS_GETHOSTBYADDR)
             endif(LIBNSL_HAS_GETHOSTBYADDR)
         endif(LIBSOCKET_HAS_GETHOSTBYADDR)
     endif(NOT STDLIBS_HAVE_GETHOSTBYADDR)
@@ -351,22 +404,69 @@ endif(STDLIBS_HAVE_GETSERVENT)
 cmake_pop_check_state()
 
 #
-# Make sure we have vsnprintf() and snprintf(); we require them.
-# We use check_symbol_exists(), as they aren't necessarily external
-# functions - in Visual Studio, for example, they're inline functions
-# calling a common external function.
+# Make sure we have snprintf(); we require it.
+# We use check_symbol_exists(), as it isn't necessarily an external
+# function - in Visual Studio, for example, it is an inline function
+# calling an external function.
 #
-check_symbol_exists(vsnprintf "stdio.h" HAVE_VSNPRINTF)
-if(NOT HAVE_VSNPRINTF)
-    message(FATAL_ERROR "vsnprintf() is required but wasn't found")
-endif(NOT HAVE_VSNPRINTF)
 check_symbol_exists(snprintf "stdio.h" HAVE_SNPRINTF)
 if(NOT HAVE_SNPRINTF)
     message(FATAL_ERROR "snprintf() is required but wasn't found")
 endif()
 
+#
+# Require a proof of suitable snprintf(3), same as in Autoconf.
+#
+include(CheckCSourceRuns)
+check_c_source_runs("
+#include <stdio.h>
+#include <string.h>
+#include <inttypes.h>
+#include <sys/types.h>
+
+int main()
+{
+  char buf[100];
+  uint64_t t = (uint64_t)1 << 32;
+
+  snprintf(buf, sizeof(buf), \"%zu\", sizeof(buf));
+  if (strncmp(buf, \"100\", sizeof(buf)))
+    return 1;
+
+  snprintf(buf, sizeof(buf), \"%zd\", -sizeof(buf));
+  if (strncmp(buf, \"-100\", sizeof(buf)))
+    return 2;
+
+  snprintf(buf, sizeof(buf), \"%\" PRId64, -t);
+  if (strncmp(buf, \"-4294967296\", sizeof(buf)))
+    return 3;
+
+  snprintf(buf, sizeof(buf), \"0o%\" PRIo64, t);
+  if (strncmp(buf, \"0o40000000000\", sizeof(buf)))
+    return 4;
+
+  snprintf(buf, sizeof(buf), \"0x%\" PRIx64, t);
+  if (strncmp(buf, \"0x100000000\", sizeof(buf)))
+    return 5;
+
+  snprintf(buf, sizeof(buf), \"%\" PRIu64, t);
+  if (strncmp(buf, \"4294967296\", sizeof(buf)))
+    return 6;
+
+  return 0;
+}
+
+"
+    SUITABLE_SNPRINTF
+)
+if(NOT SUITABLE_SNPRINTF)
+    message(FATAL_ERROR
+"The snprintf(3) implementation in this libc is not suitable,
+tcpdump would not work correctly even if it managed to compile."
+    )
+endif()
+
 check_function_exists(getopt_long HAVE_GETOPT_LONG)
-check_function_exists(strftime HAVE_STRFTIME)
 check_function_exists(setlinebuf HAVE_SETLINEBUF)
 #
 # For Windows,  don't need to waste time checking for fork() or vfork().
@@ -533,22 +633,10 @@ cmake_pop_check_state()
 #
 
 #
-# Check for IPv6 support.
-# We just check for AF_INET6 and struct in6_addr.
+# FIXME: This check does not influence the build logic, but without it CMake
+# 3.18.4 fails trying to make the next check_type_size() check later on.
 #
-cmake_push_check_state()
-if(WIN32)
-    set(CMAKE_EXTRA_INCLUDE_FILES sys/types.h ws2tcpip.h)
-    check_symbol_exists(AF_INET6 "sys/types.h;ws2tcpip.h" HAVE_AF_INET6)
-else(WIN32)
-    set(CMAKE_EXTRA_INCLUDE_FILES sys/types.h sys/socket.h netinet/in.h)
-    check_symbol_exists(AF_INET6 "sys/types.h;sys/socket.h;netinet/in.h" HAVE_AF_INET6)
-endif(WIN32)
 check_type_size("struct in6_addr" HAVE_STRUCT_IN6_ADDR)
-cmake_pop_check_state()
-if(HAVE_AF_INET6 AND HAVE_STRUCT_IN6_ADDR)
-    set(HAVE_OS_IPV6_SUPPORT TRUE)
-endif(HAVE_AF_INET6 AND HAVE_STRUCT_IN6_ADDR)
 
 ######################################
 # External dependencies
@@ -1093,6 +1181,7 @@ set(NETDISSECT_SOURCE_LIST_C
     print-ospf.c
     print-ospf6.c
     print-otv.c
+    print-pflog.c
     print-pgm.c
     print-pim.c
     print-pktap.c
@@ -1101,13 +1190,14 @@ set(NETDISSECT_SOURCE_LIST_C
     print-pppoe.c
     print-pptp.c
     print-ptp.c
+    print-quic.c
     print-radius.c
     print-raw.c
+    print-realtek.c
     print-resp.c
     print-rip.c
     print-ripng.c
     print-rpki-rtr.c
-    print-rrcp.c
     print-rsvp.c
     print-rt6.c
     print-rtsp.c
@@ -1145,6 +1235,7 @@ set(NETDISSECT_SOURCE_LIST_C
     print-vxlan-gpe.c
     print-vxlan.c
     print-wb.c
+    print-whois.c
     print-zep.c
     print-zephyr.c
     print-zeromq.c
@@ -1157,7 +1248,7 @@ set(NETDISSECT_SOURCE_LIST_C
 #
 # Replace missing functions
 #
-foreach(FUNC strlcat strlcpy strdup strsep getservent getopt_long)
+foreach(FUNC strlcat strlcpy strsep getservent getopt_long)
     string(TOUPPER ${FUNC} FUNC_UPPERCASE)
     set(HAVE_FUNC_UPPERCASE HAVE_${FUNC_UPPERCASE})
     if(NOT ${HAVE_FUNC_UPPERCASE})
@@ -1195,6 +1286,55 @@ file(GLOB PROJECT_SOURCE_LIST_H
     *.h
 )
 
+#
+# Assume, by default, no support for shared libraries and V7/BSD
+# convention for man pages (devices in section 4, file formats in
+# section 5, miscellaneous info in section 7, administrative commands
+# and daemons in section 8).  Individual cases can override this.
+# Individual cases can override this.
+#
+set(MAN_FILE_FORMATS 5)
+set(MAN_MISC_INFO 7)
+if(CMAKE_SYSTEM_NAME STREQUAL "AIX")
+    # Workaround to enable certain features
+    set(_SUN TRUE)
+elseif(CMAKE_SYSTEM_NAME STREQUAL "HP-UX")
+    #
+    # Use System V conventions for man pages.
+    #
+    set(MAN_FILE_FORMATS 4)
+    set(MAN_MISC_INFO 5)
+elseif(CMAKE_SYSTEM_NAME STREQUAL "IRIX" OR CMAKE_SYSTEM_NAME STREQUAL "IRIX64")
+    #
+    # Use IRIX conventions for man pages; they're the same as the
+    # System V conventions, except that they use section 8 for
+    # administrative commands and daemons.
+    #
+    set(MAN_FILE_FORMATS 4)
+    set(MAN_MISC_INFO 5)
+elseif(CMAKE_SYSTEM_NAME STREQUAL "OSF1")
+    #
+    # DEC OSF/1, a/k/a Digital UNIX, a/k/a Tru64 UNIX.
+    # Use Tru64 UNIX conventions for man pages; they're the same as the
+    # System V conventions except that they use section 8 for
+    # administrative commands and daemons.
+    #
+    set(MAN_FILE_FORMATS 4)
+    set(MAN_MISC_INFO 5)
+elseif(CMAKE_SYSTEM_NAME STREQUAL "SunOS" AND CMAKE_SYSTEM_VERSION MATCHES "5[.][0-9.]*")
+    #
+    # SunOS 5.x.
+    #
+    if(CMAKE_SYSTEM_VERSION STREQUAL "5.12")
+    else()
+        #
+        # Use System V conventions for man pages.
+        #
+        set(MAN_FILE_FORMATS 4)
+        set(MAN_MISC_INFO 5)
+    endif()
+endif()
+
 source_group("Source Files" FILES ${PROJECT_SOURCE_LIST_C})
 source_group("Header Files" FILES ${PROJECT_SOURCE_LIST_H})