1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150 | # C/C++ Makefile v2.2.2 2021-Set-17 Jeisson Hidalgo ECCI-UCR CC-BY 4.0
# Compiler and tool flags
CC=cc
XC=g++
DEFS=
FLAGS=$(strip -Wall -Wextra -pthread $(DEFS))
FLAGC=$(FLAGS) -std=gnu11
FLAGX=$(FLAGS) -std=gnu++11
LIBS=
LINTF=-build/header_guard,-build/include_subdir
LINTC=$(LINTF),-readability/casting
LINTX=$(LINTF),-build/c++11,-runtime/references
ARGS=5 2 3 0 100 0 750
# Directories
BIN_DIR=bin
OBJ_DIR=build
DOC_DIR=doc
SRC_DIR=src
TST_DIR=tests
# If src/ dir does not exist, use current directory .
ifeq "$(wildcard $(SRC_DIR) )" ""
SRC_DIR=.
endif
# Files
DIRS=$(shell find $(SRC_DIR) -type d)
APPNAME=$(shell basename $(shell pwd))
HEADERC=$(wildcard $(DIRS:%=%/*.h))
HEADERX=$(wildcard $(DIRS:%=%/*.hpp))
SOURCEC=$(wildcard $(DIRS:%=%/*.c))
SOURCEX=$(wildcard $(DIRS:%=%/*.cpp))
INPUTFC=$(strip $(HEADERC) $(SOURCEC))
INPUTFX=$(strip $(HEADERX) $(SOURCEX))
INPUTCX=$(strip $(INPUTFC) $(INPUTFX))
OBJECTC=$(SOURCEC:$(SRC_DIR)/%.c=$(OBJ_DIR)/%.o)
OBJECTX=$(SOURCEX:$(SRC_DIR)/%.cpp=$(OBJ_DIR)/%.o)
OBJECTS=$(strip $(OBJECTC) $(OBJECTX))
TESTINF=$(wildcard $(TST_DIR)/input*.txt)
TESTOUT=$(TESTINF:$(TST_DIR)/input%.txt=$(OBJ_DIR)/output%.txt)
INCLUDE=$(DIRS:%=-I%)
DEPENDS=$(OBJECTS:%.o=%.d)
IGNORES=$(BIN_DIR) $(OBJ_DIR) $(DOC_DIR)
EXEFILE=$(BIN_DIR)/$(APPNAME)
EXEARGS=$(strip $(EXEFILE) $(ARGS))
LD=$(if $(SOURCEC),$(CC),$(XC))
# Targets
default: debug
all: doc lint memcheck helgrind test
debug: FLAGS += -g
debug: $(EXEFILE)
release: FLAGS += -O3 -DNDEBUG
release: $(EXEFILE)
asan: FLAGS += -fsanitize=address -fno-omit-frame-pointer
asan: debug
msan: FLAGS += -fsanitize=memory
msan: CC = clang
msan: XC = clang++
msan: debug
tsan: FLAGS += -fsanitize=thread
tsan: debug
ubsan: FLAGS += -fsanitize=undefined
ubsan: debug
-include $(DEPENDS)
.SECONDEXPANSION:
# Linker call
$(EXEFILE): $(OBJECTS) | $$(@D)/.
$(LD) $(FLAGS) $(INCLUDE) $^ -o $@ $(LIBS)
# Compile C source file
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c | $$(@D)/.
$(CC) -c $(FLAGC) $(INCLUDE) -MMD $< -o $@
# Compile C++ source file
$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp | $$(@D)/.
$(XC) -c $(FLAGX) $(INCLUDE) -MMD $< -o $@
# Create a subdirectory if not exists
.PRECIOUS: %/.
%/.:
mkdir -p $(dir $@)
# Test cases
.PHONY: test
test: $(EXEFILE) $(TESTOUT)
$(OBJ_DIR)/output%.txt: SHELL:=/bin/bash
$(OBJ_DIR)/output%.txt: $(TST_DIR)/input%.txt $(TST_DIR)/output%.txt
icdiff --no-headers $(word 2,$^) <($(EXEARGS) < $<)
# Documentation
doc: $(INPUTCX)
doxygen
# Utility rules
.PHONY: lint run memcheck helgrind gitignore clean instdeps
lint:
ifneq ($(INPUTFC),)
cpplint --filter=$(LINTC) $(INPUTFC)
endif
ifneq ($(INPUTFX),)
cpplint --filter=$(LINTX) $(INPUTFX)
endif
run: $(EXEFILE)
$(EXEARGS)
memcheck: $(EXEFILE)
valgrind --tool=memcheck $(EXEARGS)
helgrind: $(EXEFILE)
valgrind --quiet --tool=helgrind $(EXEARGS)
gitignore:
echo $(IGNORES) | tr " " "\n" > .gitignore
clean:
rm -rf $(IGNORES)
# Install dependencies (Debian)
instdeps:
sudo apt install build-essential clang valgrind icdiff doxygen graphviz \
python3-gpg && sudo pip3 install cpplint
help:
@echo "Usage make [-jN] [VAR=value] [target]"
@echo " -jN Compile N files simultaneously [N=1]"
@echo " VAR=value Overrides a variable, e.g CC=mpicc DEFS=-DGUI"
@echo " all Run targets: doc lint [memcheck helgrind] test"
@echo " asan Build for detecting memory leaks and invalid accesses"
@echo " clean Remove generated directories and files"
@echo " debug Build an executable for debugging [default]"
@echo " doc Generate documentation from sources with Doxygen"
@echo " gitignore Generate a .gitignore file"
@echo " helgrind Run executable for detecting thread errors with Valgrind"
@echo " instdeps Install needed packages on Debian-based distributions"
@echo " lint Check code style conformance using Cpplint"
@echo " memcheck Run executable for detecting memory errors with Valgrind"
@echo " msan Build for detecting uninitialized memory usage"
@echo " release Build an optimized executable"
@echo " run Run executable using ARGS value as arguments"
@echo " test Run executable against test cases in folder tests/"
@echo " tsan Build for detecting thread errors, e.g race conditions"
@echo " ubsan Build for detecting undefined behavior"
|