BUILD_DIR ?= build DEPS_DIR ?= $(BUILD_DIR)/deps TEST_DIR ?= tests INCLUDE_DIR := include MODE ?= debug RELEASE_OPT ?= 3 CLINE_SIZE ?= 64 CXX ?= clang++ AR ?= ar ARFLAGS := rcs TESTS := $(shell find $(TEST_DIR) -name '*.cc') TEST_BINS := $(patsubst $(TEST_DIR)/%.cc,$(BUILD_DIR)/tests/%,$(TESTS)) TEST_DEPS := $(patsubst $(TEST_DIR)/%.cc,$(DEPS_DIR)/tests/%.d,$(TESTS)) INCLUDES := $(addprefix -I,$(INCLUDE_DIR)) WARN_FLAGS := \ -Wall \ -Wextra \ -Wpedantic \ -Werror COMMON_CXXFLAGS := \ -std=c++20 \ -flto \ --param=destructive-interference-size=$(CLINE_SIZE) \ $(WARN_FLAGS) \ $(INCLUDES) DEBUG_CXXFLAGS := \ -O0 \ -g \ -fsanitize=thread \ -fno-omit-frame-pointer RELEASE_CXXFLAGS := \ -O$(RELEASE_OPT) \ -DNDEBUG ifeq ($(MODE),debug) CXXFLAGS := $(COMMON_CXXFLAGS) $(DEBUG_CXXFLAGS) else ifeq ($(MODE),release) CXXFLAGS := $(COMMON_CXXFLAGS) $(RELEASE_CXXFLAGS) else $(error Unknown MODE '$(MODE)'; use MODE=debug or MODE=release) endif .PHONY: all clean tests all: tests tests: $(TEST_BINS) $(BUILD_DIR)/tests/%: $(TEST_DIR)/%.cc @mkdir -p $(dir $@) @mkdir -p $(DEPS_DIR)/tests/$(dir $*) $(CXX) $(CXXFLAGS) -MMD -MP -MF $(DEPS_DIR)/tests/$*.d $< -o $@ clean: rm -rf $(BUILD_DIR) -include $(TEST_DEPS)