summaryrefslogtreecommitdiffstats
path: root/Makefile
blob: ca4d3d48e596019ee5df743dc8c81bf33192986d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# Development tasks. Plain g++/clang++ rules, no generator step: the library is
# five translation units and one external dependency.
#
#   make            list the targets
#   make test       build and run the suite
#   make lint       clang-format --dry-run + clang-tidy, no files touched
#   make build      libcepis.a and the example CLI into build/
#
# Override the compiler or the standard with e.g. `make CXX=clang++ STD=c++20`.

CXX ?= g++
AR ?= ar
STD ?= c++17
BUILD_DIR ?= build

CURL_CFLAGS := $(shell pkg-config --cflags libcurl 2>/dev/null)
CURL_LIBS := $(shell pkg-config --libs libcurl 2>/dev/null || echo -lcurl)

WARNINGS := -Wall -Wextra
CXXFLAGS ?= -O2 -g
ALL_CXXFLAGS := -std=$(STD) $(WARNINGS) $(CXXFLAGS) -Iinclude -Isrc $(CURL_CFLAGS)
LDLIBS := $(CURL_LIBS) -lpthread

LIB_SOURCES := src/client.cpp src/csv.cpp src/http.cpp src/json.cpp src/models.cpp
TEST_SOURCES := tests/test_cepis.cpp tests/test_main.cpp tests/test_server.cpp
EXAMPLE_SOURCES := examples/cepis_lookup.cpp

LIB_OBJECTS := $(LIB_SOURCES:%.cpp=$(BUILD_DIR)/%.o)
TEST_OBJECTS := $(TEST_SOURCES:%.cpp=$(BUILD_DIR)/%.o)
EXAMPLE_OBJECTS := $(EXAMPLE_SOURCES:%.cpp=$(BUILD_DIR)/%.o)

LIBRARY := $(BUILD_DIR)/libcepis.a
TEST_BINARY := $(BUILD_DIR)/cepis-tests
EXAMPLE_BINARY := $(BUILD_DIR)/cepis-lookup

SOURCES := $(LIB_SOURCES) $(TEST_SOURCES) $(EXAMPLE_SOURCES)
HEADERS := $(wildcard include/cepis/*.hpp) $(wildcard src/*.hpp) $(wildcard tests/*.hpp)

.DEFAULT_GOAL := help
.PHONY: help test lint format build check clean

help:
	@echo 'Targets:'
	@echo '  test       build and run the test suite'
	@echo '  lint       clang-format --dry-run + clang-tidy (read-only)'
	@echo '  format     apply clang-format (writes)'
	@echo '  build      libcepis.a and the example CLI into $(BUILD_DIR)/'
	@echo '  check      lint + test + build, in that order'
	@echo '  clean      remove $(BUILD_DIR)/'
	@echo
	@echo 'Override the compiler or standard with e.g. make test CXX=clang++ STD=c++20'

$(BUILD_DIR)/%.o: %.cpp $(HEADERS)
	@mkdir -p $(dir $@)
	$(CXX) $(ALL_CXXFLAGS) -c $< -o $@

$(LIBRARY): $(LIB_OBJECTS)
	@mkdir -p $(dir $@)
	$(AR) rcs $@ $^

$(TEST_BINARY): $(TEST_OBJECTS) $(LIBRARY)
	$(CXX) $(ALL_CXXFLAGS) $(TEST_OBJECTS) $(LIBRARY) $(LDLIBS) -o $@

$(EXAMPLE_BINARY): $(EXAMPLE_OBJECTS) $(LIBRARY)
	$(CXX) $(ALL_CXXFLAGS) $(EXAMPLE_OBJECTS) $(LIBRARY) $(LDLIBS) -o $@

build: $(LIBRARY) $(EXAMPLE_BINARY)

test: $(TEST_BINARY)
	$(TEST_BINARY)

# Read-only by design, so it is safe in CI and in a pre-commit hook: it reports
# what `make format` would change without changing anything.
lint:
	clang-format --dry-run --Werror $(SOURCES) $(HEADERS)
	clang-tidy --quiet $(SOURCES) -- $(ALL_CXXFLAGS)

format:
	clang-format -i $(SOURCES) $(HEADERS)

# The order matters: lint is the fastest to fail, build the slowest, so a broken
# run reports the cheapest problem first.
check: lint test build

clean:
	rm -rf $(BUILD_DIR)