Search code examples
cmakeintel-oneapisyclpcapplusplus

Failing to compile and link PcapPlusPlus library with SYCL code


I want to use the C++ library PcapPlusPlus and it‘s header files in my SYCL code. More exactly I want to compile it with the Intel C++ Compiler (icpx). I know how to program and know how C, Java and Python work but seem to have issues to work with C++ and using external libraries. I can't seem to make it work, to compile and link the library correctly. I tried it with CMake which I had to read into because I really had to use it the first time but more on this further down.

I am using CentOS Stream 8 and oneAPI Base Toolkit 2023.1 which I tested successfully with code that doesn't use 3rd party libraries.

So I downloaded the Github repository because I have to build it myself for CentOS Stream 8. I put the files into my project folder and went into package to start the build of the library like in the instructions with CMake and the compiler I want to use it with (icpx).

cmake -S . -B build -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER=icx -DCMAKE_CXX_COMPILER=icpx -DCMAKE_INSTALL_PREFIX=/path/to/PcapPlusPlus

As the instructions say, build and install it.

cmake --build build
cmake --install build

After that I tried to compile the code example of PcapPlusPlus with the instructions and CMake file they provide. This worked but did not use the icpx compiler.

So I went ahead and searched on how I could link the libraries and header files with just using the icpx command in the CLI. I stumbled upon the parameters -I to add the path to the header files, -L for the libraries and -l to give the name of the library. PcapPlusPlus creates 3 static libraries.

icpx -I/path/to/installed/PcapPlusPlus/include -L/path/to/installed/PcapPlusPlus/lib -lCommon++ -lPacket++ -lPcap++ mysrc.cpp -o myexe

This command created a lot of "undefined reference" errors pointing at lines in the header files of Packet.h. icpx exits with the error:
icpx: error: linker command failed with exit code 1

Another try was to create a CMakeLists.txt file that uses the icpx compiler with the help of the CMakeLists.txt of the example of PcapPlusPlus and this documentation of Intel. It resulted in the following CMakeLists.txt file

if (CMAKE_HOST_WIN32)
    # need at least CMake 3.23 for IntelLLVM support of IntelSYCL package on Windows
    cmake_minimum_required(VERSION 3.23)
else()
    # CMake 3.20.5 is the minimum recommended for IntelLLVM on Linux
    cmake_minimum_required(VERSION 3.20.5)
endif()

project(simple-sycl LANGUAGES CXX)

set(CMAKE_CXX_COMPILER icpx)
# popen()/pclose() are not C++ standards
set(CMAKE_CXX_EXTENSIONS ON)

find_package(PcapPlusPlus REQUIRED)

add_executable("${PROJECT_NAME}" main.cpp)
# We want to have the binary compiled in the same folder as the .cpp to be near the PCAP file
set_target_properties("${PROJECT_NAME}" PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_SOURCE_DIR}")
# Link with Pcap++ libraries
target_link_libraries("${PROJECT_NAME}" PUBLIC PcapPlusPlus::Pcap++)

I erased find_package(IntelSYCL REQUIRED) as it led to errors of not finding IntelSYCL

The command to start the cmake process was following:

cmake -DCMAKE_C_COMPILER=icx -DCMAKE_CXX_COMPILER=icpx -DPcapPlusPlus_ROOT=/path/to/PcapPlusPlus

This worked until the find_package line for the PcapPlusPlus package, as it creates a C-file which the icpx cannot read of course. When adding C to the project() it went through with no error but not creating a binary.

I also tried to use one of the oneAPI samples and modify the CMakeLists.txt and adding the lines to find the package with the same errors.

Now I am stuck because I can't seem to find a solution for this linking issue and was wondering what I am doing wrong or if it is possible to use the library.


Solution

  • Solution

    So with some help of @paleonix (thank you) and an idea I have come to an easy solution.

    First of all, what I noticed that find_package(PcapPlusPlus REQUIRED) needs, is the header files in the path /usr/local/include/pcapplusplus so I copied them from the installation folders into there.

    OneAPI has its own example projects and come with their CMakeLists.txt which is easier to build upon and add the needed lines from the PcapPlusPlus library.

    Modifications to the Code

    So I choose the vector-add example, downloaded it and replaced the code in src/vector-add-buffers.cpp with the code of the PcapPlusPlus example. Keeping includes for sycl/sycl.hpp and <sycl/ext/intel/fpga_extensions.hpp> as that is what I need later on.

    Modifications to the CMakeLists.txt files

    The first modification has to be made in CMakeLists.txt to prevent the issue that the detect_pcap_version.c can't be read. Therefore the line:

    project(VectorAdd CXX) needs a "C" added to it and should look like project(VectorAdd CXX C)

    Next in the src/CMakeLists.txt needs to be added the find_package(PcapPlusPlus REQUIRED) line. I placed it in SECTION 1 right above the add_executable(${TARGET_NAME} ${SOURCE_FILE}).

    Also it needs the line target_link_libraries(${TARGET_NAME} PUBLIC PcapPlusPlus::Pcap++) after the set_target_properties(${TARGET_NAME} PROPERTIES LINK_FLAGS "${LINK_FLAGS}") line. This slightly modified function from the PcapPlusPlus example needs to be added in each SECTION with the according TARGET_NAME variable.

    Build

    The next step is following oneAPIs instructions in the README.md to build the project and adding the compiler parameters to the cmake command:

    1. mkdir build
    2. cd build
    3. cmake -DCMAKE_C_COMPILER=icx -DCMAKE_CXX_COMPILER=icpx ..

    With these steps a Makefile should be created in this build folder which can now be executed. As the README.md states, one can choose from the options, for this example I used make cpu-gpu and wait until the process finishes.

    Execute

    Now that the binary is created. To use it, we still need the pcap of PcapPlusPlus placed in this folder. With ./vector-add-buffers it executes successfully as SYCL code.