VERSION := 0.2.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)