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
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
VERSION := 0.2.0
SOVERSION := 1
CC ?= cc
AR ?= ar
CLANG_TIDY ?= clang-tidy
FORMAT ?= clang-format
PREFIX ?= /usr/local
LIBDIR ?= $(PREFIX)/lib
INCLUDEDIR ?= $(PREFIX)/include
BINDIR ?= $(PREFIX)/bin
FEATURES := -D_POSIX_C_SOURCE=200809L -D_XOPEN_SOURCE=700 -D_DEFAULT_SOURCE
WARNINGS := -Wall -Wextra -Wpedantic -Wshadow -Wstrict-prototypes \
-Wmissing-prototypes -Wold-style-definition -Wvla \
-Wpointer-arith -Wcast-qual -Wredundant-decls
SAN := -fsanitize=address,undefined -fno-omit-frame-pointer \
-fno-sanitize-recover=all
CPPFLAGS += -Iinclude -Isrc $(FEATURES)
CFLAGS ?= -O2 -g
CFLAGS += -std=c11 $(WARNINGS) $(EXTRA_CFLAGS)
LDFLAGS += $(EXTRA_LDFLAGS)
LDLIBS += -lcurl -lm
BUILD := build
LIB_SRC := src/client.c src/model.c src/util.c src/json.c src/csv.c
LIB_OBJ := $(LIB_SRC:%.c=$(BUILD)/%.o)
PIC_OBJ := $(LIB_SRC:%.c=$(BUILD)/%.pic.o)
TEST_SRC := tests/test_cepis.c tests/test_server.c
TEST_OBJ := $(TEST_SRC:%.c=$(BUILD)/%.o)
ALL_SRC := $(LIB_SRC) src/cli.c $(TEST_SRC)
ALL_HDR := include/cepis.h src/internal.h src/json.h src/csv.h \
tests/test_server.h
STATIC := $(BUILD)/libcepis.a
SHARED := $(BUILD)/libcepis.so.$(VERSION)
CLI := $(BUILD)/cepis
TESTS := $(BUILD)/test_cepis
.DEFAULT_GOAL := help
.PHONY: help build test lint format check clean memcheck sanitize install \
uninstall
help:
@echo 'Targets:'
@echo ' build static and shared libraries, plus the cepis CLI'
@echo ' test build and run the suite against a local HTTP server'
@echo ' lint clang-format --dry-run + clang-tidy (read-only)'
@echo ' format apply clang-format (writes)'
@echo ' check lint, then test, then build'
@echo ' memcheck run the suite under valgrind'
@echo ' sanitize rebuild and run the suite under ASan + UBSan'
@echo ' install install headers, libraries and the CLI under PREFIX'
@echo ' clean remove $(BUILD)/'
@echo
@echo 'Override the compiler with e.g. make test CC=clang'
build: $(STATIC) $(SHARED) $(CLI)
$(BUILD)/%.o: %.c
@mkdir -p $(dir $@)
$(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
$(BUILD)/%.pic.o: %.c
@mkdir -p $(dir $@)
$(CC) $(CPPFLAGS) $(CFLAGS) -fPIC -c $< -o $@
$(STATIC): $(LIB_OBJ)
@mkdir -p $(dir $@)
$(AR) rcs $@ $(LIB_OBJ)
$(SHARED): $(PIC_OBJ)
@mkdir -p $(dir $@)
$(CC) -shared -Wl,-soname,libcepis.so.$(SOVERSION) $(PIC_OBJ) \
$(LDFLAGS) $(LDLIBS) -o $@
ln -sf libcepis.so.$(VERSION) $(BUILD)/libcepis.so.$(SOVERSION)
ln -sf libcepis.so.$(VERSION) $(BUILD)/libcepis.so
$(CLI): $(BUILD)/src/cli.o $(STATIC)
$(CC) $(BUILD)/src/cli.o $(STATIC) $(LDFLAGS) $(LDLIBS) -o $@
$(TESTS): $(TEST_OBJ) $(STATIC)
$(CC) $(TEST_OBJ) $(STATIC) $(LDFLAGS) $(LDLIBS) -lpthread -o $@
test: $(TESTS)
$(TESTS)
# 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:
$(FORMAT) --dry-run --Werror $(ALL_SRC) $(ALL_HDR)
$(CLANG_TIDY) --quiet $(ALL_SRC) -- $(CPPFLAGS) -std=c11
format:
$(FORMAT) -i $(ALL_SRC) $(ALL_HDR)
# 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
memcheck: $(TESTS)
valgrind --error-exitcode=9 --leak-check=full --show-leak-kinds=definite,indirect \
--errors-for-leak-kinds=definite,indirect --track-origins=yes $(TESTS)
# Rebuilt from scratch: the sanitizers change the ABI of the objects, so they
# must not be mixed with objects from an ordinary build.
sanitize:
$(MAKE) clean
$(MAKE) test EXTRA_CFLAGS='$(SAN)' EXTRA_LDFLAGS='$(SAN)'
$(MAKE) clean
install: build
install -d $(DESTDIR)$(INCLUDEDIR) $(DESTDIR)$(LIBDIR) $(DESTDIR)$(BINDIR)
install -m 644 include/cepis.h $(DESTDIR)$(INCLUDEDIR)/
install -m 644 $(STATIC) $(DESTDIR)$(LIBDIR)/
install -m 755 $(SHARED) $(DESTDIR)$(LIBDIR)/
ln -sf libcepis.so.$(VERSION) $(DESTDIR)$(LIBDIR)/libcepis.so.$(SOVERSION)
ln -sf libcepis.so.$(VERSION) $(DESTDIR)$(LIBDIR)/libcepis.so
install -m 755 $(CLI) $(DESTDIR)$(BINDIR)/
uninstall:
rm -f $(DESTDIR)$(INCLUDEDIR)/cepis.h
rm -f $(DESTDIR)$(LIBDIR)/libcepis.a
rm -f $(DESTDIR)$(LIBDIR)/libcepis.so*
rm -f $(DESTDIR)$(BINDIR)/cepis
clean:
rm -rf $(BUILD)
|