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
131
132
133
134
135
136
137
138
139
140
|
VERSION := 0.1.0
ifeq ($(origin FC),default)
FC := gfortran
endif
FC ?= gfortran
CC ?= cc
AR ?= ar
FPRETTIFY ?= fprettify
PREFIX ?= /usr/local
LIBDIR ?= $(PREFIX)/lib
INCLUDEDIR ?= $(PREFIX)/include/cepis
BINDIR ?= $(PREFIX)/bin
BUILD := 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 -Wno-unused-dummy-argument
SAN := -fsanitize=address,undefined -fno-omit-frame-pointer
FFLAGS ?= -O2 -g
FFLAGS += -std=f2018 -fimplicit-none -J$(BUILD) -I$(BUILD) $(WARNINGS) $(EXTRA_FFLAGS)
CFLAGS ?= -O2 -g
CFLAGS += -std=c11 -D_POSIX_C_SOURCE=200809L -Wall -Wextra $(EXTRA_CFLAGS)
LDFLAGS += $(EXTRA_LDFLAGS)
LDLIBS += $(CURL_LIBS)
LIB_SRC := src/cepis_errors.f90 src/cepis_strings.f90 src/cepis_json.f90 \
src/cepis_csv.f90 src/cepis_http.f90 src/cepis_models.f90 \
src/cepis.f90
LIB_OBJ := $(LIB_SRC:%.f90=$(BUILD)/%.o)
LIB_MOD := $(BUILD)/cepis.mod $(BUILD)/cepis_errors.mod \
$(BUILD)/cepis_strings.mod $(BUILD)/cepis_json.mod \
$(BUILD)/cepis_csv.mod $(BUILD)/cepis_http.mod \
$(BUILD)/cepis_models.mod
ALL_F90 := $(LIB_SRC) test/test_server.f90 app/main.f90 test/test_cepis.f90
STATIC := $(BUILD)/libcepis.a
CLI := $(BUILD)/cepis
TESTS := $(BUILD)/test_cepis
.DEFAULT_GOAL := help
.PHONY: help build test lint format check sanitize clean install uninstall
help:
@echo 'Targets:'
@echo ' build static library, modules and the cepis CLI'
@echo ' test build and run the suite against a local HTTP server'
@echo ' lint strict warning-free rebuild + fprettify --diff (read-only)'
@echo ' format apply fprettify (writes)'
@echo ' check lint, then test, then build'
@echo ' sanitize rebuild and run the suite under ASan + UBSan'
@echo ' install install modules, the library and the CLI under PREFIX'
@echo ' clean remove $(BUILD)/'
@echo
@echo 'Requires gfortran (or another Fortran 2018 compiler), a C compiler'
@echo 'and libcurl with its development headers.'
@echo 'Override the compiler with e.g. make test FC=flang'
build: $(STATIC) $(CLI)
$(BUILD)/%.o: %.f90
@mkdir -p $(dir $@) $(BUILD)
$(FC) $(FFLAGS) -c $< -o $@
$(BUILD)/%.o: %.c
@mkdir -p $(dir $@)
$(CC) $(CFLAGS) $(CURL_CFLAGS) -c $< -o $@
$(BUILD)/src/cepis_json.o: $(BUILD)/src/cepis_strings.o
$(BUILD)/src/cepis_csv.o: $(BUILD)/src/cepis_strings.o
$(BUILD)/src/cepis_http.o: $(BUILD)/src/cepis_strings.o
$(BUILD)/src/cepis_models.o: $(BUILD)/src/cepis_json.o $(BUILD)/src/cepis_strings.o
$(BUILD)/src/cepis.o: $(BUILD)/src/cepis_errors.o $(BUILD)/src/cepis_strings.o \
$(BUILD)/src/cepis_json.o $(BUILD)/src/cepis_csv.o \
$(BUILD)/src/cepis_http.o $(BUILD)/src/cepis_models.o
$(BUILD)/app/main.o: $(BUILD)/src/cepis.o
$(BUILD)/test/test_server.o: $(BUILD)/src/cepis_strings.o
$(BUILD)/test/test_cepis.o: $(BUILD)/src/cepis.o $(BUILD)/test/test_server.o
$(STATIC): $(LIB_OBJ)
@mkdir -p $(dir $@)
$(AR) rcs $@ $(LIB_OBJ)
$(CLI): $(BUILD)/app/main.o $(STATIC)
$(FC) $(FFLAGS) $(BUILD)/app/main.o $(STATIC) $(LDFLAGS) $(LDLIBS) -o $@
$(TESTS): $(BUILD)/test/test_cepis.o $(BUILD)/test/test_server.o \
$(BUILD)/test/http_server.o $(STATIC)
$(FC) $(FFLAGS) $(BUILD)/test/test_cepis.o $(BUILD)/test/test_server.o \
$(BUILD)/test/http_server.o $(STATIC) $(LDFLAGS) $(LDLIBS) -lpthread -o $@
test: $(TESTS)
$(TESTS)
# Read-only by design, so it is safe in CI and in a pre-commit hook. The
# rebuild turns every warning into an error without touching the ordinary
# build tree; fprettify only reports, and is skipped when it is not installed.
lint:
@rm -rf $(BUILD)/lint
@mkdir -p $(BUILD)/lint
$(FC) -std=f2018 -fimplicit-none $(WARNINGS) -Werror -fsyntax-only \
-J$(BUILD)/lint -I$(BUILD)/lint $(ALL_F90)
$(CC) $(CFLAGS) $(CURL_CFLAGS) -Werror -fsyntax-only test/http_server.c
@if command -v $(FPRETTIFY) >/dev/null 2>&1; then \
$(FPRETTIFY) --diff --indent 4 --line-length 100 $(ALL_F90); \
else \
echo 'fprettify not installed: skipping style check'; \
fi
format:
$(FPRETTIFY) --indent 4 --line-length 100 $(ALL_F90)
# 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
# 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_FFLAGS='$(SAN) -fcheck=all' EXTRA_CFLAGS='$(SAN)' \
EXTRA_LDFLAGS='$(SAN)'
$(MAKE) clean
install: build
install -d $(DESTDIR)$(INCLUDEDIR) $(DESTDIR)$(LIBDIR) $(DESTDIR)$(BINDIR)
install -m 644 $(LIB_MOD) $(DESTDIR)$(INCLUDEDIR)/
install -m 644 $(STATIC) $(DESTDIR)$(LIBDIR)/
install -m 755 $(CLI) $(DESTDIR)$(BINDIR)/
uninstall:
rm -rf $(DESTDIR)$(INCLUDEDIR)
rm -f $(DESTDIR)$(LIBDIR)/libcepis.a
rm -f $(DESTDIR)$(BINDIR)/cepis
clean:
rm -rf $(BUILD)
|