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