# We need 3.12 or later, so that we can set policy CMP0074; see below. cmake_minimum_required(VERSION 3.12) set(PCAPPP_VERSION "25.05+") # MAIN_PROJECT CHECK set(PCAPPP_MAIN_PROJECT OFF) if(CMAKE_CURRENT_SOURCE_DIR STREQUAL CMAKE_SOURCE_DIR) set(PCAPPP_MAIN_PROJECT ON) endif() project( PcapPlusPlus DESCRIPTION "PcapPlusPlus is a multiplatform C++ library for capturing, parsing and crafting of network packets." LANGUAGES CXX HOMEPAGE_URL "https://pcapplusplus.github.io/" ) # Include our custom CMake modules list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake/modules/") include(CMakeDependentOption) include(CMakePackageConfigHelpers) include(PcapPlusPlusUtils) include(GNUInstallDirs) include(TargetArch) # Setup CMake pcapp_detect_compiler(PCAPPP_TARGET) # Get architecture target_architecture(PCAPP_TARGET_ARCHITECTURE) # Use Ccache if available find_program(CCACHE_PROGRAM ccache) if(CCACHE_PROGRAM) message(STATUS "Ccache found!") set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE "${CCACHE_PROGRAM}") set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK "${CCACHE_PROGRAM}") else() message(STATUS "Ccache not found!") endif() # LINUX is set Only since 3.25 see: https://cmake.org/cmake/help/latest/variable/LINUX.html if(UNIX AND NOT APPLE AND NOT CYGWIN AND NOT ANDROID) set(LINUX True) endif() # Declare install folders location set(PCAPPP_INSTALL_BINDIR ${CMAKE_INSTALL_BINDIR}) set(PCAPPP_INSTALL_CMAKEDIR ${CMAKE_INSTALL_LIBDIR}/cmake/pcapplusplus) set(PCAPPP_INSTALL_INCLUDEDIR ${CMAKE_INSTALL_INCLUDEDIR}/pcapplusplus) set(PCAPPP_INSTALL_LIBDIR ${CMAKE_INSTALL_LIBDIR}) # Build options enable sanitizers set( PCAPPP_ALLOWED_SANITIZERS "" "AddressSanitizer" "MemorySanitizer" "ThreadSanitizer" "UndefinedBehaviorSanitizer" ) set(PCAPPP_USE_SANITIZER "" CACHE STRING "Compile with a sanitizer") set_property(CACHE PCAPPP_USE_SANITIZER PROPERTY STRINGS ${PCAPPP_ALLOWED_SANITIZERS}) if(NOT PCAPPP_USE_SANITIZER IN_LIST PCAPPP_ALLOWED_SANITIZERS) message(FATAL_ERROR "PCAPPP_USE_SANITIZER must be one of ${PCAPPP_ALLOWED_SANITIZERS}") endif() if(PCAPPP_USE_SANITIZER) add_compile_options("-fno-omit-frame-pointer") add_compile_options("-O1") if(PCAPPP_USE_SANITIZER STREQUAL "AddressSanitizer") add_compile_options("-fsanitize=address") add_link_options("-fsanitize=address") elseif(PCAPPP_USE_SANITIZER STREQUAL "MemorySanitizer") add_compile_options("-fsanitize=memory") add_link_options("-fsanitize=memory") elseif(PCAPPP_USE_SANITIZER STREQUAL "ThreadSanitizer") add_compile_options("-fsanitize=thread") add_link_options("-fsanitize=thread") elseif(PCAPPP_USE_SANITIZER STREQUAL "UndefinedBehaviorSanitizer") add_compile_options("-fsanitize=undefined") add_link_options("-fsanitize=undefined") endif() endif() # Build options (Compile time log level) set( PCAPP_ALLOWED_LOG_LEVELS "" "0" "1" "2" "3" "4" "Off" "Error" "Warn" "Info" "Debug" ) set( PCAPPP_LOG_LEVEL "" CACHE STRING "Compile time log level (0 - Off, 1 - Error, 2 - Warn, 3 - Info, 4 - Debug) Default(empty): Debug" ) set_property(CACHE PCAPPP_LOG_LEVEL PROPERTY STRINGS ${PCAPP_ALLOWED_LOG_LEVELS}) if(NOT PCAPPP_LOG_LEVEL IN_LIST PCAPP_ALLOWED_LOG_LEVELS) message(FATAL_ERROR "PCAPPP_LOG_LEVEL must be one of ${PCAPP_ALLOWED_LOG_LEVELS}") endif() if(PCAPPP_LOG_LEVEL) if(PCAPPP_LOG_LEVEL STREQUAL "0" OR PCAPPP_LOG_LEVEL STREQUAL "Off") set(PCAPPP_LOG_LEVEL_VALUE "PCPP_LOG_LEVEL_OFF") elseif(PCAPPP_LOG_LEVEL STREQUAL "1" OR PCAPPP_LOG_LEVEL STREQUAL "Error") set(PCAPPP_LOG_LEVEL_VALUE "PCPP_LOG_LEVEL_ERROR") elseif(PCAPPP_LOG_LEVEL STREQUAL "2" OR PCAPPP_LOG_LEVEL STREQUAL "Warn") set(PCAPPP_LOG_LEVEL_VALUE "PCPP_LOG_LEVEL_WARN") elseif(PCAPPP_LOG_LEVEL STREQUAL "3" OR PCAPPP_LOG_LEVEL STREQUAL "Info") set(PCAPPP_LOG_LEVEL_VALUE "PCPP_LOG_LEVEL_INFO") elseif(PCAPPP_LOG_LEVEL STREQUAL "4" OR PCAPPP_LOG_LEVEL STREQUAL "Debug") set(PCAPPP_LOG_LEVEL_VALUE "PCPP_LOG_LEVEL_DEBUG") endif() message( STATUS "Compile time logging verbocity has been set to level \"${PCAPPP_LOG_LEVEL_VALUE}\". All messages below this level will be pruned." ) add_compile_definitions("PCPP_ACTIVE_LOG_LEVEL=${PCAPPP_LOG_LEVEL_VALUE}") endif() # Build options (Turn on Examples and Tests if it's the main project) option(PCAPPP_BUILD_PCAPPP "Build Pcap++ project. Turning this off will build only Common++ and Packet++" ON) cmake_dependent_option( PCAPPP_BUILD_EXAMPLES "Build Examples" ${PCAPPP_MAIN_PROJECT} "PCAPPP_BUILD_PCAPPP" OFF ) cmake_dependent_option( PCAPPP_BUILD_TUTORIALS "Build Tutorials" OFF "PCAPPP_BUILD_EXAMPLES" OFF ) option(PCAPPP_BUILD_TESTS "Build Tests" ${PCAPPP_MAIN_PROJECT}) option(PCAPPP_BUILD_COVERAGE "Generate Coverage Report" OFF) option(PCAPPP_BUILD_FUZZERS "Build Fuzzers binaries" OFF) option(PCAPPP_BUILD_REPRODUCIBLE "Build a reproducible version" OFF) option(BUILD_SHARED_LIBS "Build using shared libraries" OFF) option(PCAPPP_USE_DPDK "Setup PcapPlusPlus with DPDK. In this case you must also set DPDK_ROOT") cmake_dependent_option( PCAPPP_USE_DPDK_KNI "Add KNI Support to Pcap++" OFF "PCAPPP_USE_DPDK" OFF ) option(PCAPPP_USE_PF_RING "Setup PcapPlusPlus with PF_RING. In this case you must also set PF_RING_ROOT") option(PCAPPP_USE_XDP "Setup PcapPlusPlus with XDP") option(PCAPPP_INSTALL "Install Pcap++" ${PCAPPP_MAIN_PROJECT}) option(PCAPPP_PACKAGE "Package Pcap++ could require a recent version of CMake" OFF) # Set C++14 if not defined if(NOT DEFINED CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD 14) set(CMAKE_CXX_STANDARD_REQUIRED ON) endif() # popen()/pclose() are not C++ standards set(CMAKE_CXX_EXTENSIONS ON) # Set Position Independent Code for static libraries set(CMAKE_POSITION_INDEPENDENT_CODE ON) # Export compile commands for external tools set(CMAKE_EXPORT_COMPILE_COMMANDS ON) # Git Commit and Branch find_package(Git) if(Git_FOUND) execute_process( COMMAND ${GIT_EXECUTABLE} log -1 --format=%h WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE PCAPPP_GIT_COMMIT ) string(STRIP "${PCAPPP_GIT_COMMIT}" PCAPPP_GIT_COMMIT) execute_process( COMMAND ${GIT_EXECUTABLE} rev-parse --abbrev-ref HEAD WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR} OUTPUT_VARIABLE PCAPPP_GIT_BRANCH ) string(STRIP "${PCAPPP_GIT_BRANCH}" PCAPPP_GIT_BRANCH) message(STATUS "Building from commit:${PCAPPP_GIT_COMMIT} on branch:${PCAPPP_GIT_BRANCH}") add_compile_definitions(GIT_COMMIT="${PCAPPP_GIT_COMMIT}") add_compile_definitions(GIT_BRANCH="${PCAPPP_GIT_BRANCH}") endif() if(MSVC) # Other hacks for VStudio # fopen(), sscanf() and strncpy() are not safe add_definitions(-D_CRT_SECURE_NO_WARNINGS) endif() # Required dependencies only for PCap++ project. if(PCAPPP_BUILD_PCAPPP) # Usually on Windows PCAP_ROOT and Packet_ROOT are at the same location if(WIN32 AND PCAP_ROOT AND NOT Packet_ROOT) set(Packet_ROOT ${PCAP_ROOT}) endif() find_package(PCAP) if(NOT PCAP_FOUND) if(WIN32) message(FATAL_ERROR "Please specify Npcap/WinPcap SDK directory with -DPCAP_ROOT=") else() message(FATAL_ERROR "PCAP library not found!") endif() endif() # Look for Packet if(WIN32) find_package(Packet) if(NOT Packet_FOUND) message(FATAL_ERROR "Please specify Packet library -DPacket_ROOT=") endif() endif() if(HAVE_PCAP_IMMEDIATE_MODE) add_definitions(-DHAS_PCAP_IMMEDIATE_MODE) endif() if(HAVE_PCAP_TIMESTAMP_TYPES) add_definitions(-DHAS_TIMESTAMP_TYPES_ENABLED) endif() if(HAVE_PCAP_TIMESTAMP_PRECISION) add_definitions(-DHAS_TIMESTAMP_PRECISION_ENABLED) endif() set(THREADS_PREFER_PTHREAD_FLAG ON) find_package(Threads REQUIRED) if(PCAPPP_USE_PF_RING AND NOT CMAKE_USE_PTHREADS_INIT) message(FATAL_ERROR "Pthreads not found!") endif() if(PCAPPP_USE_DPDK) find_package(DPDK) if(NOT DPDK_FOUND) message(FATAL_ERROR "Specify DPDK Library with -DDPDK_ROOT=") endif() add_definitions(-DUSE_DPDK) # Check in case user force KNI but it's not available if(PCAPPP_USE_DPDK_KNI) if(NOT HAVE_DPDK_RTE_KNI) message(FATAL_ERROR "DPDK library doesn't have KNI support!") endif() add_definitions(-DUSE_DPDK_KNI) endif() # Disable deprecated warnings when DPDK enabled since warnings are treated as errors add_definitions("-Wno-deprecated-declarations") configure_file("${CMAKE_CURRENT_SOURCE_DIR}/cmake/setup_dpdk.py" "${CMAKE_CURRENT_BINARY_DIR}" COPYONLY) endif() if(PCAPPP_USE_PF_RING) find_package(PF_RING) if(NOT PF_RING_FOUND) message(FATAL_ERROR "Specify PF_RING Library with -DPF_RING_ROOT=") endif() add_definitions(-DUSE_PF_RING) endif() if(PCAPPP_USE_XDP) find_package(BPF) if(NOT BPF_FOUND) message(FATAL_ERROR "libbpf not found!") endif() add_definitions(-DUSE_XDP) endif() endif() if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the type of build." FORCE) set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release") endif() if(PCAPPP_TARGET_COMPILER_CLANG OR PCAPPP_TARGET_COMPILER_GCC OR PCAPPP_TARGET_COMPILER_INTEL) add_compile_options(-Wall) endif() if(PCAPPP_BUILD_REPRODUCIBLE) add_definitions(-DPCAPPP_BUILD_REPRODUCIBLE) if(APPLE) if(NOT $ENV{ZERO_AR_DATE}) message(FATAL_ERROR "You need to set `export ZERO_AR_DATE=1`") endif() elseif(MSVC) message(FATAL_ERROR "Unsupported with MSVC compiler") # Try to build a reproducible static library with MSVC doesn't work but this option should make it work for shared # libraries or executables. add_compile_options(/Brepro) add_compile_options(/experimental:deterministic) # add_link_options(/Brepro) add_link_options(/experimental:deterministic) add_link_options(/INCREMENTAL:NO) else() # We should not use __DATE__ nor __TIME__ in case of reproducible build add_compile_options(-Wdate-time) endif() endif() if(PCAPPP_BUILD_FUZZERS) add_compile_options(-w) endif() # Static linking GCC/Threads for minGW (Windows + GNU) if(MINGW) add_link_options(-static-libgcc -static-libstdc++) add_link_options(-static) add_compile_options(-Wno-unused-function) endif() if(PCAPPP_TARGET_COMPILER_MSVC) # Disable VS warnings: Unknown pragma (4068), Zero-sized array in struct/union (4200), Possible loss of data (4244), # Possible loss of data (4267), Character may not be represented (4819) add_definitions("/wd4068 /wd4200 /wd4244 /wd4267 /wd4819") endif() if(PCAPPP_BUILD_COVERAGE) add_compile_options(--coverage) add_link_options(--coverage) set(_PCAPPP_FIND_COVERAGE "find_dependency(Coverage)\n") endif() add_subdirectory(3rdParty) add_subdirectory(Common++) add_subdirectory(Packet++) if(PCAPPP_BUILD_PCAPPP) add_subdirectory(Pcap++) endif() if(PCAPPP_BUILD_EXAMPLES) if(PCAPPP_BUILD_PCAPPP) set(PCAPPP_BINARY_EXAMPLES_DIR ${CMAKE_BINARY_DIR}/examples_bin) add_subdirectory(Examples) else() # Examples searches for Pcap++, so it needs to be built. message(FATAL_ERROR "Examples require Pcap++ project to be built") endif() endif() if(PCAPPP_BUILD_TESTS OR PCAPPP_BUILD_FUZZERS OR PCAPPP_BUILD_EXAMPLES) include(CTest) add_subdirectory(Tests) endif() if(PCAPPP_INSTALL) # Generate PKG-Config for non WIN32 system if(NOT WIN32) if(APPLE) # Add System and CoreFoundation libs on MacOS set(PCAPPP_PKGCONFIG_EXTRA_LIBS "-framework SystemConfiguration -framework CoreFoundation") endif() configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/cmake/PcapPlusPlus.pc.in" "${CMAKE_CURRENT_BINARY_DIR}/PcapPlusPlus.pc" @ONLY ) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/PcapPlusPlus.pc" DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") endif() # CMake helpers to compile Pcap++ with CMake pcapp_install_cmake_module(PCAP) if(WIN32) pcapp_install_cmake_module(Packet) endif() if(PCAPPP_USE_PF_RING) pcapp_install_cmake_module(PF_RING) endif() if(PCAPPP_USE_DPDK) pcapp_install_cmake_module(DPDK) pcapp_install_cmake_module(NUMA) endif() if(LIGHT_PCAPNG_ZSTD) pcapp_install_cmake_module(ZSTD) endif() install(EXPORT PcapPlusPlusTargets DESTINATION ${PCAPPP_INSTALL_CMAKEDIR} NAMESPACE PcapPlusPlus::) configure_package_config_file( "${CMAKE_CURRENT_SOURCE_DIR}/cmake/PcapPlusPlusConfig.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/PcapPlusPlusConfig.cmake" INSTALL_DESTINATION "${PCAPPP_INSTALL_CMAKEDIR}" ) write_basic_package_version_file( "${CMAKE_CURRENT_BINARY_DIR}/PcapPlusPlusConfigVersion.cmake" VERSION ${PCAPPP_VERSION} COMPATIBILITY AnyNewerVersion ) # CMake helpers to compile Pcap++ with CMake install( FILES "${CMAKE_CURRENT_BINARY_DIR}/PcapPlusPlusConfig.cmake" "${CMAKE_CURRENT_BINARY_DIR}/PcapPlusPlusConfigVersion.cmake" COMPONENT devel DESTINATION "${PCAPPP_INSTALL_CMAKEDIR}" ) endif() if(PCAPPP_PACKAGE) if(NOT PCAPPP_INSTALL) message(SEND_ERROR "Packaging depends on PCAPP_INSTALL") endif() set(CPACK_PACKAGE_NAME "pcapplusplus") set(CPACK_PACKAGE_VERSION "${PCAPPP_VERSION}") set(CPACK_PACKAGE_MAINTAINER "seladb") set(CPACK_DEBIAN_PACKAGE_MAINTAINER "${CPACK_PACKAGE_MAINTAINER}") set( CPACK_PACKAGE_DESCRIPTION_SUMMARY "PcapPlusPlus is a multiplatform C++ library for capturing, parsing and crafting of network packets. It is designed to be efficient, powerful and easy to use." ) # Default output a .tar.gz set(CPACK_GENERATOR "TGZ") # Remove the tweak for Compiler Version string(REPLACE "." ";" VERSION_LIST ${CMAKE_CXX_COMPILER_VERSION}) list(LENGTH VERSION_LIST CMAKE_CXX_COMPILER_VERSION_LENGTH) if(${CMAKE_CXX_COMPILER_VERSION_LENGTH} GREATER 3) list(POP_BACK VERSION_LIST) endif() list(JOIN VERSION_LIST "." PCAPP_CXX_COMPILER_VERSION) set(_PCAPPP_PACKAGE_README_PATH "${CMAKE_SOURCE_DIR}/cmake/package/READMEs") set(_PCAPPP_PACKAGE_README_OUTFILE "${CMAKE_BINARY_DIR}/README.release.md") if(ANDROID) set(CPACK_SYSTEM_NAME "android-${ANDROID_ABI}-${ANDROID_PLATFORM}") set(_PCAPPP_PACKAGE_README_CUSTOM_PATH "${_PCAPPP_PACKAGE_README_PATH}/README.release.android") elseif(APPLE) # set(CPACK_GENERATOR ${CPACK_GENERATOR};productbuild) set(CPACK_SYSTEM_NAME "macos-${CMAKE_OSX_ARCHITECTURES}-${PCAPPP_TARGET_COMPILER}-${PCAPP_CXX_COMPILER_VERSION}") set(_PCAPPP_PACKAGE_README_CUSTOM_PATH "${_PCAPPP_PACKAGE_README_PATH}/README.release.macos") elseif(LINUX) # Easier for Packing but requires CMake 3.22 cmake_minimum_required(VERSION 3.22) cmake_host_system_information(RESULT DISTRO_ID QUERY DISTRIB_ID) cmake_host_system_information(RESULT DISTRO_VERSION_ID QUERY DISTRIB_VERSION_ID) set(_PCAPPP_PACKAGE_README_CUSTOM_PATH "${_PCAPPP_PACKAGE_README_PATH}/README.release.linux") if("${DISTRO_ID}" STREQUAL "ubuntu") # set(CPACK_GENERATOR ${CPACK_GENERATOR};DEB) elseif("${DISTRO_ID}" STREQUAL "centos" OR "${DISTRO_ID}" STREQUAL "rhel") # set(CPACK_GENERATOR ${CPACK_GENERATOR};RPM) elseif("${DISTRO_ID}" STREQUAL "freebsd") set(_PCAPPP_PACKAGE_README_CUSTOM_PATH "${_PCAPPP_PACKAGE_README_PATH}/README.release.freebsd") endif() set( CPACK_SYSTEM_NAME "${DISTRO_ID}-${DISTRO_VERSION_ID}-${PCAPPP_TARGET_COMPILER}-${PCAPP_CXX_COMPILER_VERSION}-${CMAKE_SYSTEM_PROCESSOR}" ) elseif(MINGW) # Check MinGW before WIN32 as MinGW defines both set(CPACK_GENERATOR "ZIP") set( CPACK_SYSTEM_NAME "windows-mingw64-${PCAPP_TARGET_ARCHITECTURE}-${PCAPPP_TARGET_COMPILER}-${PCAPP_CXX_COMPILER_VERSION}" ) set(_PCAPPP_PACKAGE_README_CUSTOM_PATH "${_PCAPPP_PACKAGE_README_PATH}/README.release.win.mingw") elseif(WIN32) set(CPACK_GENERATOR "ZIP") string(TOLOWER ${CMAKE_BUILD_TYPE} BUILD_TYPE_LOWER) string(TOLOWER ${CMAKE_VS_PLATFORM_NAME} PLATFORM_LOWER) set(CPACK_SYSTEM_NAME "windows-vs${MSVC_YEAR}-${PLATFORM_LOWER}-${BUILD_TYPE_LOWER}") set(_PCAPPP_PACKAGE_README_CUSTOM_PATH "${_PCAPPP_PACKAGE_README_PATH}/README.release.win.vs") endif() # Generate output README file(READ "${_PCAPPP_PACKAGE_README_PATH}/README.release.header" _CONTENT) file(APPEND ${_PCAPPP_PACKAGE_README_OUTFILE} "${_CONTENT}") if(_PCAPPP_PACKAGE_README_CUSTOM_PATH) file(READ ${_PCAPPP_PACKAGE_README_CUSTOM_PATH} _CONTENT) file(APPEND ${_PCAPPP_PACKAGE_README_OUTFILE} "${_CONTENT}\n") endif() file(READ "${_PCAPPP_PACKAGE_README_PATH}/release_notes.txt" _CONTENT) file(APPEND ${_PCAPPP_PACKAGE_README_OUTFILE} "${_CONTENT}") # As we only generate .TGZ for the moment keep it to False if(FALSE) # Apple productbuild cannot handle .md or file without extension Use textutil to convert them to HTML find_program(CONVERTER textutil) if(NOT CONVERTER) message(FATAL_ERROR "textutil executable not found") endif() execute_process( COMMAND ${CONVERTER} -convert html "${CMAKE_SOURCE_DIR}/LICENSE" -output "${CMAKE_BINARY_DIR}/LICENSE.html" ) execute_process( COMMAND ${CONVERTER} -convert html "${_PCAPPP_PACKAGE_README_OUTFILE}" -output "${CMAKE_BINARY_DIR}/README.html" ) set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_BINARY_DIR}/LICENSE.html") set(CPACK_RESOURCE_FILE_README "${CMAKE_BINARY_DIR}/README.html") else() set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_SOURCE_DIR}/LICENSE") set(CPACK_RESOURCE_FILE_README "${_PCAPPP_PACKAGE_README_OUTFILE}") endif() # used in CPackAdditionalInstall.cmake set(CPACK_ADDITIONAL_INSTALL_RESOURCES "${CPACK_RESOURCE_FILE_LICENSE}" "${CPACK_RESOURCE_FILE_README}") set( CPACK_ADDITIONAL_EXAMPLE_APP "${CMAKE_SOURCE_DIR}/Examples/ExampleApp/1_packet.pcap" "${CMAKE_SOURCE_DIR}/Examples/ExampleApp/CMakeLists.txt" "${CMAKE_SOURCE_DIR}/Examples/ExampleApp/main.cpp" "${CMAKE_SOURCE_DIR}/Examples/ExampleApp/README.md" ) set(CPACK_INSTALL_SCRIPT "${CMAKE_SOURCE_DIR}/cmake/CPackAdditionalInstall.cmake") include(CPack) endif() # uninstall target if(NOT TARGET uninstall) configure_file( "${CMAKE_CURRENT_SOURCE_DIR}/cmake/PcapPlusPlusUninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/PcapPlusPlusUninstall.cmake" IMMEDIATE @ONLY ) add_custom_target(uninstall COMMAND "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/PcapPlusPlusUninstall.cmake") endif()