# Copyright (c) 2022 Yunshan Networks
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

LLC ?= /usr/bin/llc
CLANG ?= /usr/bin/clang
LLVM_STRIP ?= /usr/bin/llvm-strip
LLVM_OBJDUMP ?= /usr/bin/llvm-objdump
CC ?= gcc
PREFIX ?=
ifneq ($(PREFIX),)
	BUILD_DIR := build/$(PREFIX)
else
	BUILD_DIR := build
endif
TAEGET_KERN_SRC := socket_trace.bpf.c perf_profiler.bpf.c
TAEGET_KERN_SRC += $(KERN_SRC_EXTRA)
TAEGET_KERN_LL = $(addprefix $(BUILD_DIR)/,$(TAEGET_KERN_SRC:c=ll))
TAEGET_KERN_ELF = $(addprefix $(BUILD_DIR)/,$(TAEGET_KERN_SRC:c=elf))
OBJDUMP ?=
ifeq ($(V),1)
	Q =
	msg =
else
	Q = @
	msg = @printf '  %-8s %s%s\n'                                   \
                      "$(1)"                                            \
                      "$(patsubst $(abspath $(OUTPUT))/%,%,$(2))"       \
                      "$(if $(3),  CO-RE)";
endif
ARCH := $(shell uname -m | sed 's/x86_64/x86/' | sed 's/aarch64/arm64/' | sed 's/ppc64le/powerpc/' | sed 's/mips.*/mips/')

ifeq ($(LINUX_VER_3_10_0),1)
	EXTRA_EBPF_CLAGS = -DLINUX_VER_3_10_0
else ifeq ($(LINUX_VER_5_2_PLUS),1)
	EXTRA_EBPF_CLAGS = -DLINUX_VER_5_2_PLUS
else ifeq ($(LINUX_VER_KYLIN),1)
	EXTRA_EBPF_CLAGS = -DLINUX_VER_KYLIN
else ifeq ($(LINUX_VER_KFUNC),1)
	EXTRA_EBPF_CLAGS = -DLINUX_VER_KFUNC
else ifeq ($(LINUX_VER_RT),1)
	EXTRA_EBPF_CLAGS = -DLINUX_VER_RT
else ifeq ($(LINUX_VER_KPROBE),1)
	EXTRA_EBPF_CLAGS = -DSUPPORTS_KPROBE_ONLY
endif

FINAL_TARGET = -emit-llvm -D__TARGET_ARCH_$(ARCH) -o ${@:.elf=.ll} -c $^ && $(LLC) -march=bpf -filetype=obj -mcpu=v2 -o $@ ${@:.elf=.ll}

all: $(TAEGET_KERN_ELF)

EBPF_CLAGS ?= -I. -Ivmlinux -Iinclude -I../../../crates/trace-utils/src \
        -D__BPF_TRACING__ -D GROUP_LEADER_OFFSET_OVERRIDE=0 \
        -DSTART_BOOTTIME_OFFSET_OVERRIDE=0      \
        -DSTART_BOOTTIME_VARNAME=real_start_time

ifeq ($(OBJDUMP),1)
	OBJDUMP_CMD = $(Q)$(LLVM_OBJDUMP) --source --debug-vars --line-numbers --symbol-description $@ > ${@:.elf=.objdump}
endif

define compile_elf
	$(call msg,BPF,$@,$(CORE))	
	$(Q)mkdir -p $(BUILD_DIR)
	$(Q)$(CLANG) $(EBPF_CLAGS) $(EXTRA_EBPF_CLAGS) -DCOMPILE_MUSL=$(C_USE_STATIC) -std=gnu99 -Wimplicit-function-declaration \
		-ffreestanding -fno-builtin -Wall \
		-Wno-deprecated-declarations \
		-Wno-gnu-variable-sized-type-not-at-end \
		-Wno-pragma-once-outside-header \
		-Wno-address-of-packed-member \
		-Wno-unknown-warning-option \
		-fno-color-diagnostics \
		-fno-unwind-tables \
		-fno-stack-protector \
		-fno-asynchronous-unwind-tables -g -O2 $(FINAL_TARGET)
	$(OBJDUMP_CMD)
	$(Q)$(LLVM_STRIP) -g $@ # strip useless DWARF info
endef

$(BUILD_DIR)/%.elf: ../user/extended/bpf/%.c
	$(call compile_elf)

$(BUILD_DIR)/%.elf: %.c
	$(call compile_elf)

clean:
	@rm -f ../user/extended/bpf/*.bpf.elf ../user/extended/bpf/*.bpf.ll
	@rm -rf $(BUILD_DIR)
	@rm $(TAEGET_KERN_ELF) $(TARGET) ${TAEGET_KERN_ELF:.elf=.ll} *.S *.objdump -rf

.PHONY: all clean

