Makefile 6.6 KB

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