xaizek / uncov (License: AGPLv3+) (since 2018-12-07)
Uncov(er) is a tool that collects and processes code coverage reports.
<root> / Makefile (f5a5c4194b5cf98a31ca6f115b3ae106becfa191) (8,384B) (mode 100644) [raw]
CXXFLAGS += -std=gnu++11 -Wall -Wextra -MMD -MP -I$(abspath src)
CXXFLAGS += -Wno-non-template-friend -include config.h
LDFLAGS  += $(ld_extra) -g -lsqlite3 -lgit2 -lsource-highlight -lz
LDFLAGS  += -lboost_filesystem -lboost_iostreams -lboost_program_options
LDFLAGS  += -lboost_system

INSTALL := install -D

PREFIX := /usr

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
    # EXTRA_LDFLAGS  := -Wl,--strip-all

    out_dir := release
    target  := release
else
    EXTRA_CXXFLAGS := -O0 -g
    EXTRA_LDFLAGS  := -g

    ifneq ($(call pos,debug,$(MAKECMDGOALS)),-1)
        out_dir := debug
    else
        ifneq ($(call pos,sanitize-basic,$(MAKECMDGOALS)),-1)
            out_dir := sanitize-basic
            EXTRA_CXXFLAGS += -fsanitize=address -fsanitize=undefined
            EXTRA_LDFLAGS  += -fsanitize=address -fsanitize=undefined -pthread
        else
            with_cov := 0
            ifneq ($(call pos,coverage,$(MAKECMDGOALS)),-1)
                with_cov := 1
            endif
            ifneq ($(call pos,self-coverage,$(MAKECMDGOALS)),-1)
                with_cov := 1
            endif

            ifneq ($(with_cov),0)
                out_dir := coverage
                EXTRA_CXXFLAGS += --coverage
                EXTRA_LDFLAGS  += --coverage
            else
                out_dir := .
            endif
        endif
    endif
    target := debug
endif

# run all tests by default
TESTS :=

-include config.mk

# 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))

bin := $(out_dir)/uncov$(bin_suffix)

bin_sources := $(call rwildcard, src/, *.cpp)
bin_objects := $(bin_sources:%.cpp=$(out_dir)/%.o)
bin_depends := $(bin_objects:.o=.d)

tests_sources := $(call rwildcard, tests/, *.cpp)
tests_sources := $(filter-out tests/test-repo%, $(tests_sources))

tests_objects := $(tests_sources:%.cpp=$(out_dir)/%.o)
tests_objects += $(filter-out %/main.o,$(bin_objects))
tests_depends := $(tests_objects:%.o=%.d)

webbin := $(out_dir)/uncov-web$(bin_suffix)
web_sources := $(call rwildcard, web/, *.cpp)
web_temps := $(patsubst %.ecpp,$(out_dir)/%.cpp,$(call rwildcard, web/, *.ecpp))
web_temps += $(patsubst %.css,$(out_dir)/%.cpp,$(call rwildcard, web/, *.css))
web_temps += $(patsubst %.ico,$(out_dir)/%.cpp,$(call rwildcard, web/, *.ico))
web_temps += $(patsubst %.txt,$(out_dir)/%.cpp,$(call rwildcard, web/, *.txt))
web_objects := $(web_sources:%.cpp=$(out_dir)/%.o)
web_objects += $(web_temps:%.cpp=%.o)
web_objects += $(filter-out %/main.o,$(bin_objects))
web_depends := $(web_objects:%.o=%.d)
web_depends += $(patsubst %.ecpp,$(out_dir)/%.ecpp.d, \
                          $(call rwildcard, web/, *.ecpp))

out_dirs := $(sort $(dir $(bin_objects) $(web_objects) $(tests_objects)))

.PHONY: all check clean debug release sanitize-basic install uninstall
.PHONY: man doxygen
.PHONY: coverage self-coverage self-coverage-release reset-coverage

all: $(bin) $(webbin)

debug release sanitize-basic: all

coverage: check $(bin)
	uncov new-gcovi --exclude tests/ --exclude web/ \
	                --capture-worktree $(out_dir)

self-coverage: check self-coverage-release
	release/uncov new-gcovi --exclude tests/ --exclude web/ \
	                        --capture-worktree $(out_dir)

self-coverage-release:
	+$(MAKE) release

man: docs/uncov.1 docs/uncov-gcov.1 docs/uncov-web.1
# the following targets don't depend on $(wildcard docs/*/*.md) to make pandoc
# optional
docs/uncov.1: force
	pandoc -V title=uncov \
	       -V section=1 \
	       -V app=uncov \
	       -V footer="uncov v0.5" \
	       -V date="$$(date +'%B %d, %Y')" \
	       -V author='xaizek <xaizek@posteo.net>' \
	       -s -o $@ $(sort $(wildcard docs/uncov/*.md))
docs/uncov-gcov.1: force
	pandoc -V title=uncov-gcov \
	       -V section=1 \
	       -V app=uncov-gcov \
	       -V footer="uncov v0.5" \
	       -V date="$$(date +'%B %d, %Y')" \
	       -V author='xaizek <xaizek@posteo.net>' \
	       -s -o $@ $(sort $(wildcard docs/uncov-gcov/*.md))
docs/uncov-web.1: force
	pandoc -V title=uncov-web \
	       -V section=1 \
	       -V app=uncov-web \
	       -V footer="uncov v0.5" \
	       -V date="$$(date +'%B %d, %Y')" \
	       -V author='xaizek <xaizek@posteo.net>' \
	       -s -o $@ $(sort $(wildcard docs/uncov-web/*.md))

doxygen:
	doxygen doxygen/config
	ln -sr data doxygen/html/

# target that doesn't exist and used to force rebuild
force:

reset-coverage: | $(out_dirs)
ifeq ($(with_cov),1)
	find $(out_dir)/ -name '*.gcda' -delete
endif

$(bin) $(webbin): | $(out_dirs)

$(bin): $(bin_objects)
	$(CXX) -o $@ $^ $(LDFLAGS) $(EXTRA_LDFLAGS)

ifndef NO-WEB
$(webbin): $(web_objects) | $(web_temps)
	$(CXX) -o $@ $^ $(LDFLAGS) $(EXTRA_LDFLAGS) -ltntnet -lcxxtools
else
$(webbin):
	@echo '#!/bin/bash' >> $@
	@echo 'echo "Uncov-web was disabled during build"' >> $@
	@chmod +x $@
endif

check: $(target) $(out_dir)/tests/tests tests/test-repo-gcno/test-repo-gcno \
       reset-coverage
	@$(out_dir)/tests/tests $(TESTS)

tests/test-repo-gcno/test-repo-gcno: tests/test-repo-gcno/main.cpp
	# this must always be compiled with GCC for gcov to be able to process
	# output files (need a separate variable for it?)
	cd tests/test-repo-gcno/ && g++ --coverage -o test-repo-gcno main.cpp

install: release
	$(INSTALL) -t $(DESTDIR)$(PREFIX)/bin/ $(bin) $(webbin) uncov-gcov
	$(INSTALL) -t $(DESTDIR)$(PREFIX)/share/uncov/srchilight/ data/srchilight/*
	$(INSTALL) -m 644 docs/uncov.1 $(DESTDIR)$(PREFIX)/share/man/man1/uncov.1
	$(INSTALL) -m 644 docs/uncov-gcov.1 \
	              $(DESTDIR)$(PREFIX)/share/man/man1/uncov-gcov.1
	$(INSTALL) -m 644 docs/uncov-web.1 \
	              $(DESTDIR)$(PREFIX)/share/man/man1/uncov-web.1

uninstall:
	$(RM) $(DESTDIR)$(PREFIX)/bin/$(basename $(bin)) \
	      $(DESTDIR)$(PREFIX)/bin/$(basename $(webbin)) \
	      $(DESTDIR)$(PREFIX)/bin/uncov-gcov \
	      $(DESTDIR)$(PREFIX)/share/man/man1/uncov.1 \
	      $(DESTDIR)$(PREFIX)/share/man/man1/uncov-gcov.1 \
	      $(DESTDIR)$(PREFIX)/share/man/man1/uncov-web.1
	$(RM) -r $(DESTDIR)$(PREFIX)/share/uncov/

# work around parenthesis warning in tests somehow caused by ccache
$(out_dir)/tests/tests: EXTRA_CXXFLAGS += -Wno-error=parentheses -Itests/
$(out_dir)/tests/tests: $(tests_objects) tests/. | $(out_dirs)
	$(CXX) -o $@ $(tests_objects) $(LDFLAGS) $(EXTRA_LDFLAGS)

config.h: | config.h.in
	cp config.h.in $@

$(out_dir)/web/%.o: CXXFLAGS += -I$(abspath web)
$(out_dir)/web/%.o: $(out_dir)/web/%.cpp config.h | $(out_dirs)
	$(CXX) -o $@ -c $(CXXFLAGS) $(EXTRA_CXXFLAGS) $<

$(out_dir)/%.o: %.cpp config.h | $(out_dirs)
	$(CXX) -o $@ -c $(CXXFLAGS) $(EXTRA_CXXFLAGS) $<

$(out_dir)/%.cpp: %.ecpp | $(out_dirs)
	ecppc -o $@ $<
	ecppc -M -o $(out_dir)/$*.ecpp.d -n $* $<

$(out_dir)/%.cpp: %.css | $(out_dirs)
	ecppc -b -m text/css -o $@ $<

$(out_dir)/%.cpp: %.ico | $(out_dirs)
	ecppc -b -m image/x-icon -o $@ $<

$(out_dir)/%.cpp: %.txt | $(out_dirs)
	ecppc -b -m text/plain -o $@ $<

$(out_dirs) $(out_dir)/docs:
	mkdir -p $@

clean:
	-$(RM) -r coverage/ debug/ release/
	-$(RM) $(bin_objects) $(tests_objects) $(web_objects) \
	       $(bin_depends) $(tests_depends) $(web_depends) \
	       $(web_temps) \
	       $(bin) $(webbin) $(out_dir)/tests/tests \
	       tests/test-repo-gcno/test-repo-gcno \
	       tests/test-repo-gcno/test-repo-gcno.gcda \
	       tests/test-repo-gcno/test-repo-gcno.gcno

include $(wildcard $(bin_depends) $(tests_depends) $(web_depends))
Hints

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/uncov

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/uncov

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