LIB_NAME = icmp
LIB_STATIC = lib$(LIB_NAME).a
LIB_SHARED = lib$(LIB_NAME).so
LIB_VERSION = 1.0.0
LIB_SHARED_VERSIONED = $(LIB_SHARED).$(LIB_VERSION)
TEST_BIN = libicmp.test

# Build configuration
BUILD_STATIC ?= yes
BUILD_SHARED ?= yes

# Installation paths
PREFIX ?= /usr/local
INCLUDEDIR = $(PREFIX)/include
LIBDIR = $(PREFIX)/lib

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

include sources.mk

CC = clang
CPPFLAGS = -std=c99 -I includes -D_POSIX_C_SOURCE=199309L
CFLAGS = -Wall -Wextra -Werror -pipe -Wpedantic -Wconversion
CFLAGS_SHARED = $(CFLAGS) -fPIC
LDFLAGS =
TEST_LDFLAGS = -lcriterion
TEST_CFLAGS = -Wall -Wextra -Werror -pipe

OBJ_DIR = .build
OBJ_DIR_STATIC = $(OBJ_DIR)/static
OBJ_DIR_SHARED = $(OBJ_DIR)/shared

OBJS_STATIC = $(SRCS:$(SRC_DIR)/%.c=$(OBJ_DIR_STATIC)/%.o)
OBJS_SHARED = $(SRCS:$(SRC_DIR)/%.c=$(OBJ_DIR_SHARED)/%.o)
DEPS = $(OBJS_STATIC:.o=.d) $(OBJS_SHARED:.o=.d)

TARGETS =
ifeq ($(BUILD_STATIC),yes)
TARGETS += $(LIB_STATIC)
endif
ifeq ($(BUILD_SHARED),yes)
TARGETS += $(LIB_SHARED)
endif

.PHONY: all
all: $(TARGETS)

$(LIB_STATIC): $(OBJS_STATIC)
	$(AR) rcs $@ $^

$(LIB_SHARED): $(OBJS_SHARED)
	$(CC) -shared -Wl,-soname,$(LIB_SHARED_VERSIONED) -o $@ $^

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

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

-include $(DEPS)

.PHONY: test
test: $(TEST_BIN)
	./$(TEST_BIN)

$(TEST_BIN): $(TESTS) $(OBJS_STATIC)
	@mkdir -p $(dir $@)
	$(CC) $(CPPFLAGS) -I tests $(TEST_CFLAGS) $(TEST_LDFLAGS) $^ -o $@

.PHONY: install
install:
	@test -f $(LIB_STATIC) -o -f $(LIB_SHARED) || \
		(echo "Error: No libraries found. Run 'make' first." >&2 && false)
	install -d $(DESTDIR)$(INCLUDEDIR)
	install -d $(DESTDIR)$(LIBDIR)
	install -m 644 includes/icmp.h $(DESTDIR)$(INCLUDEDIR)
	install -m 644 includes/icmp_types.h $(DESTDIR)$(INCLUDEDIR)
ifneq ($(wildcard $(LIB_STATIC)),)
	install -m 644 $(LIB_STATIC) $(DESTDIR)$(LIBDIR)
endif
ifneq ($(wildcard $(LIB_SHARED)),)
	install -m 755 $(LIB_SHARED) $(DESTDIR)$(LIBDIR)/$(LIB_SHARED_VERSIONED)
	ln -sf $(LIB_SHARED_VERSIONED) $(DESTDIR)$(LIBDIR)/$(LIB_SHARED)
endif

.PHONY: uninstall
uninstall:
	$(RM) $(DESTDIR)$(INCLUDEDIR)/icmp.h
	$(RM) $(DESTDIR)$(INCLUDEDIR)/icmp_types.h
	$(RM) $(DESTDIR)$(LIBDIR)/$(LIB_STATIC)
	$(RM) $(DESTDIR)$(LIBDIR)/$(LIB_SHARED)*

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

.PHONY: fclean
fclean: clean
	$(RM) $(LIB_STATIC) $(LIB_SHARED)
	$(RM) $(TEST_BIN)

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