1# SPDX-License-Identifier: ISC
2#
3# Copyright (C) 2017-2021 Michael Drake <tlsa@netsurf-browser.org>
4
5# CYAML's versioning is <MAJOR>.<MINOR>.<PATCH>[-DEVEL]
6# Master branch will always be DEVEL.  The release process will be to make
7# the release branch, set VESION_DEVEL to 0, and tag the release.
8VERSION_MAJOR = 1
9VERSION_MINOR = 3
10VERSION_PATCH = 0
11VERSION_DEVEL = 0
12VERSION_STR = $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH)
13
14# Default variant depends on whether it's a development build.
15ifeq ($(VERSION_DEVEL), 1)
16	VARIANT = debug
17else
18	VARIANT = release
19endif
20
21# Unfortunately ASan is incompatible with valgrind, so we have a special
22# variant for running with sanitisers.
23VALID_VARIANTS := release debug san
24ifneq ($(filter $(VARIANT),$(VALID_VARIANTS)),)
25else
26$(error VARIANT must be 'debug' (default), 'san', or 'release')
27endif
28
29UNAME_S := $(shell uname -s)
30
31LIB_NAME = libcyaml
32LIB_PKGCON = $(LIB_NAME).pc
33LIB_STATIC = $(LIB_NAME).a
34LIB_SHARED = $(LIB_NAME).so
35LIB_SH_MAJ = $(LIB_SHARED).$(VERSION_MAJOR)
36LIB_SH_VER = $(LIB_SHARED).$(VERSION_STR)
37
38.IMPLICIT =
39
40PREFIX ?= /usr/local
41LIBDIR ?= lib
42INCLUDEDIR ?= include
43
44Q ?= @
45
46CC ?= gcc
47AR ?= ar
48MKDIR =	mkdir -p
49INSTALL ?= install -c
50VALGRIND = valgrind --leak-check=full --track-origins=yes
51
52VERSION_FLAGS = -DVERSION_MAJOR=$(VERSION_MAJOR) \
53                -DVERSION_MINOR=$(VERSION_MINOR) \
54                -DVERSION_PATCH=$(VERSION_PATCH) \
55                -DVERSION_DEVEL=$(VERSION_DEVEL)
56
57LIBYAML = yaml-0.1
58LIBYAML_CFLAGS := $(if $(PKG_CONFIG),$(shell $(PKG_CONFIG) --cflags $(LIBYAML)),)
59LIBYAML_LIBS := $(if $(PKG_CONFIG),$(shell $(PKG_CONFIG) --libs $(LIBYAML)),-lyaml)
60
61INCLUDE = -I include
62CPPFLAGS += $(VERSION_FLAGS) -MMD -MP
63CFLAGS += $(INCLUDE) $(LIBYAML_CFLAGS)
64CFLAGS += -std=c11 -Wall -Wextra -pedantic \
65		-Wconversion -Wwrite-strings -Wcast-align -Wpointer-arith \
66		-Winit-self -Wshadow -Wstrict-prototypes -Wmissing-prototypes \
67		-Wredundant-decls -Wundef -Wvla -Wdeclaration-after-statement
68LDFLAGS += $(LIBYAML_LIBS)
69LDFLAGS_SHARED = -Wl,-soname=$(LIB_SH_MAJ) -shared
70
71ifeq ($(VARIANT), debug)
72	CFLAGS += -O0 -g
73else ifeq ($(VARIANT), san)
74	CFLAGS += -O0 -g -fsanitize=address -fsanitize=undefined -fno-sanitize-recover
75	LDFLAGS += -fsanitize=address -fsanitize=undefined -fno-sanitize-recover
76else
77	CFLAGS += -O2 -DNDEBUG
78endif
79
80ifneq ($(filter coverage,$(MAKECMDGOALS)),)
81	BUILDDIR = build/coverage/$(VARIANT)
82	CFLAGS_COV = --coverage -DNDEBUG
83	LDFLAGS_COV = --coverage
84else
85	BUILDDIR = build/$(VARIANT)
86	CFLAGS_COV =
87	LDFLAGS_COV =
88endif
89
90BUILDDIR_SHARED = $(BUILDDIR)/shared
91BUILDDIR_STATIC = $(BUILDDIR)/static
92
93LIB_SRC_FILES = mem.c free.c load.c save.c util.c utf8.c
94LIB_SRC := $(addprefix src/,$(LIB_SRC_FILES))
95LIB_OBJ = $(patsubst %.c,%.o, $(addprefix $(BUILDDIR)/,$(LIB_SRC)))
96LIB_DEP = $(patsubst %.c,%.d, $(addprefix $(BUILDDIR)/,$(LIB_SRC)))
97LIB_OBJ_SHARED = $(patsubst $(BUILDDIR)%,$(BUILDDIR_SHARED)%,$(LIB_OBJ))
98LIB_OBJ_STATIC = $(patsubst $(BUILDDIR)%,$(BUILDDIR_STATIC)%,$(LIB_OBJ))
99LIB_DEP_SHARED = $(patsubst $(BUILDDIR)%,$(BUILDDIR_SHARED)%,$(LIB_DEP))
100LIB_DEP_STATIC = $(patsubst $(BUILDDIR)%,$(BUILDDIR_STATIC)%,$(LIB_DEP))
101
102LIB_PATH = LD_LIBRARY_PATH=$(BUILDDIR)
103
104ifeq ($(UNAME_S),Darwin)
105	LIB_SHARED = $(LIB_NAME).dylib
106	LIB_SH_MAJ = $(LIB_NAME).$(VERSION_MAJOR).dylib
107	LIB_SH_VER = $(LIB_NAME).$(VERSION_STR).dylib
108	LDFLAGS_SHARED = -dynamiclib -install_name "$(LIB_SH_MAJ)" -current_version $(VERSION_STR)
109	LIB_PATH = DYLD_FALLBACK_LIBRARY_PATH=$(BUILDDIR)
110endif
111
112TEST_SRC_FILES = units/free.c units/load.c units/test.c units/util.c \
113		units/errs.c units/file.c units/save.c units/utf8.c
114TEST_SRC := $(addprefix test/,$(TEST_SRC_FILES))
115TEST_OBJ = $(patsubst %.c,%.o, $(addprefix $(BUILDDIR)/,$(TEST_SRC)))
116TEST_DEP = $(patsubst %.c,%.d, $(addprefix $(BUILDDIR)/,$(TEST_SRC)))
117
118TEST_BINS = \
119		$(BUILDDIR)/test/units/cyaml-shared \
120		$(BUILDDIR)/test/units/cyaml-static
121
122all: $(BUILDDIR)/$(LIB_SH_MAJ) $(BUILDDIR)/$(LIB_STATIC) examples
123
124coverage: test-verbose
125	$(Q)$(MKDIR) $(BUILDDIR)
126	$(Q)gcovr -e 'test/.*' -r .
127	$(Q)gcovr -e 'test/.*' -x -o build/coverage.xml -r .
128	$(Q)gcovr -e 'test/.*' --html --html-details -o build/coverage.html -r .
129
130test test-quiet test-verbose test-debug: $(TEST_BINS)
131	$(Q)for i in $(^); do $(LIB_PATH) $$i $(subst test,,$(subst test-,--,$@)) "$(TESTLIST)" || exit; done
132
133valgrind valgrind-quiet valgrind-verbose valgrind-debug: $(TEST_BINS)
134	$(Q)for i in $(^); do $(LIB_PATH) $(VALGRIND) $$i $(subst valgrind,,$(subst valgrind-,--,$@)) "$(TESTLIST)" || exit; done
135
136check: test
137
138$(BUILDDIR)/$(LIB_PKGCON): $(LIB_PKGCON).in
139	sed \
140		-e 's#PREFIX#$(PREFIX)#' \
141		-e 's#LIBDIR#$(LIBDIR)#' \
142		-e 's#INCLUDEDIR#$(INCLUDEDIR)#' \
143		-e 's#VERSION#$(VERSION_STR)#' \
144		$(LIB_PKGCON).in >$(BUILDDIR)/$(LIB_PKGCON)
145
146$(BUILDDIR)/$(LIB_STATIC): $(LIB_OBJ_STATIC)
147	$(AR) -rcs $@ $^
148
149$(BUILDDIR)/$(LIB_SH_MAJ): $(LIB_OBJ_SHARED)
150	$(CC) -o $@ $^ $(LDFLAGS) $(LDFLAGS_COV) $(LDFLAGS_SHARED)
151
152$(LIB_OBJ_STATIC): $(BUILDDIR_STATIC)/%.o : %.c
153	$(Q)$(MKDIR) $(dir $@)
154	$(CC) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_COV) -c -o $@ $<
155
156$(LIB_OBJ_SHARED): $(BUILDDIR_SHARED)/%.o : %.c
157	$(Q)$(MKDIR) $(dir $@)
158	$(CC) $(CPPFLAGS) $(CFLAGS) -fPIC $(CFLAGS_COV) -c -o $@ $<
159
160docs:
161	$(MKDIR) build/docs/api
162	$(MKDIR) build/docs/devel
163	doxygen docs/api.doxygen.conf
164	doxygen docs/devel.doxygen.conf
165
166clean:
167	rm -rf build/
168
169install: $(BUILDDIR)/$(LIB_SH_MAJ) $(BUILDDIR)/$(LIB_STATIC) $(BUILDDIR)/$(LIB_PKGCON)
170	$(INSTALL) -d $(DESTDIR)$(PREFIX)/$(LIBDIR)
171	$(INSTALL) $(BUILDDIR)/$(LIB_SH_MAJ) $(DESTDIR)$(PREFIX)/$(LIBDIR)/$(LIB_SH_VER)
172	(cd $(DESTDIR)$(PREFIX)/$(LIBDIR) && { ln -s -f $(LIB_SH_VER) $(LIB_SH_MAJ) || { rm -f $(LIB_SH_MAJ) && ln -s $(LIB_SH_VER) $(LIB_SH_MAJ); }; })
173	(cd $(DESTDIR)$(PREFIX)/$(LIBDIR) && { ln -s -f $(LIB_SH_VER) $(LIB_SHARED) || { rm -f $(LIB_SHARED) && ln -s $(LIB_SH_VER) $(LIB_SHARED); }; })
174	$(INSTALL) $(BUILDDIR)/$(LIB_STATIC) $(DESTDIR)$(PREFIX)/$(LIBDIR)/$(LIB_STATIC)
175	chmod 644 $(DESTDIR)$(PREFIX)/$(LIBDIR)/$(LIB_STATIC)
176	$(INSTALL) -d $(DESTDIR)$(PREFIX)/$(INCLUDEDIR)/cyaml
177	$(INSTALL) -m 644 include/cyaml/* $(DESTDIR)$(PREFIX)/$(INCLUDEDIR)/cyaml
178	$(INSTALL) -d $(DESTDIR)$(PREFIX)/$(LIBDIR)/pkgconfig
179	$(INSTALL) -m 644 $(BUILDDIR)/$(LIB_PKGCON) $(DESTDIR)$(PREFIX)/$(LIBDIR)/pkgconfig/$(LIB_PKGCON)
180
181examples: $(BUILDDIR)/planner $(BUILDDIR)/numerical
182
183$(BUILDDIR)/planner: examples/planner/main.c $(BUILDDIR)/$(LIB_STATIC)
184	$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $^ $(LDFLAGS)
185
186$(BUILDDIR)/numerical: examples/numerical/main.c $(BUILDDIR)/$(LIB_STATIC)
187	$(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $^ $(LDFLAGS)
188
189-include $(LIB_DEP_SHARED) $(LIB_DEP_STATIC) $(TEST_DEP)
190
191.PHONY: all test test-quiet test-verbose test-debug \
192		valgrind valgrind-quiet valgrind-verbose valgrind-debug \
193		clean coverage docs install examples check
194
195$(BUILDDIR)/test/units/cyaml-static: $(TEST_OBJ) $(BUILDDIR)/$(LIB_STATIC)
196	$(CC) $(LDFLAGS_COV) -o $@ $^ $(LDFLAGS)
197
198$(BUILDDIR)/test/units/cyaml-shared: $(TEST_OBJ) $(BUILDDIR)/$(LIB_SH_MAJ)
199	$(CC) $(LDFLAGS_COV) -o $@ $^ $(LDFLAGS)
200
201$(TEST_OBJ): $(BUILDDIR)/%.o : %.c
202	$(Q)$(MKDIR) $(dir $@)
203	$(CC) $(CPPFLAGS) $(CFLAGS) $(CFLAGS_COV) -c -o $@ $<
204