CFLAGS += -Wall -Wextra -Werror -MMD -Isrc/ -Ilibs/
CXXFLAGS += -std=c++11 $(CFLAGS)
LDFLAGS += -lcursesw -lreadline
INSTALL := install -D
GZIP := gzip
ifneq ($(OS),Windows_NT)
bin_suffix :=
else
bin_suffix := .exe
endif
# this function of two arguments (array and element) returns index of the
# element in the array; return -1 if item not found in the list
pos = $(strip $(eval T := ) \
$(eval i := -1) \
$(foreach elem, $1, \
$(if $(filter $2,$(elem)), \
$(eval i := $(words $T)), \
$(eval T := $T $(elem)))) \
$i)
# determine output directory and build target; "." is the directory by default
# or "release"/"debug" for corresponding targets
is_release := 0
ifneq ($(call pos,release,$(MAKECMDGOALS)),-1)
is_release := 1
endif
ifneq ($(call pos,install,$(MAKECMDGOALS)),-1)
is_release := 1
endif
ifneq ($(is_release),0)
EXTRA_CXXFLAGS := -O3
out_dir := release
target := release
else
EXTRA_CXXFLAGS := -O0 -g
EXTRA_LDFLAGS := -g
ifneq ($(call pos,debug,$(MAKECMDGOALS)),-1)
out_dir := debug
else
with_cov := 0
ifneq ($(call pos,coverage,$(MAKECMDGOALS)),-1)
with_cov := 1
endif
ifeq ($(with_cov),1)
out_dir := coverage
EXTRA_CXXFLAGS += --coverage -DNDEBUG
EXTRA_LDFLAGS += --coverage
else
out_dir := .
endif
endif
target := debug
endif
# traverse directories ($1) recursively looking for a pattern ($2) to make list
# of matching files
rwildcard = $(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) \
$(filter $(subst *,%,$2),$d))
name := pipedial
bin := $(name)$(bin_suffix)
bin_sources := $(call rwildcard, src/, *.cpp)
libs_cpp := $(call rwildcard, libs/, *.cpp)
libs_c := $(call rwildcard, libs/, *.c)
bin_objects := $(bin_sources:%.cpp=$(out_dir)/%.o) \
$(libs_cpp:%.cpp=$(out_dir)/%.o) $(libs_c:%.c=$(out_dir)/%.o)
bin_depends := $(bin_objects:%.o=%.d)
tests_sources := $(call rwildcard, tests/, *.cpp)
tests_objects := $(tests_sources:%.cpp=$(out_dir)/%.o)
tests_depends := $(tests_objects:%.o=%.d)
out_dirs := $(sort $(dir $(bin_objects) $(tests_objects)))
.PHONY: check clean man debug release
.PHONY: coverage reset-coverage
.PHONY: install uninstall
debug release: $(out_dir)/$(bin)
man: docs/$(name).1
# the following target doesn't depend on $(wildcard docs/*.md) to make pandoc
# optional
docs/$(name).1: $(wildcard docs/*.md)
pandoc -V title=$(name) \
-V section=1 \
-V app=$(name) \
-V date="$$(date +'%B %d, %Y')" \
-V author='xaizek <xaizek@posteo.net>' \
-s -o $@ $(sort $(wildcard docs/*.md))
coverage: check
gcov -p $(bin_objects) > /dev/null
uncov-gcov --root . --build-root . --no-gcov --capture-worktree \
--exclude tests | uncov new
find . -name '*.gcov' -delete
reset-coverage:
ifeq ($(with_cov),1)
find $(out_dir)/ -name '*.gcda' -delete
endif
$(out_dir)/$(bin): $(bin_objects) | $(out_dirs)
$(CXX) -o $@ $^ $(LDFLAGS) $(EXTRA_LDFLAGS)
check: $(target) $(out_dir)/tests/tests reset-coverage
@$(out_dir)/tests/tests
install: $(target)
$(INSTALL) $(out_dir)/$(bin) $(DESTDIR)/usr/bin/$(bin)
$(GZIP) < docs/$(name).1 > docs/$(name).1.gz
$(INSTALL) -m 644 docs/$(name).1.gz \
$(DESTDIR)/usr/share/man/man1/$(name).1.gz
uninstall:
$(RM) $(DESTDIR)/usr/bin/$(bin) $(DESTDIR)/usr/share/man/man1/$(name).1.gz
# work around parenthesis warning in tests somehow caused by ccache
$(out_dir)/tests/tests: EXTRA_CXXFLAGS += -Wno-error=parentheses -Itests/
$(out_dir)/tests/tests: $(filter-out %/main.o,$(bin_objects)) $(tests_objects) \
tests/. \
| $(out_dirs)
$(CXX) -o $@ $(filter-out %/main.o,$(bin_objects)) $(tests_objects) \
$(LDFLAGS) $(EXTRA_LDFLAGS)
$(out_dir)/%.o: %.cpp | $(out_dirs)
$(CXX) -o $@ -c $(CXXFLAGS) $(EXTRA_CXXFLAGS) $<
$(out_dir)/%.o: %.c | $(out_dirs)
$(CC) -o $@ -c $(CFLAGS) $(EXTRA_CXXFLAGS) $<
$(out_dirs):
mkdir -p $@
clean:
-$(RM) -r coverage/ debug/ release/
-$(RM) $(bin_objects) $(bin_depends) $(tests_objects) $(tests_depends) \
$(out_dir)/$(bin) $(out_dir)/tests/tests docs/$(name).1.gz
include $(wildcard $(bin_depends) $(tests_depends))
Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"
Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/pipedial
Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/pipedial
You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a
pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master