# Semana 5: memoria dinámica. 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 hunt      compila los programas de la cacería en build/hunt/: con sanitizers,
#                  y con el sufijo _vg para valgrind (-g -O0, sin sanitizers)
#   make test      corre las pruebas de los ejemplos y de los apuntes
#   make test-lab  prueba su laboratorio; 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
CFLAGS = -Wall -Wextra -std=c17 -g -fsanitize=address,undefined
VGFLAGS = -Wall -Wextra -std=c17 -g -O0
BUILD = build
PROGRAMS = reverse_numbers range_block sizes calloc_zero strings_owner student realloc_grow growth_count image_size
HUNT = longest_word seat_list route_backup grade_histogram passing_groups
IMAGE_HEADERS = lab/image.h lab/filters.h
ARRAY_HEADERS = lab/int_array.h
LAB_PROGRAMS = image_tests image_demo str_tests array_tests sum_file

.PHONY: all lab hunt test test-lab clean

all: $(PROGRAMS:%=$(BUILD)/%) $(BUILD)/no_memory

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

# Sin sanitizers: con ASan, un pedido imposible detiene el programa antes de que malloc devuelva.
$(BUILD)/no_memory: no_memory.c | $(BUILD)
	$(CC) $(VGFLAGS) $< -o $@

$(BUILD)/lab/image_tests: lab/image_tests.c lab/image.c $(IMAGE_HEADERS) | $(BUILD)/lab
	$(CC) $(CFLAGS) -Ilab lab/image_tests.c lab/image.c -o $@

$(BUILD)/lab/image_demo: lab/image_demo.c lab/image.c lab/filters.c $(IMAGE_HEADERS) | $(BUILD)/lab
	$(CC) $(CFLAGS) -Ilab lab/image_demo.c lab/image.c lab/filters.c -o $@

$(BUILD)/lab/str_tests: lab/str_tests.c lab/str_tools.c lab/str_tools.h | $(BUILD)/lab
	$(CC) $(CFLAGS) -Ilab lab/str_tests.c lab/str_tools.c -o $@

$(BUILD)/lab/array_tests: lab/array_tests.c lab/int_array.c $(ARRAY_HEADERS) | $(BUILD)/lab
	$(CC) $(CFLAGS) -Ilab lab/array_tests.c lab/int_array.c -o $@

$(BUILD)/lab/sum_file: lab/sum_file.c lab/int_array.c $(ARRAY_HEADERS) | $(BUILD)/lab
	$(CC) $(CFLAGS) -Ilab lab/sum_file.c lab/int_array.c -o $@

$(BUILD)/solution/image_tests: solution/image_tests.c solution/image.c $(IMAGE_HEADERS) | $(BUILD)/solution
	$(CC) $(CFLAGS) -Ilab solution/image_tests.c solution/image.c -o $@

$(BUILD)/solution/image_demo: lab/image_demo.c solution/image.c lab/filters.c $(IMAGE_HEADERS) | $(BUILD)/solution
	$(CC) $(CFLAGS) -Ilab lab/image_demo.c solution/image.c lab/filters.c -o $@

$(BUILD)/solution/str_tests: solution/str_tests.c solution/str_tools.c lab/str_tools.h | $(BUILD)/solution
	$(CC) $(CFLAGS) -Ilab solution/str_tests.c solution/str_tools.c -o $@

$(BUILD)/solution/array_tests: solution/array_tests.c solution/int_array.c $(ARRAY_HEADERS) | $(BUILD)/solution
	$(CC) $(CFLAGS) -Ilab solution/array_tests.c solution/int_array.c -o $@

$(BUILD)/solution/sum_file: lab/sum_file.c solution/int_array.c $(ARRAY_HEADERS) | $(BUILD)/solution
	$(CC) $(CFLAGS) -Ilab lab/sum_file.c solution/int_array.c -o $@

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

$(BUILD)/hunt/%_vg: lab/hunt/%.c | $(BUILD)/hunt
	$(CC) $(VGFLAGS) $< -o $@

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

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

hunt: $(HUNT:%=$(BUILD)/hunt/%) $(HUNT:%=$(BUILD)/hunt/%_vg)

# Si existe solution/, también se comprueba la solución del laboratorio.
test: all
	@if [ -d solution ]; then $(MAKE) --no-print-directory \
	  $(LAB_PROGRAMS:%=$(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__
