cmake/modules/BPF.cmake (97 lines of code) (raw):

# SPDX-License-Identifier: Elastic-2.0 # Copyright 2021 Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one # or more contributor license agreements. Licensed under the Elastic License 2.0; # you may not use this file except in compliance with the Elastic License 2.0. # Tools and defines option(USE_BUILTIN_VMLINUX "If true, use the builtin vmlinux.h for building eBPF probes instead of generating one from system BTF" True) option(USE_ZIG_BPF_COMPILER "If true, use zig's drop in replacement to clang/llvm compiler" True) if (USE_ZIG_BPF_COMPILER) set(BPF_COMPILER_ENV "ZIG_GLOBAL_CACHE_DIR=${PROJECT_BINARY_DIR}/zigcache") set(BPF_COMPILER zig) set(BPF_COMPILER_FLAGS cc --target=bpfel-freestanding-none ) else() set(BPF_COMPILER_ENV "") set(BPF_COMPILER clang) set(BPF_COMPILER_FLAGS -target=bpf ) endif() set(LLVM_STRIP llvm-strip) set(BPFTOOL bpftool) set(BTF_FILE "/sys/kernel/btf/vmlinux") # Standard includes if(NOT USE_ZIG_BPF_COMPILER) execute_process(COMMAND ${CLANG} -print-file-name=include OUTPUT_VARIABLE NOSTDINC_INCLUDES ERROR_QUIET OUTPUT_STRIP_TRAILING_WHITESPACE) endif() if(NOT USE_BUILTIN_VMLINUX) set(VMLINUX_INSTALL_COMMAND /bin/sh -c "${BPFTOOL} btf dump file ${BTF_FILE} format c > ${EBPF_INSTALL_DIR}/include/vmlinux.h") else() set(VMLINUX_INSTALL_COMMAND /bin/sh -c "cp ${PROJECT_SOURCE_DIR}/contrib/vmlinux/${ARCH}/vmlinux.h ${EBPF_INSTALL_DIR}/include/vmlinux.h") endif() ExternalProject_Add( vmlinux-external DOWNLOAD_COMMAND "" CONFIGURE_COMMAND "" BUILD_COMMAND "" BUILD_IN_SOURCE 0 INSTALL_COMMAND ${VMLINUX_INSTALL_COMMAND} BUILD_BYPRODUCTS ${EBPF_INSTALL_DIR}/include/vmlinux.h ) add_library(vmlinux INTERFACE) set_property(TARGET vmlinux PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${EBPF_INSTALL_DIR}/include) add_dependencies(vmlinux vmlinux-external) function (ebpf_probe_target target) set(options OPTIONAL GENSKELETON INSTALL) set(multiValueArgs FLAGS SOURCES DEPENDENCIES PUBLIC_HEADERS DEPENDS) cmake_parse_arguments(EBPF_PROBE "${options}" "" "${multiValueArgs}" ${ARGN}) file(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/public-headers) set(OUT_FILE ${CMAKE_CURRENT_BINARY_DIR}/${target}.bpf.o) if (EBPF_PROBE_GENSKELETON) set(SKEL_FILE ${CMAKE_CURRENT_BINARY_DIR}/public-headers/${target}.skel.h) set(SKELETON_CMD ${BPFTOOL} gen skeleton ${OUT_FILE} > ${SKEL_FILE}) else() set(SKELETON_CMD /bin/sh -c "exit 0") endif() if (NOT CMAKE_BUILD_TYPE STREQUAL Debug) set(STRIP_CMD ${LLVM_STRIP} -d -g -S ${OUT_FILE}) else() set(STRIP_CMD /bin/sh -c "exit 0") endif() set(EBPF_PROBE_DEPFILE ${CMAKE_CURRENT_BINARY_DIR}/${target}.bpf.d) add_custom_command( OUTPUT ${OUT_FILE} ${SKEL_FILE} COMMAND ${EBPF_EXTERNAL_ENV_FLAGS} ${BPF_COMPILER_ENV} ${BPF_COMPILER} ${BPF_COMPILER_FLAGS} -MD -MF ${EBPF_PROBE_DEPFILE} ${EBPF_PROBE_FLAGS} -c ${EBPF_PROBE_SOURCES} -o ${OUT_FILE} COMMAND ${STRIP_CMD} COMMAND ${SKELETON_CMD} DEPENDS ${EBPF_PROBE_DEPENDS} ) add_custom_target(${target}_Probe DEPENDS ${OUT_FILE} ${SKEL_FILE}) add_dependencies(${target}_Probe ${EBPF_PROBE_DEPENDENCIES} libbpf vmlinux) add_library(${target} INTERFACE) add_dependencies(${target} ${target}_Probe) foreach(HDR ${EBPF_PROBE_PUBLIC_HEADERS}) configure_file(${HDR} ${CMAKE_CURRENT_BINARY_DIR}/public-headers/${HDR} COPYONLY) endforeach() if (EBPF_PROBE_GENSKELETON) set(EBPF_PROBE_PUBLIC_HEADERS ${EBPF_PROBE_PUBLIC_HEADERS} ${SKEL_FILE}) endif() set_property(TARGET ${target} PROPERTY PUBLIC_HEADER ${EBPF_PROBE_PUBLIC_HEADERS} ) set_property(TARGET ${target} PROPERTY RESOURCE ${OUT_FILE} ) target_include_directories(${target} INTERFACE ${CMAKE_CURRENT_BINARY_DIR}/public-headers) if (EBPF_PROBE_INSTALL) install(TARGETS ${target} RESOURCE DESTINATION ${EBPF_INSTALL_DIR}/probes PUBLIC_HEADER DESTINATION ${EBPF_INSTALL_DIR}/include ) endif() endfunction()