LLC ?= llc
CLANG ?= clang
CC ?= gcc

# Detecta a arquitetura de verdade em vez de fixar x86_64 (o host de
# produção é ARM64/aarch64 — Oracle Ampere). O diretório de headers da
# libc varia por arquitetura (/usr/include/<triplet>/), então isso
# precisa ser dinâmico ou o -I aponta pra um caminho que nunca existiu
# nesta máquina.
# Mesmo mapeamento usado no Makefile do ebpf-sockmap (convenção libbpf/CO-RE:
# __TARGET_ARCH_arm64, não __TARGET_ARCH_aarch64).
ARCH        := $(shell uname -m | sed 's/x86_64/x86/' | sed 's/aarch64/arm64/')
MULTIARCH   := $(shell $(CC) -dumpmachine 2>/dev/null)
BPF_OBJS    := bridge_xdp.o xdp_ddos_filter.o xdp_wg_mtu_optimizer.o

all: $(BPF_OBJS) loader af_xdp_user

# Regra genérica: qualquer programa XDP compila num passo só (clang
# direto pra .o, sem o pipeline antigo emit-llvm + llc). Antes só existia
# a regra explícita pra bridge_xdp.o — xdp_ddos_filter.o e
# xdp_wg_mtu_optimizer.o que estavam na pasta foram gerados por fora do
# Makefile, então "make" nunca os reconstruía depois de editar o .c
# correspondente.
#
# -g é OBRIGATÓRIO aqui: os mapas destes programas usam a sintaxe
# moderna (struct { __uint(type,...); ... } SEC(".maps")), que depende
# de BTF pra o libbpf conseguir interpretar. Sem -g não sai BTF, e
# "ip link set ... xdp obj" falha com "BTF is required, but is missing
# or corrupted" — foi exatamente esse erro que o pipeline antigo
# (emit-llvm sem -g, depois llc) causava.
%.o: %.c
	$(CLANG) -g -O2 \
	    -target bpf \
	    -D __BPF_TRACING__ \
	    -D__TARGET_ARCH_$(ARCH) \
	    -I/usr/include/$(MULTIARCH) \
	    -Wall \
	    -c -o $@ $<

loader: loader.c
	$(CC) -Wall -o loader loader.c -l:libbpf.a -lelf -lz

# af_xdp_user.c é userspace puro (usa só headers de kernel/libc via
# syscalls diretos: socket(AF_XDP), setsockopt, mmap) — não precisa
# linkar libbpf.
af_xdp_user: af_xdp_user.c
	$(CC) -Wall -O2 -o af_xdp_user af_xdp_user.c

clean:
	rm -f $(BPF_OBJS) *.ll loader af_xdp_user
