TOOLCHAIN_PATH = /opt/xpack-riscv-none-elf-gcc-14.2.0-3/bin/
CC = $(TOOLCHAIN_PATH)riscv-none-elf-gcc
LD = $(TOOLCHAIN_PATH)riscv-none-elf-g++
CXX = $(TOOLCHAIN_PATH)riscv-none-elf-g++
OBJCOPY = $(TOOLCHAIN_PATH)riscv-none-elf-objcopy

linker_script = bootloader.ld
includes =
sources =

CFLAGS = -march=rv32i -g -ffunction-sections -fdata-sections -Os -Werror -Wall -flto
CXXFLAGS = $(CFLAGS) -std=c++20 -fno-exceptions -fcoroutines
CPPFLAGS = -MD -MP
LDFLAGS = -march=rv32i \
		  -g \
		  -Wl,--gc-sections -Os \
		  -Wl,--print-memory-usage -flto

sources += hal/lib/common/xil_assert.c
includes += -Ihal/lib/common

sources += hal/uart/xuartlite.c hal/uart/xuartlite_stats.c hal/uart/xuartlite_intr.c
includes += -Ihal/uart

bootloader_objects = bootloader.o start.o $(sources:.c=.o)
app_objects = helloworld.o start.o $(sources:.c=.o)

CPPFLAGS += $(includes)

%.bin: %.elf
	$(OBJCOPY) -O binary $< $@

bootloader.elf: $(bootloader_objects) bootloader.ld
	$(LD) -Wl,-Tbootloader.ld $(LDFLAGS) -o $@ $(bootloader_objects)

app.elf: $(app_objects) app.ld
	$(LD) -Wl,-Tapp.ld $(LDFLAGS) -o $@ $(app_objects)

deps = $(app_objects:.o=.d) $(bootloader_objects:.o=.d)

HOSTCXX = clang++
HOSTLDFLAGS = -lgmock -lgtest -lgtest_main -L/usr/local/opt/llvm/lib -L/usr/local/lib
HOSTCFLAGS = -std=c++20 -g\
			 -I/usr/local/opt/llvm/include \
			 -I/usr/local/include \
			 -I/usr/local/include \
			 -MP -MD

TSAN_CFLAGS = $(HOSTCFLAGS) -fsanitize=thread
ASAN_CFLAGS = $(HOSTCFLAGS) -fsanitize=address -fsanitize=leak

tests =

.PHONY: test
test: $(tests)  ## Run tests

%.run: test/%
	TSAN_OPTIONS='suppressions=tsan.suppressions' ASAN_OPTIONS=detect_leaks=1 ./$<

%.host.o: %.cc
	$(HOSTCXX) $(HOSTCFLAGS) -c -o $@ $<

test/%_test: | mktest
	$(HOSTCXX) $(HOSTCFLAGS) -o $@ $^ $(HOSTLDFLAGS)

test/%_asan: | mktest
	$(HOSTCXX) $(ASAN_CFLAGS) -o $@ $^ $(HOSTLDFLAGS)

test/%_tsan: | mktest
	$(HOSTCXX) $(TSAN_CFLAGS) -o $@ $^ $(HOSTLDFLAGS)

.PHONY: mktest
mktest:
	mkdir -p test

test_deps =

.PHONY: bootloader
bootloader:  ## Build the bootloader in a docker container
	docker build -o . --target bootloader-export .

.PHONY: dev-image
dev-image:
	docker build -t mbv-dev --target dev .

.PHONY: dev
dev: dev-image  ## Run a dev container
	docker run -it --rm -v $(CURDIR):/workspace -w /workspace mbv-dev

.PHONY: clean
clean:  ## Remove generated files
	rm -rf *.elf *.bin $(app_objects) $(bootloader_objects) $(deps)
	rm -rf test/ *.dSYM $(test_deps) *.o

.PHONY: help
help:           ## Show this help
	@echo Noteworthy targets:
	@egrep '^[a-zA-Z_-]+:.*?## .*$$' $(firstword $(MAKEFILE_LIST)) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-20s\033[0m %s\n", $$1, $$2}'
.DEFAULT_GOAL := help

#-include $(deps)
#-include $(test_deps)