123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272 |
- # NOTE: only tested in GNU/Linux.
- ## Binary dependencies.
- CC = gcc
- AR = ar
- ## Paths.
- PREFIX ?= /usr/local
- bindir ::= $(PREFIX)/bin
- libdir ::= $(PREFIX)/lib
- includedir = $(PREFIX)/include/lsup
- MDB_DIR = ext/openldap/libraries/liblmdb
- XXHASH_DIR = ext/xxHash
- VALGRIND_DUMP = /tmp/lsup_valgrind.log
- CALLGRIND_DUMP = /tmp/lsup_callgrind.out
- MASSIF_DUMP = /tmp/lsup_massif.out
- INCLUDE_BASE ::= . -Iinclude -I$(MDB_DIR) -I$(XXHASH_DIR) \
- -Iext/tpl/src -Iext/hashmap -Iext/log/src
- INCLUDE ::= -I$(INCLUDE_BASE)
- _CFLAGS ::= -std=gnu11 -Wall -fPIC -MMD $(INCLUDE)
- CFLAGS = $(_CFLAGS) -O3
- DBG_CFLAGS = $(_CFLAGS) -Itest -O0 -g3 -DDEBUG
- # NOTE: -luuid is a Linux system library. Other OS's might need a different
- # link or a non-system library built.
- LDFLAGS ::= -L. -L$(libdir) -llmdb -lxxhash -luuid
- PARSER = bin/lemon
- LEMON_SRC = ext/sqlite/tool/lemon.c
- CODEC_DIR = src/codec
- # External sources compiled in core object.
- EXT_SRC ::= $(wildcard ext/log/src/*.c) \
- $(wildcard ext/hashmap/*.c) \
- $(wildcard ext/tpl/src/*.c)
- # External headers of libraries compiled in core.
- EXT_H ::= $(wildcard ext/log/src/*.h) \
- $(wildcard ext/tpl/src/*.h) \
- $(wildcard ext/hashmap/*.h)
- LSUP_SRC = $(wildcard src/*.c)
- SRC = $(EXT_SRC) $(LSUP_SRC)
- TEST_SRC = $(wildcard test/*.c) test.c
- EXT_OBJ ::= $(EXT_SRC:.c=.o)
- # TODO This is extremely convoluted, simplify if possible.
- CODEC_SRC ::= $(wildcard $(CODEC_DIR)/codec_*.c)
- CODEC_REL_SRC ::= $(CODEC_SRC:$(CODEC_DIR)/%=%)
- ALL_CODEC_REL_SRC ::= $(CODEC_REL_SRC) $(CODEC_REL_SRC:codec_%=parser_%) \
- $(CODEC_REL_SRC:codec_%=grammar_%)
- CODEC_SRC = $(ALL_CODEC_REL_SRC:%=$(CODEC_DIR)/%)
- CODEC_OBJ = $(CODEC_SRC:.c=.o)
- CODEC_DBG_OBJ = $(CODEC_SRC:.c=_dbg.o)
- OBJ = $(EXT_OBJ) $(LSUP_SRC:.c=.o)
- DBG_OBJ = $(EXT_OBJ) $(LSUP_SRC:.c=_dbg.o)
- DEPLIBS = libxxhash liblmdb
- LIBS = liblsuprdf.a liblsuprdf.so
- DBG_LIBS = liblsuprdf_dbg.a liblsuprdf_dbg.so
- # For visual dep graph.
- DEPS := $(shell echo "${INCLUDE_BASE}" | sed -e 's/ -I/,/g'),include/codec
- DOCS = docs
- ## Environment.
- # Tests need the freshly compiled libs.
- export LD_LIBRARY_PATH = .:$(libdir)
- ## Rules.
- .DEFAULT_GOAL := lib
- # Extract all rule comments into a help message.
- .PHONY: help
- help:
- @echo "Command overview:"; echo; \
- grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) \
- | sed -n 's/^\(.*\): \(.*\)##\(.*\)/\1|\3/p' \
- | column -t -s '|'
-
- lib: $(DEPLIBS) codec $(LIBS) ## Compile main library (static and dynamic linking).
- debug: $(DEPLIBS) codec_dbg $(DBG_LIBS) ## Compile main library with debug symbols.
- # Static library.
- liblsuprdf.a: $(OBJ)
- $(AR) rs $@ $^ $(CODEC_OBJ)
- # Dynamic library.
- liblsuprdf.so: $(OBJ)
- $(CC) -shared $(LDFLAGS) -o $@ $^ $(CODEC_OBJ)
- # Static debug library.
- liblsuprdf_dbg.a: $(DBG_OBJ)
- $(AR) rs $@ $^ $(CODEC_DBG_OBJ)
- # Dynamic debug library.
- liblsuprdf_dbg.so: $(DBG_OBJ)
- $(CC) -shared $(LDFLAGS) -o $@ $^ $(CODEC_DBG_OBJ)
- # Debug objects.
- %_dbg.o: %.c
- $(CC) $(DBG_CFLAGS) -c $^ -o $@
- # Codecs in a subfolder.
- .PHONY: codec
- codec: $(PARSER)
- $(MAKE) -C $(CODEC_DIR) codec
- .PHONY: codec_dbg
- codec_dbg: $(PARSER)
- $(MAKE) -C $(CODEC_DIR) debug
- # Build the parser executable.
- $(PARSER): $(LEMON_SRC)
- $(CC) $^ -o $@
- # Ext libraries.
- .PHONY: libxxhash
- libxxhash:
- $(MAKE) -C $(XXHASH_DIR)
- .PHONY: liblmdb
- liblmdb:
- $(MAKE) -C $(MDB_DIR)
- install: lib ## Install library and dependencies to $PREFIX. May require sudo.
- @echo "Installing library files in $(PREFIX)."
- cd $(MDB_DIR); PREFIX=$(PREFIX) make install
- cd $(XXHASH_DIR); PREFIX=$(PREFIX) make install
- mkdir -p $(DESTDIR)$(libdir)
- mkdir -p $(DESTDIR)$(includedir)
- cp liblsuprdf.{a,so} $(DESTDIR)$(libdir) && \
- cp include/*.h $(EXT_H) $(DESTDIR)$(includedir)
- debug_install: install debug ## Install standard and debug libraries.
- @echo "Installing debug library files in $(PREFIX)."
- cp liblsuprdf_dbg.{a,so} $(DESTDIR)$(libdir)
-
- .PHONY: clean ## Clean up artifacts, including language parsers.
- clean:
- rm -f src/*.[aod] ./*.[aod] src/codec/*.[aod] src/codec/*.out
- rm -rf build/ dist/ lsup_rdf.egg-info/
- rm -f *.so
- rm -f include/codec/grammar_*.h
- rm -f src/codec/{grammar,parser}_*.c
- .PHONY: deepclean ## Clean up external libraries.
- deepclean: clean
- cd $(MDB_DIR); make clean
- cd $(XXHASH_DIR); make clean
- .PHONY: uninstall ## Uninstall library (not the dependencies).
- uninstall:
- rm -f $(DESTDIR)$(libdir)/liblsuprdf*
- rm -rf $(DESTDIR)$(includedir)
- rm -f bin/test*
- # For testing, use debug symbols.
- bin/test: debug $(TEST_SRC)
- $(CC) $(DBG_CFLAGS) $(LDFLAGS) -llsuprdf_dbg \
- test.c -o bin/test
- .PHONY: test
- test: bin/test ## Run a test suite.
- @echo "Using libraries: "; ldd bin/test
- exec bin/test
- .PHONY: gdb_test
- gdb_test: bin/test ## Run a test suite within gdb.
- @echo "Using libraries: "; ldd bin/test
- exec gdb bin/test
- lint:
- splint \
- $(INCLUDE) -Itest \
- -DUINT_MAX=0xFFFFFFFFUL \
- -nullpass \
- -posix-lib \
- test.c
- .PHONY: memcheck
- memcheck:
- valgrind \
- --leak-check=full --show-leak-kinds=all --track-origins=yes \
- --log-file=$(VALGRIND_DUMP) \
- ./bin/test
- @echo "Memcheck complete. Valgrind log is at $(VALGRIND_DUMP)"
- memtest: bin/test memcheck ## Run a test suite using Valgrind. Output to separate file.
- # Performance test application. Essentially the profiling code without debug.
- bin/profile: debug profile.c
- $(CC) $(CFLAGS) -g -DTESTING $(LDFLAGS) -llsuprdf_dbg \
- profile.c -o bin/profile
- # Performance test application. Essentially the profiling code without debug.
- bin/perftest: lib profile.c
- $(CC) $(CFLAGS) -g $(LDFLAGS) -llsuprdf profile.c -o bin/perftest
- .PHONY: perftest
- perftest: bin/perftest ## Run a performance test by creating, inserting and looking up triples.
- bin/perftest
- .PHONY: profile
- profile: bin/profile ## Run a profiling session. Output can be inspected with KCachegrind.
- LSUP_MDB_MAPSIZE=800000 valgrind --tool=callgrind \
- --callgrind-out-file="$(CALLGRIND_DUMP)" bin/perftest 1000
- @echo "Profile dump written at $(CALLGRIND_DUMP). Open it with "\
- "qcachegrind, kcachegrind, etc."
- .PHONY: footprint
- footprint: bin/perftest ## Measure memory footprint by generating and storing 100K triples.
- LSUP_MDB_MAPSIZE=80000000 valgrind --tool=massif \
- --massif-out-file=$(MASSIF_DUMP) bin/perftest 100000
- @echo "Memory stats file written at $(MASSIF_DUMP). Open it with "\
- "massif-visualizer or similar."
- .PHONY: py_module
- py_module: codec
- pip3 install build==0.8.0
- pip3 uninstall -y lsup_rdf
- python3 -m build
- pip3 install --no-index --find-links=dist/ lsup_rdf
- .PHONY: pytest
- pytest: py_module ## Run a test suite for the Python package.
- python3 test/cpython_test.py
- # Requires cinclude2dot (https://www.flourish.org/cinclude2dot) and Graphviz.
- depgraph: $(LSUP_SRC) $(CODEC_SRC) include/* include/codec/* ## Build a visual dependency graph of the code.
- cinclude2dot --merge=module --include=$(DEPS) \
- --exclude='test|ext' >| $(DOCS)/dev/deps.dot
- dot $(DOCS)/dev/deps.dot -Tpdf >| $(DOCS)/dev/deps.pdf
|