Makefile 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  1. # NOTE: only tested in GNU/Linux.
  2. ## Binary dependencies.
  3. CC = gcc
  4. AR = ar
  5. ## Paths.
  6. PREFIX ?= /usr/local
  7. bindir := $(PREFIX)/bin
  8. libdir := $(PREFIX)/lib
  9. includedir = $(PREFIX)/include/lsup
  10. outdir = ./bin
  11. VALGRIND_DUMP = /tmp/lsup_valgrind.log
  12. CALLGRIND_DUMP = /tmp/lsup_callgrind.out
  13. MASSIF_DUMP = /tmp/lsup_massif.out
  14. INCLUDE_BASE := . -Iinclude -Iext/tpl/src -Iext/hashmap -Iext/log/src
  15. INCLUDE := -I$(INCLUDE_BASE)
  16. _CFLAGS := -std=gnu11 -Wall -fPIC -MMD $(INCLUDE)
  17. CFLAGS = $(_CFLAGS) -O3
  18. DBG_CFLAGS = $(_CFLAGS) -Itest -O0 -g3 -DDEBUG
  19. #$(info CFLAGS: $(CFLAGS))
  20. #$(info DBG_CFLAGS: $(DBG_CFLAGS))
  21. # NOTE: -luuid is a Linux system library. Other OS's might need a different
  22. # link or a non-system library built.
  23. LDFLAGS := -L. -L$(outdir) -L$(libdir) -llmdb -lxxhash -luuid
  24. PARSER = bin/lemon
  25. LEMON_SRC = ext/sqlite/tool/lemon.c
  26. CODEC_DIR = src/codec
  27. # External sources compiled in core object.
  28. EXT_SRC := $(wildcard ext/log/src/*.c) \
  29. $(wildcard ext/hashmap/*.c) \
  30. $(wildcard ext/tpl/src/*.c)
  31. # External headers of libraries compiled in core.
  32. EXT_H := $(wildcard ext/log/src/*.h) \
  33. $(wildcard ext/tpl/src/*.h) \
  34. $(wildcard ext/hashmap/*.h)
  35. LSUP_SRC = $(wildcard src/*.c)
  36. SRC = $(EXT_SRC) $(LSUP_SRC)
  37. TEST_SRC = $(wildcard test/*.c) test.c
  38. EXT_OBJ := $(EXT_SRC:.c=.o)
  39. # TODO This is extremely convoluted, simplify if possible.
  40. CODEC_SRC := $(wildcard $(CODEC_DIR)/codec_*.c)
  41. CODEC_REL_SRC := $(CODEC_SRC:$(CODEC_DIR)/%=%)
  42. ALL_CODEC_REL_SRC := $(CODEC_REL_SRC) $(CODEC_REL_SRC:codec_%=parser_%) \
  43. $(CODEC_REL_SRC:codec_%=grammar_%)
  44. CODEC_SRC = $(ALL_CODEC_REL_SRC:%=$(CODEC_DIR)/%)
  45. CODEC_OBJ = $(CODEC_SRC:.c=.o)
  46. CODEC_DBG_OBJ = $(CODEC_SRC:.c=_dbg.o)
  47. OBJ = $(EXT_OBJ) $(LSUP_SRC:.c=.o)
  48. DBG_OBJ = $(EXT_OBJ) $(LSUP_SRC:.c=_dbg.o)
  49. STATIC_LIB = $(outdir)/liblsuprdf.a
  50. DYN_LIB = $(outdir)/liblsuprdf.so
  51. STATIC_DBG_LIB = $(outdir)/liblsuprdf_dbg.a
  52. DYN_DBG_LIB = $(outdir)/liblsuprdf_dbg.so
  53. LIBS = $(STATIC_LIB) $(DYN_LIB)
  54. DBG_LIBS = $(STATIC_DBG_LIB) $(DYN_DBG_LIB)
  55. # LDD for Linux, otool -L for OSX.
  56. ifdef $(shell which ldd 2> /dev/null)
  57. LDD := ldd
  58. else
  59. LDD := otool -L
  60. endif
  61. # For visual dep graph.
  62. DEPS := $(shell echo "${INCLUDE_BASE}" | sed -e 's/ -I/,/g'),include/codec
  63. DOCS = docs
  64. ## Environment.
  65. # Tests need the freshly compiled libs.
  66. export LD_LIBRARY_PATH = $(outdir):$(libdir)
  67. ## Rules.
  68. .DEFAULT_GOAL := lib
  69. # Extract all rule comments into a help message.
  70. .PHONY: help
  71. help:
  72. @echo "Command overview:"; echo; \
  73. grep -E '^[a-zA-Z0-9_-]+:.*?## .*$$' $(MAKEFILE_LIST) \
  74. | sed -n 's/^\(.*\): \(.*\)##\(.*\)/\1|\3/p' \
  75. | column -t -s '|'
  76. lib: codec $(LIBS) ## Compile main library (static and dynamic linking).
  77. debug: codec_dbg $(DBG_LIBS) ## Compile main library with debug symbols.
  78. # Static library.
  79. $(STATIC_LIB): $(OBJ)
  80. $(AR) rs $@ $^ $(CODEC_OBJ)
  81. # Dynamic library.
  82. $(DYN_LIB): $(OBJ)
  83. $(CC) -shared $(LDFLAGS) -o $@ $^ $(CODEC_OBJ)
  84. # Static debug library.
  85. $(STATIC_DBG_LIB): $(DBG_OBJ)
  86. $(AR) rs $@ $^ $(CODEC_DBG_OBJ)
  87. # Dynamic debug library.
  88. $(DYN_DBG_LIB): $(DBG_OBJ)
  89. $(CC) -shared $(LDFLAGS) -o $@ $^ $(CODEC_DBG_OBJ)
  90. # Debug objects.
  91. %_dbg.o: %.c
  92. $(CC) $(DBG_CFLAGS) -c $^ -o $@
  93. # Codecs in a subfolder.
  94. .PHONY: codec
  95. codec: $(PARSER)
  96. $(MAKE) -C $(CODEC_DIR) codec
  97. .PHONY: codec_dbg
  98. codec_dbg: $(PARSER)
  99. $(MAKE) -C $(CODEC_DIR) debug
  100. # Build the parser executable.
  101. $(PARSER): $(LEMON_SRC)
  102. $(CC) $^ -o $@
  103. install: lib ## Install library and dependencies to $PREFIX. May require sudo.
  104. @echo "Installing library files in $(PREFIX)."
  105. mkdir -p $(DESTDIR)$(libdir)
  106. mkdir -p $(DESTDIR)$(includedir)
  107. cp $(LIBS) $(DESTDIR)$(libdir) && \
  108. cp -r include/*.h include/codec $(EXT_H) $(DESTDIR)$(includedir)
  109. debug_install: install debug ## Install standard and debug libraries.
  110. @echo "Installing debug library files in $(PREFIX)."
  111. cp $(DBG_LIBS) $(DESTDIR)$(libdir)
  112. .PHONY: clean ## Clean up artifacts, including language parsers.
  113. clean:
  114. rm -f ./*.[aod] bin/* src/*.[aod] src/codec/*.[aod] src/codec/*.out
  115. rm -rf build/ dist/ lsup_rdf.egg-info/
  116. rm -f $(LIBS) $(DBG_LIBS)
  117. rm -f include/codec/grammar_*.h
  118. rm -f src/codec/grammar_*.c src/codec/parser_*.c
  119. .PHONY: uninstall ## Uninstall library (not the dependencies).
  120. uninstall:
  121. rm -f $(DESTDIR)$(libdir)/liblsuprdf*
  122. rm -rf $(DESTDIR)$(includedir)
  123. rm -f bin/test*
  124. # For testing, use debug symbols.
  125. bin/test: debug $(TEST_SRC)
  126. $(CC) $(DBG_CFLAGS) $(LDFLAGS) -llsuprdf_dbg \
  127. test.c -o bin/test
  128. .PHONY: test
  129. test: bin/test ## Run a test suite.
  130. @echo "Using libraries: "; $(LDD) bin/test
  131. exec bin/test
  132. .PHONY: gdb_test
  133. gdb_test: bin/test ## Run a test suite within gdb.
  134. @echo "Using libraries: "; $(LDD) bin/test
  135. exec gdb bin/test
  136. lint:
  137. splint \
  138. $(INCLUDE) -Itest \
  139. -DUINT_MAX=0xFFFFFFFFUL \
  140. -nullpass \
  141. -posix-lib \
  142. test.c
  143. .PHONY: memcheck
  144. memcheck:
  145. valgrind \
  146. --leak-check=full --show-leak-kinds=all --track-origins=yes \
  147. --log-file=$(VALGRIND_DUMP) \
  148. ./bin/test
  149. @echo "Memcheck complete. Valgrind log is at $(VALGRIND_DUMP)"
  150. memtest: bin/test memcheck ## Run a test suite using Valgrind. Output to separate file.
  151. # Performance test application. Essentially the profiling code without debug.
  152. bin/profile: debug profile.c
  153. $(CC) $(CFLAGS) -g -DTESTING $(LDFLAGS) -llsuprdf_dbg \
  154. profile.c -o bin/profile
  155. # Performance test application. Essentially the profiling code without debug.
  156. bin/perftest: lib profile.c
  157. $(CC) $(CFLAGS) -g $(LDFLAGS) -llsuprdf profile.c -o bin/perftest
  158. .PHONY: perftest
  159. perftest: bin/perftest ## Run a performance test by creating, inserting and looking up triples.
  160. bin/perftest
  161. .PHONY: profile
  162. profile: bin/profile ## Run a profiling session. Output can be inspected with KCachegrind.
  163. LSUP_MDB_MAPSIZE=800000 valgrind --tool=callgrind \
  164. --callgrind-out-file="$(CALLGRIND_DUMP)" bin/perftest 1000
  165. @echo "Profile dump written at $(CALLGRIND_DUMP). Open it with "\
  166. "qcachegrind, kcachegrind, etc."
  167. .PHONY: footprint
  168. footprint: bin/perftest ## Measure memory footprint by generating and storing 100K triples.
  169. LSUP_MDB_MAPSIZE=80000000 valgrind --tool=massif \
  170. --massif-out-file=$(MASSIF_DUMP) bin/perftest 100000
  171. @echo "Memory stats file written at $(MASSIF_DUMP). Open it with "\
  172. "massif-visualizer or similar."
  173. .PHONY: py
  174. py: codec ## Build and install python library.
  175. pip3 install build==0.8.0
  176. pip3 uninstall -y lsup_rdf
  177. python3 -m build
  178. pip3 install --no-index --find-links=dist/ lsup_rdf
  179. .PHONY: py_dbg
  180. py_dbg: codec_dbg ## Build and install python library with debug symbols.
  181. pip3 install build==0.8.0
  182. pip3 uninstall -y lsup_rdf
  183. DEBUG=1 python3 -m build
  184. pip3 install --no-index --find-links=dist/ lsup_rdf
  185. .PHONY: pytest
  186. pytest: py_dbg ## Run a test suite for the Python package.
  187. python3 test/cpython_test.py
  188. # Requires cinclude2dot (https://www.flourish.org/cinclude2dot) and Graphviz.
  189. depgraph: $(LSUP_SRC) $(CODEC_SRC) include/* include/codec/* ## Build a visual dependency graph of the code.
  190. cinclude2dot --merge=module --include=$(DEPS) \
  191. --exclude='test|ext' >| $(DOCS)/dev/deps.dot
  192. dot $(DOCS)/dev/deps.dot -Tpdf >| $(DOCS)/dev/deps.pdf