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