-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMakefile
174 lines (126 loc) · 5.87 KB
/
Makefile
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# makefile which automatically adapts to new files in the source code
# also uses file compilation dependencies generated by the compiler for minimal partial rebuilds
# platform ('linux' or 'windows')
PLATFORM = linux
# binary and build/source directory name
BUILD_DIR = build
BIN = a.out
SRC_DIR = src
# assign 1 for release build
RELEASE = 0
# optional dependency info
# assign 1 to use or 0 to exclude dependency
# USE_FFMPEG = 1
# non-optional dependency info
# ...
# rest are only relevant on Windows, as these dependencies are managed by Linux package managers
SDL2_DIR = dependencies/sdl2
SDL2_TTF_DIR = dependencies/sdl2_ttf
# general compiler flags
N_CORES = 20# use less on low RAM systems
CXX = g++
CXXFLAGS = -std=c++20# -shared -fPIC
WARNINGS = -Wall -Wextra -Wshadow -pedantic -Wstrict-aliasing# -Wfloat-conversion -Wconversion -Warith-conversion -Wfloat-equal -Wold-style-cast
OPTIMIZATIONS = -O3# -march=native -mtune=native -mfma -mavx2 -ftree-vectorize -ffast-math
# release/debug build
ifeq ($(RELEASE),1)
CXXFLAGS += -DNDEBUG
else
CXXFLAGS += -g
endif
# include source directory for absolute path includes (relative to source dir root)
INCL += -I$(SRC_DIR)/
# manage dependency build flags
# mingw32 (for building on windows)
ifeq ($(PLATFORM),windows)
# -mwindows prevents opening a terminal at program start-up
# CXXFLAGS += -mwindows
LIBS += -lmingw32
endif
# sdl2 and sdl2_ttf
ifeq ($(PLATFORM),windows)
INCL += -I$(SDL2_DIR)/include -I$(SDL2_TTF_DIR)/include
LIBS += -L$(SDL2_DIR)/bin -L$(SDL2_TTF_DIR)/bin -lSDL2 -lSDL2_ttf
# needed for sdl2_ttf as in includes "SDL.h" instead of "SDL2/SDL.h"
INCL += -I$(SDL2_DIR)/include/SDL2
# needed for "undefined reference to 'WinMain'" error
LIBS += -L$(SDL2_DIR)/lib -lSDL2main
else
LIBS += -lSDL2 -lSDL2_ttf
endif
# set-up build directories and source structure info
# `SRC_SUBDIRS` includes `SRC_DIR`
SRC_SUBDIRS = $(patsubst %,%/,$(shell find $(SRC_DIR) -type d -print))
SRC_FILES = $(wildcard $(patsubst $(SRC_DIR)%/,$(SRC_DIR)%/*.hpp,$(SRC_SUBDIRS))) $(wildcard $(patsubst $(SRC_DIR)%/,$(SRC_DIR)%/*.cpp,$(SRC_SUBDIRS)))
TMP_FILE_DIR = $(BUILD_DIR)/tmp
BUILD_OBJ_DIR = $(TMP_FILE_DIR)/obj
BUILD_DEP_DIR = $(TMP_FILE_DIR)/dep
BUILD_SUBDIRS = $(patsubst $(SRC_DIR)%/,$(BUILD_OBJ_DIR)%/,$(SRC_SUBDIRS)) $(patsubst $(SRC_DIR)%/,$(BUILD_DEP_DIR)%/,$(SRC_SUBDIRS))
# create an .o file for every .cpp file
ALL_OBJ = $(patsubst $(SRC_DIR)/%.cpp,$(BUILD_OBJ_DIR)/%.o,$(wildcard $(patsubst $(SRC_DIR)%/,$(SRC_DIR)%/*.cpp,$(SRC_SUBDIRS))))
# .o files which should not be created (.cpp which should not be compiled)
FILTER_OBJ =# e.g. $(BUILD_OBJ_DIR)/main.o
# objects to compile
OBJ = $(filter-out $(FILTER_OBJ),$(ALL_OBJ))
# command to automatically generate compile dependency data
DEPFLAGS = -MT $@ -MMD -MF $(patsubst $(BUILD_OBJ_DIR)/%.o,$(BUILD_DEP_DIR)/%.d,$@)
.PHONY: all sanitize force fresh clean valgrind lines trailing_spaces no_pragma help
all:
# compile and link
make -j $(N_CORES) $(BUILD_DIR)/$(BIN) --no-print-directory
# TODO: copy dependencies (library files on Windows mostly)
# copy resource dir
cp -r -u rsc $(BUILD_DIR)/
@# clean compilation files when building release
@if [ "$(RELEASE)" == "1" ]; then \
echo "# cleaning build files..."; \
echo "rm -rf $(TMP_FILE_DIR)"; \
rm -rf $(TMP_FILE_DIR); \
fi
# build project with address sanitizer
sanitize:
make all BUILD_DIR=$(BUILD_DIR)_asan CXXFLAGS="$(CXXFLAGS) -fsanitize=address" --no-print-directory
force:
make -B all --no-print-directory
fresh:
make clean --no-print-directory
make all --no-print-directory
clean:
rm -rf $(BUILD_DIR)
rm -rf $(BUILD_DIR)_asan
# binary rule
$(BUILD_DIR)/$(BIN): $(OBJ)
$(CXX) $(CXXFLAGS) $(WARNINGS) $(OPTIMIZATIONS) -o $@ $^ $(LIBS)
# the different build folders needed
$(BUILD_SUBDIRS):
mkdir -p $@
# generic object file rule; also makes dependency files using $(DEPFLAGS)
$(BUILD_OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp | $(BUILD_SUBDIRS)
$(CXX) $(DEPFLAGS) $(CXXFLAGS) $(INCL) $(WARNINGS) $(OPTIMIZATIONS) -c $< -o $@
# include the dependencies
include $(wildcard $(patsubst $(BUILD_OBJ_DIR)/%.o,$(BUILD_DEP_DIR)/%.d,$(OBJ)))
compile_commands.json: $(SRC_FILES) Makefile
bear -- make -B
valgrind: all
clear
valgrind --leak-check=full --error-limit=no $(BUILD_DIR)/$(BIN) #--show-reachable=yes
lines:
wc -l $(SRC_FILES)
# note that when copy pasting the grep command, the extra $ has to be removed
trailing_spaces:
@grep --color=auto -n -r '[[:blank:]]$$' -r $(SRC_DIR)/ Makefile || echo -e "No trailing spaces in source!\n"
# don't forget to set PROJECT_NAME='<project name>'
no_pragma:
find $(SRC_DIR)/ -type f -exec sh -c 'if head -n 1 "$$1" | grep -q "^#pragma once$$"; then filename=$$(printf "$(PROJECT_NAME)_%s" "$${1#$(SRC_DIR)/}" | tr -c "[:alnum:]" "_" | tr "[:lower:]" "[:upper:]"); sed -i "1s,^#pragma once$$,#ifndef $${filename%.*}\n#define $${filename%.*}\n," "$$1"; echo -e "\n\n#endif // ifndef $${filename%.*}" >> "$$1"; fi' sh {} \;
help:
@echo The default build target is \"all\", produces the build in $(BUILD_DIR).
@echo \ \ \"make clean\" removes all built files.
@echo \ \ \"make force\" forces all build targets to be rebuild.
@echo \ \ \"make fresh\" runs \"make clean\; make\", which may help with potential building problems after updating.
@echo \ \ \"make sanitize\" builds with -fsanitize=address.
@echo
@echo Furthermore, some often used command are added to the makefile:
@echo \ \ \"make compile_commands.json\" creates compile command database used by clangd\; requires bear to be installed
@echo \ \ \"make lines\" counts the number of lines in all source files.
@echo \ \ \"make trailing_spaces\" searches all source files for trailing whitespace characters \(whitespace characters before line end\).
@echo \ \ \"make no_pragma PROJECT_NAME=\'\<project name\>\'\" replaces \"\#pragma once\" based include guards with \"\#ifndef ...\" based ones.