EXEC = r2unity
CONFIG_H = r2unity_config.h
PROJECT_VERSION = $(shell ./release.sh version)
ifeq ($(PROJECT_VERSION),)
	error
endif

SOEXT = $(shell r2 -H R2_LIBEXT)
ifeq ($(SOEXT),dylib)
PLUGIN_SHFLAGS = -dynamiclib
else
PLUGIN_SHFLAGS = -shared
endif

CORE_PLUGIN = src/r2/core_r2unity.$(SOEXT)
BIN_PLUGIN = src/r2/bin_r2unity.$(SOEXT)
PLUGINS = $(CORE_PLUGIN) $(BIN_PLUGIN)
CC = gcc

CFLAGS = -Wall -Wextra -g -I. $(shell pkg-config --cflags r_util r_bin 2>/dev/null || echo "")
LDFLAGS = $(shell pkg-config --libs r_util r_bin 2>/dev/null || echo "")

# r_core plugin flags (full radare2)
CORE_PLUGIN_CFLAGS = -Wall -Wextra -g -fPIC $(shell pkg-config --cflags r_core r_bin 2>/dev/null || echo "")
CORE_PLUGIN_LDFLAGS = $(shell pkg-config --libs r_core r_bin 2>/dev/null || echo "")

# r_bin plugin flags
BIN_PLUGIN_CFLAGS = -Wall -Wextra -g -fPIC $(shell pkg-config --cflags r_bin 2>/dev/null || echo "")
BIN_PLUGIN_LDFLAGS = $(shell pkg-config --libs r_bin 2>/dev/null || echo "")

R2_USER_PLUGINS = $(shell r2 -H R2_USER_PLUGINS 2>/dev/null)

BGDATABASE_LIB_SRCS = src/lib/bgdatabase.c
RESOURCE_PACK_LIB_SRCS = src/lib/resource_pack.c
BIN_ONLY_LIB_SRCS = $(BGDATABASE_LIB_SRCS) $(RESOURCE_PACK_LIB_SRCS)
LIB_SRCS = $(filter-out $(BIN_ONLY_LIB_SRCS),$(wildcard src/lib/*.c)) $(wildcard src/lib/bin/*.c)
LIB_OBJS = $(LIB_SRCS:.c=.o)
LEGACY_OBJS = src/lib/elf.o src/lib/macho.o src/lib/pe.o src/lib/native.o
CLI_SRCS = src/main.c
CLI_OBJS = $(CLI_SRCS:.c=.o)
OBJS = $(CLI_OBJS) $(LIB_OBJS)

R2PM_BINDIR=$(shell r2pm -H R2PM_BINDIR)

all: $(EXEC)

r2 plugin: $(PLUGINS)

test: $(EXEC) $(PLUGINS)
	python3 test/test_import.py

install-plugin: $(PLUGINS)
	@[ -n "$(R2_USER_PLUGINS)" ] || (echo "r2 not found; cannot resolve R2_USER_PLUGINS"; exit 1)
	mkdir -p "$(R2_USER_PLUGINS)"
	# Replace the inode so macOS does not reuse a stale code-signature cache.
	@for plugin in $(PLUGINS); do \
		name=$${plugin##*/}; \
		cp -f "$$plugin" "$(R2_USER_PLUGINS)/.$$name.tmp" && \
		mv -f "$(R2_USER_PLUGINS)/.$$name.tmp" "$(R2_USER_PLUGINS)/$$name" || exit 1; \
	done

uninstall-plugin:
	@[ -n "$(R2_USER_PLUGINS)" ] || (echo "r2 not found; cannot resolve R2_USER_PLUGINS"; exit 1)
	rm -f "$(R2_USER_PLUGINS)/core_r2unity.$(SOEXT)"
	rm -f "$(R2_USER_PLUGINS)/bin_r2unity.$(SOEXT)"

fmt:
	clang-format-radare2 src/**/*.c

user-install: $(EXEC) install-plugin
	mkdir -p "$(R2PM_BINDIR)"
	cp -f $(EXEC) "$(R2PM_BINDIR)/.$(EXEC).tmp"
	mv -f "$(R2PM_BINDIR)/.$(EXEC).tmp" "$(R2PM_BINDIR)/$(EXEC)"

user-uninstall: uninstall-plugin
	rm -f "$(R2PM_BINDIR)/$(EXEC)"

# Binary package for r2pm -bi: plugins/ and bin/ for this r2 version and platform
# Binary package for r2pm -bi: plugins/ and bin/ for this r2 version and platform
# R2PM_OS/ARCH/BITS require a recent r2pm; fall back to uname when missing
R2PM_OS_SH = $(shell r2pm -H R2PM_OS 2>/dev/null)
R2PM_ARCH_SH = $(shell r2pm -H R2PM_ARCH 2>/dev/null)
R2PM_BITS_SH = $(shell r2pm -H R2PM_BITS 2>/dev/null)
ifeq ($(R2PM_OS_SH),)
ifeq ($(shell uname -s),Darwin)
R2PM_OS_SH = darwin
else
R2PM_OS_SH = linux
endif
endif
ifeq ($(R2PM_ARCH_SH),)
ifeq ($(shell uname -m),x86_64)
R2PM_ARCH_SH = x86
else ifneq (,$(filter $(shell uname -m),aarch64 arm64))
R2PM_ARCH_SH = arm
else
R2PM_ARCH_SH = $(shell uname -m)
endif
endif
ifeq ($(R2PM_BITS_SH),)
R2PM_BITS_SH = 64
endif
BINDIST_ZIP = r2unity-$(shell r2 -qv)-$(R2PM_OS_SH)-$(R2PM_ARCH_SH)-$(R2PM_BITS_SH).zip

bindist: $(EXEC) $(PLUGINS)
	rm -rf build/bindist $(BINDIST_ZIP)
	$(MAKE) user-install R2_USER_PLUGINS=$(CURDIR)/build/bindist/plugins R2PM_BINDIR=$(CURDIR)/build/bindist/bin
	cd build/bindist && zip -r $(CURDIR)/$(BINDIST_ZIP) plugins bin

$(EXEC): $(OBJS)
	$(CC) -o $@ $^ $(LDFLAGS)

$(CONFIG_H): meson.build
	echo '#define R2UNITY_VERSION "$(PROJECT_VERSION)"' > $@

$(CLI_OBJS): %.o: %.c $(CONFIG_H)
	$(CC) $(CFLAGS) -c -o $@ $<

$(CORE_PLUGIN): src/r2/core_r2unity.c $(LIB_SRCS)
	$(CC) $(CORE_PLUGIN_CFLAGS) $(PLUGIN_SHFLAGS) -o $@ $^ $(CORE_PLUGIN_LDFLAGS)

$(BIN_PLUGIN): src/r2/bin_r2unity.c $(LIB_SRCS) $(BIN_ONLY_LIB_SRCS)
	$(CC) $(BIN_PLUGIN_CFLAGS) $(PLUGIN_SHFLAGS) -o $@ $^ $(BIN_PLUGIN_LDFLAGS)

%.o: %.c
	$(CC) $(CFLAGS) -c -o $@ $<

clean:
	rm -f $(EXEC) $(OBJS) $(LEGACY_OBJS) $(PLUGINS) $(CONFIG_H)


.PHONY: all clean plugin install-plugin uninstall-plugin fmt bindist test
