# Semana 10: recursión en árbol. Se usa dentro del entorno del curso.
#
#   make           compila los programas de la clase en build/
#   make lab       compila el laboratorio en build/lab/
#   make test      corre las pruebas de los ejemplos y de los apuntes
#   make test-lab  prueba su laboratorio (lab/regions.c y lab/board.c); falla hasta que lo terminen
#   make clean     borra lo generado
#
# Los programas de errors/ tienen errores a propósito. No se compilan con make:
# los compilan las pruebas, y ustedes, con los comandos de los apuntes.

CC = gcc
BASE = -Wall -Wextra -std=c17
CFLAGS = $(BASE) -g -fsanitize=address,undefined
BUILD = build
PROGRAMS = fib_count fib_trace fib_memo grid_fill fill_trace count_islands maze deep_fill fill_stack
LAB_HEADERS = lab/image.h lab/regions.h lab/board.h

.PHONY: all lab test test-lab clean

all: $(PROGRAMS:%=$(BUILD)/%) $(BUILD)/deep_fill_plain $(BUILD)/deep_fill_o2

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

# El mismo deep_fill.c sin sanitizers: con -O0, y con -O2.
$(BUILD)/deep_fill_plain: deep_fill.c | $(BUILD)
	$(CC) $(BASE) -g -O0 $< -o $@

$(BUILD)/deep_fill_o2: deep_fill.c | $(BUILD)
	$(CC) $(BASE) -g -O2 $< -o $@

# Cada .c se compila por separado y luego se enlaza, como en la semana 6.
$(BUILD)/lab/%.o: lab/%.c $(LAB_HEADERS) | $(BUILD)/lab
	$(CC) $(CFLAGS) -c $< -o $@

$(BUILD)/solution/%.o: solution/%.c $(LAB_HEADERS) | $(BUILD)/solution
	$(CC) $(CFLAGS) -Ilab -c $< -o $@

$(BUILD)/solution/%.o: lab/%.c $(LAB_HEADERS) | $(BUILD)/solution
	$(CC) $(CFLAGS) -Ilab -c $< -o $@

# Los programas del laboratorio, en cada carpeta: $(1) es lab o solution.
define LAB_PROGRAMS
$(BUILD)/$(1)/regions_tests: $(BUILD)/$(1)/regions_tests.o $(BUILD)/$(1)/regions.o $(BUILD)/$(1)/image.o
	$(CC) $(CFLAGS) $$^ -o $$@

$(BUILD)/$(1)/fill_demo: $(BUILD)/$(1)/fill_demo.o $(BUILD)/$(1)/regions.o $(BUILD)/$(1)/image.o
	$(CC) $(CFLAGS) $$^ -o $$@

$(BUILD)/$(1)/board_tests: $(BUILD)/$(1)/board_tests.o $(BUILD)/$(1)/board.o
	$(CC) $(CFLAGS) $$^ -o $$@

$(BUILD)/$(1)/minesweeper: $(BUILD)/$(1)/minesweeper.o $(BUILD)/$(1)/board.o
	$(CC) $(CFLAGS) $$^ -o $$@

$(BUILD)/$(1)/big_board: $(BUILD)/$(1)/big_board.o $(BUILD)/$(1)/board.o
	$(CC) $(CFLAGS) $$^ -o $$@

$(BUILD)/$(1)/big_board_plain: lab/big_board.c $(1)/board.c lab/board.h | $(BUILD)/$(1)
	$(CC) $(BASE) -g -O0 -Ilab lab/big_board.c $(1)/board.c -o $$@

$(BUILD)/$(1)/big_board_o2: lab/big_board.c $(1)/board.c lab/board.h | $(BUILD)/$(1)
	$(CC) $(BASE) -g -O2 -Ilab lab/big_board.c $(1)/board.c -o $$@
endef
LAB_TARGETS = regions_tests fill_demo board_tests minesweeper big_board big_board_plain big_board_o2

$(eval $(call LAB_PROGRAMS,lab))
$(eval $(call LAB_PROGRAMS,solution))

$(BUILD) $(BUILD)/lab $(BUILD)/solution:
	mkdir -p $@

lab: $(LAB_TARGETS:%=$(BUILD)/lab/%)

# Si existe solution/, también se comprueba la solución del laboratorio.
test: all
	@if [ -d solution ]; then $(MAKE) --no-print-directory $(LAB_TARGETS:%=$(BUILD)/solution/%); fi
	python3 -m unittest discover -p 'test_*.py'

test-lab: all lab
	LAB_DIR=lab python3 -m unittest -v test_lab

clean:
	rm -rf $(BUILD) __pycache__
