-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathMakefile
174 lines (142 loc) · 7.56 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
CC = clang
NAME = uls
# set default rule
.DEFAULT_GOAL = all
MKDIR = mkdir -p
PRINT = printf
RM = rm -rf
# colors
R = \033[1;91m
G = \033[1;92m
Y = \033[1;93m
B = \033[1;94m
M = \033[1;95m
C = \033[1;96m
S = \033[38;5;45;1m
D = \033[0m
F = \033[5m
K = \033[K
# warning flags
WFLAGS = -Wall -Wextra -Werror -Wpedantic
# debug flags
DFLAGS = -O0 -g3 -ftrapv -fstandalone-debug
SRC_DIR = src/
INC_DIR = inc/
OBJ_DIR = obj/
# collect subdirectories in source directory
SRC_DIRS := $(wildcard $(SRC_DIR)**) $(SRC_DIR)
# collect source files
SRC := $(wildcard $(SRC_DIR)**/*.c) $(wildcard $(SRC_DIR)*.c)
# collect subdirectories in header directory
INC_DIRS := $(wildcard $(INC_DIR)**) $(INC_DIR)
# collect header files
HDR := $(wildcard $(INC_DIR)**/*.h) $(wildcard $(INC_DIR)*.h)
# include flags
IFLAGS := $(foreach f, $(INC_DIRS), $(f:%=-I%))
# link directory flags
LFLAGS := # -L...
# link library flags
lFLAGS := # -l...
# compilation of translation unit
COMPILE := $(CC) -std=c11 -pipe $(WFLAGS) $(IFLAGS)
# compilation of target
BUILD := $(COMPILE) $(LFLAGS) $(lFLAGS)
# template for using libraries of depend makefiles
define DEPENDENCY_template # 1 - include path | 2 - link path | 3 - link name
# sets -I flag before every include path ($1 could be list of directories)
DEP_IFLAGS += $$(foreach f, $1, $$(f:%=-I%))
# sets -L flag before link directory
DEP_LFLAGS += -L$2
# sets -l flag before link library
DEP_lFLAGS += -l$3
endef
# template for calling all depend makefiles
define DEPENDENT_MAKE_template # 1 - name | 2 - directory
# prevents errors if $1 target named same as one of items in current directory
.PHONY: $1 clean_$1 uninstall_$1
# add target for calling depend makefiles
MAKE_TARGETS += $1
# add current target in main target list of dependencies for building
BUILD_TARGETS += $2/$1
# add current target in main target list of dependencies for cleaning
CLEAN_TARGETS += clean_$1
# add current target in main target list of dependencies for uninstalling
UNINSTALL_TARGETS += uninstall_$1
# build target for dependency
$1:
@$(MAKE) -sf Makefile -C $2
# clean target for dependency
clean_$1:
@$(MAKE) -sf Makefile -C $2 clean
# uninstall target for dependency
uninstall_$1:
@$(MAKE) -sf Makefile -C $2 uninstall
endef
# template for building version of target with different compilation flags
define BUILD_template # 1 - target | 2 - flags
# add build type in name if it isn't default build
ifeq ($1,default)
NAME_$1 = $(NAME)
else
NAME_$1 = $(NAME)_$1
endif
# add name of target file to list of build targets
BUILD_NAMES += $$(NAME_$1)
# create name of subdirectory for subdirectories with object files
OBJ_DIR_$1 = $(OBJ_DIR)$1/
# create names of subdirectories with object files
OBJ_DIRS_$1 = $$(SRC_DIRS:$(SRC_DIR)%=$$(OBJ_DIR_$1)%)
# create names of object files
OBJ_$1 = $(SRC:$(SRC_DIR)%.c=$$(OBJ_DIR_$1)%.o)
# rule for creating subdirectories for object files
$$(OBJ_DIR_$1):
@$(MKDIR) $$(OBJ_DIR) $$@ $$(OBJ_DIRS_$1)
# rules for compilation every object file that depend on source file and header files
$$(OBJ_DIR_$1)%.o: $$(SRC_DIR)%.c $$(HDR)
@$(PRINT) "$K$G COMPILING $Y[$M$1$Y] $B$$(<:$(SRC_DIR)%=%)$D\r"
@$(COMPILE) $2 $$(DEP_IFLAGS) -o $$@ -c $$<
# rule for creating executable from object files
$$(NAME_$1): $$(OBJ_DIR_$1) $$(OBJ_$1) $$(HDR) $$(BUILD_TARGETS)
@$(PRINT) "$K$G COMPILING $Y[$M$1$Y] $R$$@$D\r"
ifeq ($1,default)
@$(BUILD) $2 $$(DEP_IFLAGS) $$(DEP_LFLAGS) $$(DEP_lFLAGS) $$(OBJ_$1) -o $$@
else
# if not default build, then should use libs with same build type
@$(BUILD) $2 $$(DEP_IFLAGS) $$(DEP_LFLAGS) $$(foreach f, $$(DEP_lFLAGS), $$(f:%=%_$1)) $$(OBJ_$1) -o $$@
endif
endef
# generates linking to depend makefiles libraries
$(eval $(call DEPENDENCY_template,libmx/inc,libmx,mx))
# generates calling rules of depend makefiles
$(eval $(call DEPENDENT_MAKE_template,libmx.a,libmx))
# generates build targets from template
$(eval $(call BUILD_template,default,))
$(eval $(call BUILD_template,release,-Ofast -march=native -flto))
$(eval $(call BUILD_template,debug,$(DFLAGS)))
$(eval $(call BUILD_template,debug_address,$(DFLAGS) -fsanitize=address -fno-sanitize=null -fno-sanitize=alignment))
$(eval $(call BUILD_template,debug_undefined,$(DFLAGS) -fsanitize=undefined -fno-sanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow))
$(eval $(call BUILD_template,debug_address_undefined,$(DFLAGS) -fsanitize=address,undefined -fno-sanitize-recover=all -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fno-sanitize=null -fno-sanitize=alignment))
$(eval $(call BUILD_template,debug_leak,$(DFLAGS) -fsanitize=address))
$(eval $(call BUILD_template,debug_memory,$(DFLAGS) -fsanitize=memory))
$(eval $(call BUILD_template,debug_thread,$(DFLAGS) -fsanitize=thread))
# default rule
all: $(MAKE_TARGETS) $(BUILD_NAMES)
@$(PRINT) "$K$S╔═══════════════════════════════════════════════════════════════════════════════════════════════════╗\n\
║ ║\n\
║ $C██$M╗ $C██$M╗$C██$M╗ $C███████$M╗ $C██$M╗$C███████$M╗ $C██████$M╗ $C███████$M╗ $C█████$M╗ $C██████$M╗ $C██$M╗ $C██$M╗ $S║\n\
║ $C██$M║ $C██$M║$C██$M║ $C██$M╔════╝ $C██$M║$C██$M╔════╝ $C██$M╔══$C██$M╗$C██$M╔════╝$C██$M╔══$C██$M╗$C██$M╔══$C██$M╗╚$C██$M╗ $C██$M╔╝ $S║\n\
║ $C██$M║ $C██$M║$C██$M║ $C███████$M╗ $C██$M║$C███████$M╗ $C██████$M╔╝$C█████$M╗ $C███████$M║$C██$M║ $C██$M║ ╚$C████$M╔╝ $S║\n\
║ $C██$M║ $C██$M║$C██$M║ ╚════$C██$M║ $C██$M║╚════$C██$M║ $C██$M╔══$C██$M╗$C██$M╔══╝ $C██$M╔══$C██$M║$C██$M║ $C██$M║ ╚$C██$M╔╝ $S║\n\
║ $M╚$C██████$M╔╝$C███████$M╗$C███████$M║ $C██$M║$C███████$M║ $C██$M║ $C██$M║$C███████$M╗$C██$M║ $C██$M║$C██████$M╔╝ $C██$M║ $S║\n\
║ $M ╚═════╝ ╚══════╝╚══════╝ ╚═╝╚══════╝ ╚═╝ ╚═╝╚══════╝╚═╝ ╚═╝╚═════╝ ╚═╝ $S║\n\
║ ║\n\
╚═══════════════════════════════════════════════════════════════════════════════════════════════════╝\n$D"
# deletes directory with object files
clean: $(CLEAN_TARGETS)
@$(RM) $(OBJ_DIR)
# deletes directory with object files and libraries
uninstall: $(UNINSTALL_TARGETS)
@$(RM) $(OBJ_DIR) $(BUILD_NAMES)
reinstall: uninstall all
# prevents errors if some item in current directory named same as one of this targets
.PHONY: all clean uninstall reinstall