SRC_DIR = src
COLLEEN_SRCS = $(SRC_DIR)/Colleen/Colleen.c
GRACE_SRCS = $(SRC_DIR)/Grace/Grace.c
SULLY_SRCS = $(SRC_DIR)/Sully/Sully.c

COLLEEN = Colleen
GRACE = Grace
SULLY = Sully

COLLEEN_ASM_SRCS = $(SRC_DIR)/Colleen/Colleen.s
COLLEEN_ASM = Colleen_asm
GRACE_ASM_SRCS = $(SRC_DIR)/Grace/Grace.s
GRACE_ASM = Grace_asm
NASM = nasm
NASMFLAGS = -f elf64
LD = ld

.DEFAULT_GOAL := all
MAKEFLAGS += --no-print-directory

CC = clang
CPPFLAGS = -std=c99 -I includes
CFLAGS = -Wall -Wextra -Werror -pipe -Wpedantic -Wconversion -Wshadow -Wvla
LDFLAGS =

OBJ_DIR = .build

COLLEEN_OBJS = $(COLLEEN_SRCS:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
COLLEEN_DEPS = $(COLLEEN_OBJS:.o=.d)

GRACE_OBJS = $(GRACE_SRCS:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
GRACE_DEPS = $(GRACE_OBJS:.o=.d)

SULLY_OBJS = $(SULLY_SRCS:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
SULLY_DEPS = $(SULLY_OBJS:.o=.d)

COLLEEN_ASM_OBJS = $(COLLEEN_ASM_SRCS:$(SRC_DIR)/%.s=$(OBJ_DIR)/%.asm.o)
GRACE_ASM_OBJS = $(GRACE_ASM_SRCS:$(SRC_DIR)/%.s=$(OBJ_DIR)/%.asm.o)

.PHONY: all
all: $(COLLEEN) $(GRACE) $(SULLY) $(COLLEEN_ASM) $(GRACE_ASM)

$(GRACE): $(GRACE_OBJS)
	$(CC) $(LDFLAGS) -o $@ $^

$(COLLEEN): $(COLLEEN_OBJS)
	$(CC) $(LDFLAGS) -o $@ $^
	
$(SULLY): $(SULLY_OBJS)
	$(CC) $(LDFLAGS) -o $@ $^

$(COLLEEN_ASM): $(COLLEEN_ASM_OBJS)
	$(LD) -o $@ $^

$(GRACE_ASM): $(GRACE_ASM_OBJS)
	$(LD) -o $@ $^

$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c
	@mkdir -p $(dir $@)
	$(CC) $(CPPFLAGS) $(CFLAGS) -MMD -MP -c $< -o $@

$(OBJ_DIR)/%.asm.o: $(SRC_DIR)/%.s
	@mkdir -p $(dir $@)
	$(NASM) $(NASMFLAGS) $< -o $@

-include $(COLLEEN_DEPS)
-include $(GRACE_DEPS)
-include $(SULLY_DEPS)

.PHONY: clean
clean:
	$(RM) -r $(OBJ_DIR)

.PHONY: fclean
fclean: clean
	$(RM) $(COLLEEN) $(GRACE) $(SULLY) $(COLLEEN_ASM) $(GRACE_ASM)

.PHONY: re
re: fclean
	$(MAKE) all
