Packages
glazer
0.5.14
0.5.17
0.5.16
0.5.15
0.5.14
retired
0.5.13
retired
0.5.12
retired
0.5.11
retired
0.5.10
retired
0.5.9
retired
0.5.8
retired
0.5.7
retired
0.5.6
retired
0.5.5
retired
0.5.4
retired
0.5.3
retired
0.5.2
retired
0.5.1
retired
0.5.0
retired
0.3.2
retired
0.3.0
retired
0.2.6
retired
0.2.5
retired
0.2.4
retired
0.2.3
retired
0.2.2
retired
0.2.1
retired
0.2.0
retired
0.1.7
retired
0.1.6
retired
0.1.5
retired
0.1.4
retired
Erlang NIF JSON encoder/decoder using the glaze C++ library
Retired package: Deprecated - Deprecated
Current section
Files
Jump to
Current section
Files
Makefile
ifndef VERBOSE
MAKEFLAGS += --no-print-directory
endif
PRIV_DIR := $(abspath priv)
OBJ_DIR := $(abspath obj)
DEBUG ?= 0
REBAR ?= rebar3
APP := $(shell sed -nE 's/^\{application, ([a-zA-Z0-9_]+),.*/\1/p' src/*.app.src | head -n1)
OPTIMIZE ?= 0
ifneq ($(filter $(OPTIMIZE),1 true),)
override OPTIMIZE := 1
else
override OPTIMIZE := 0
endif
all: compile
help:
@echo "Usage: make [target] [VAR=value ...]"
@echo ""
@echo "Build targets:"
@echo " all Build NIF and compile Erlang (default)"
@echo " nif Build only the C NIF shared library"
@echo " compile Build NIF + run rebar3 compile"
@echo " optimize PGO build: instrument → benchmark → rebuild (fastest binary)"
@echo " clean Remove build artifacts"
@echo " distclean Remove all generated files including deps"
@echo ""
@echo "Development:"
@echo " test Run eunit test suite"
@echo " cover Run eunit with coverage analysis and print a summary"
@echo " check Run xref and dialyzer"
@echo " dialyzer Run dialyzer"
@echo " memcheck Build with ASan (-fsanitize=address) and run eunit (leak=1 adds LSan)"
@echo " benchmark Run benchmarks via mix bench"
@echo " deps Fetch mix dependencies"
@echo " doc Generate documentation"
@echo ""
@echo "Publishing:"
@echo " bump-version Increment patch version and commit"
@echo " publish Publish to hex.pm (pass replace=1 to replace existing)"
@echo " deprecate Deprecate a hex.pm release (pass vsn=X.Y.Z)"
@echo ""
@echo "Variables:"
@echo " DEBUG=1 Build NIF without optimisations (-O0 -g)"
@echo " ASAN=1 Build with AddressSanitizer (implied by memcheck)"
@echo " leak=1 Enable LeakSanitizer during memcheck (off by default)"
@echo " VERBOSE=1 Show full compiler command lines"
@echo " OPTIMIZE=1 Make all/compile run the PGO 'optimize' build (same as 'make optimize')"
nif: $(PRIV_DIR)/glazer.so
$(PRIV_DIR)/glazer.so: $(wildcard c_src/*.cpp c_src/*.hpp)
@$(MAKE) -C c_src PRIV_DIR=$(PRIV_DIR) OBJ_DIR=$(OBJ_DIR) DEBUG=$(DEBUG) \
$(if $(VERBOSE),VERBOSE=1,) --no-print-directory
ifeq ($(OPTIMIZE),1)
compile: optimize
else
compile: $(PRIV_DIR)/glazer.so
$(REBAR) compile
endif
clean:
$(REBAR) clean
@$(MAKE) --no-print-directory -C c_src PRIV_DIR=$(PRIV_DIR) OBJ_DIR=$(OBJ_DIR) DEBUG=$(DEBUG) clean 2>/dev/null || true
distclean: clean
@rm -rf obj priv/glazer.so _build .perf.txt
test:
$(REBAR) eunit
# Locate the ASan runtime for LD_PRELOAD on Linux.
# macOS memcheck is not supported (DYLD_INSERT_LIBRARIES is dropped by the
# rebar3 shell wrapper before reaching erl), so this block is Linux-only.
# Try Clang's resource-dir path first; fall back to GCC's -print-file-name.
_CXX_RESOURCE_DIR := $(shell $(CXX) -print-resource-dir 2>/dev/null)
_HOST_ARCH := $(shell uname -m)
_ASAN_CLANG := $(_CXX_RESOURCE_DIR)/lib/linux/libclang_rt.asan-$(_HOST_ARCH).so
_ASAN_GCC := $(shell $(CXX) -print-file-name=libasan.so 2>/dev/null)
ASAN_RT := $(strip $(if $(wildcard $(_ASAN_CLANG)),$(_ASAN_CLANG),\
$(if $(filter-out $(notdir $(_ASAN_GCC)),$(_ASAN_GCC)),$(_ASAN_GCC))))
ASAN_PRELOAD = LD_PRELOAD="$(ASAN_RT)"
LSAN_SUPPRESSIONS := $(abspath c_src/lsan_suppressions.txt)
leak ?= 0
ifeq ($(leak),0)
DETECT_LEAKS := 0
else
DETECT_LEAKS := 1
endif
check:
$(REBAR) xref
$(REBAR) dialyzer
memcheck:
@echo "==> Building NIF with AddressSanitizer"
@$(MAKE) -C c_src PRIV_DIR=$(PRIV_DIR) OBJ_DIR=$(OBJ_DIR) ASAN=1 \
$(if $(VERBOSE),VERBOSE=1,) clean all
@$(REBAR) compile
@echo "==> Running eunit under ASan$(if $(filter 1,$(DETECT_LEAKS)), + LeakSanitizer,) ($(ASAN_PRELOAD))"
ERL_FLAGS="+A 1" ASAN_OPTIONS="detect_leaks=$(DETECT_LEAKS)" \
LSAN_OPTIONS="suppressions=$(LSAN_SUPPRESSIONS)" \
$(ASAN_PRELOAD) \
$(REBAR) eunit
@echo "==> Rebuilding normal NIF (removing ASan instrumentation)"
@$(MAKE) -C c_src PRIV_DIR=$(PRIV_DIR) OBJ_DIR=$(OBJ_DIR) \
$(if $(VERBOSE),VERBOSE=1,) clean all
@$(REBAR) compile
doc docs:
$(REBAR) ex_doc
benchmark bench: do-bench
do-bench: deps
@rm -f .perf.txt
@$(MAKE) --no-print-directory optimize
PARALLEL=$(if $(PARALLEL),$(PARALLEL),1) MIX_ENV=bench mix bench | tee .perf.txt;
# ELIXIR_ERL_OPTIONS quiets rustler_precompiled's [debug] "Copying NIF from
# cache and extracting..." noise (torque/yaml_rustler/rusty_csv all use it)
# without touching the project-wide Logger level — scoped to bench targets
# only via this env var, not a global :logger config in mix.exs.
bench-json bench-yaml bench-csv: export ELIXIR_ERL_OPTIONS = -logger level warning
bench-json bench-yaml bench-csv: deps
PARALLEL=$(if $(PARALLEL),$(PARALLEL),1) MIX_ENV=bench mix $@
# Profile-guided optimisation: instrument → run tests as workload → rebuild.
# Usage: make optimize
optimize:
@echo "==> PGO step 1/3: build instrumented binary"
@$(MAKE) -C c_src PRIV_DIR=$(PRIV_DIR) OBJ_DIR=$(OBJ_DIR) PGO=generate clean all
@$(REBAR) compile
@echo "==> PGO step 2/3: collect profile data"
@./bin/pgo-profile.es
@echo "==> PGO step 3/3: rebuild with profile data"
@rm -f $(OBJ_DIR)/glazer_nif.o $(PRIV_DIR)/glazer.so
@$(MAKE) -C c_src PRIV_DIR=$(PRIV_DIR) OBJ_DIR=$(OBJ_DIR) PGO=use all
@$(REBAR) compile
@echo "==> PGO build complete"
deps:
@mix deps.get
publish: docs
$(REBAR) hex publish$(if $(replace), --replace)
deprecate:
@if [ -z $(vsn) ]; then \
echo "Usage: $(MAKE) $@ vsn=X.Y.Z - Deprecate version X.Y.Z"; \
exit 1; \
fi
$(REBAR) hex retire $(APP) $(vsn) deprecated --message Deprecated
cover:
$(REBAR) cover --verbose
bump-version:
@FILE=$$(ls -1 src/*.app.src | head -n1); \
CURRENT=$$(grep -m1 '{vsn,' $$FILE | sed -E 's/.*"([0-9]+\.[0-9]+\.[0-9]+)".*/\1/'); \
MAJOR=$$(echo $$CURRENT | cut -d. -f1); \
MINOR=$$(echo $$CURRENT | cut -d. -f2); \
PATCH=$$(echo $$CURRENT | cut -d. -f3); \
NEW=$$(echo "$${MAJOR}.$${MINOR}.$$((PATCH + 1))" | tr -d '\n'); \
echo "Bumping version from $${CURRENT} to $${NEW}"; \
sed -i "s/{vsn, \"$${CURRENT}\"}/{vsn, \"$${NEW}\"}/" $$FILE; \
echo "Changed: {vsn, \"$${CURRENT}\"} -> {vsn, \"$${NEW}\"}"; \
sed -i 's/\({:\?glazer,[[:space:]]*"~>\)[^"]*/\1 '"$${MAJOR}.$${MINOR}"'/' README.md; \
echo ""; \
read -p "Commit this change? [Y/n] " -n 1 -r || true; \
echo ""; \
if [[ $$REPLY =~ ^[Yy]$$ ]] || [[ -z $$REPLY ]]; then \
git commit -am "Bump version to $${NEW}"; \
fi
.PHONY: all help doc compile clean distclean test cover check dialyzer memcheck nif \
optimize benchmark bench publish deprecate bump-version deps \
bench-yaml bench-json bench-csv do-bench