CC ?= cc
PKG_CONFIG ?= pkg-config
PREFIX ?= /usr/local
LIBDIR ?= $(PREFIX)/lib
INCLUDEDIR ?= $(PREFIX)/include
BUILD_DIR ?= build

OPENSSL_CFLAGS ?= $(shell $(PKG_CONFIG) --cflags libcrypto)
OPENSSL_LIBS ?= $(shell $(PKG_CONFIG) --libs libcrypto)
CPPFLAGS += -Iinclude $(OPENSSL_CFLAGS) -DOPENSSL_API_COMPAT=0x30000000L -DOPENSSL_NO_DEPRECATED
CFLAGS ?= -O2 -g
COMMON_CFLAGS = -std=c11 -Wall -Wextra -Wpedantic -fPIC -fvisibility=hidden

ifeq ($(shell uname -s),Darwin)
  SHARED_EXT = dylib
  SHARED_FLAGS = -dynamiclib -Wl,-install_name,@rpath/libm7crypto.dylib
  TEST_RPATH = -Wl,-rpath,@loader_path
else
  SHARED_EXT = so
  SHARED_FLAGS = -shared -Wl,-soname,libm7crypto.so
  TEST_RPATH = -Wl,-rpath,'$$ORIGIN'
endif

LIBRARY = $(BUILD_DIR)/libm7crypto.$(SHARED_EXT)
SOURCES = src/m7crypto.c src/error.c src/key.c src/keygen.c src/key_export.c src/signature.c \
          src/rsa.c src/rsa_pss.c src/rsa_oaep.c src/ecdsa.c src/eddsa.c src/hmac.c src/ml_dsa.c
OBJECTS = $(SOURCES:src/%.c=$(BUILD_DIR)/%.o)
TESTS = $(BUILD_DIR)/test_pss $(BUILD_DIR)/test_families $(BUILD_DIR)/test_keygen $(BUILD_DIR)/test_encryption

.PHONY: all test sanitize install clean
all: $(LIBRARY)

$(BUILD_DIR):
	mkdir -p "$@"

$(BUILD_DIR)/%.o: src/%.c src/internal.h include/m7crypto.h | $(BUILD_DIR)
	$(CC) $(CPPFLAGS) $(CFLAGS) $(COMMON_CFLAGS) -c $< -o $@

$(LIBRARY): $(OBJECTS)
	$(CC) $(CFLAGS) $(LDFLAGS) $(SHARED_FLAGS) -o $@ $(OBJECTS) $(OPENSSL_LIBS)

$(BUILD_DIR)/test_%: tests/test_%.c include/m7crypto.h $(LIBRARY)
	$(CC) $(CPPFLAGS) $(CFLAGS) $(COMMON_CFLAGS) $(LDFLAGS) -o $@ $< -L$(BUILD_DIR) -lm7crypto $(OPENSSL_LIBS) $(TEST_RPATH)

test: $(TESTS)
	$(BUILD_DIR)/test_pss
	$(BUILD_DIR)/test_families
	$(BUILD_DIR)/test_keygen
	$(BUILD_DIR)/test_keygen --no-provider
	$(BUILD_DIR)/test_encryption
	$(BUILD_DIR)/test_encryption --no-provider

sanitize:
	$(MAKE) BUILD_DIR=build/sanitize CFLAGS='-O1 -g -fno-omit-frame-pointer -fsanitize=address,undefined' test

install: $(LIBRARY)
	install -d "$(DESTDIR)$(LIBDIR)" "$(DESTDIR)$(INCLUDEDIR)"
	install -m 755 $(LIBRARY) "$(DESTDIR)$(LIBDIR)/"
	install -m 644 include/m7crypto.h "$(DESTDIR)$(INCLUDEDIR)/"

clean:
	rm -rf "$(BUILD_DIR)"
