-
Notifications
You must be signed in to change notification settings - Fork 0
/
common.mk
executable file
·323 lines (267 loc) · 11.8 KB
/
common.mk
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
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
ARCHTUPLE=arm-none-eabi-
DEVICE=VEX EDR V5
# User toggles for controlling compiler flags for builds
# ALWAYS run `make clean-bin` before changing these flags
DEBUG_LEVEL := 0
ANALYZE_LEVEL := 0
ifeq ($(DEBUG_LEVEL), 1)
DEBUG_FLAGS += -fsanitize=float-divide-by-zero -fsanitize=float-cast-overflow -fsanitize=leak -fsanitize=signed-integer-overflow -fsanitize=bounds -fno-sanitize=null -fno-sanitize=alignment
endif
ifeq ($(ANALYZE_LEVEL), 1)
ANALYZE_FLAGS += -fanalyzer
endif
# Optimization flags for the compiler - https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
OPTIM_FLAGS :=
MFLAGS=-mcpu=cortex-a9 -mfpu=neon-fp16 -mfloat-abi=softfp -Os -g
CPPFLAGS=-D_POSIX_THREADS -D_UNIX98_THREAD_MUTEX_ATTRIBUTES -D_POSIX_TIMERS -D_POSIX_MONOTONIC_CLOCK
GCCFLAGS=-ffunction-sections -fdata-sections -fdiagnostics-color -funwind-tables $(DEBUG_FLAGS) $(ANALYZE_FLAGS) $(OPTIM_FLAGS)
# Check if the llemu files in libvgl exist. If they do, define macros that the
# llemu headers in the kernel repo can use to conditionally include the libvgl
# versions
ifneq (,$(wildcard ./include/liblvgl/llemu.h))
CPPFLAGS += -D_PROS_INCLUDE_LIBLVGL_LLEMU_H
endif
ifneq (,$(wildcard ./include/liblvgl/llemu.hpp))
CPPFLAGS += -D_PROS_INCLUDE_LIBLVGL_LLEMU_HPP
endif
WARNFLAGS+=-Wno-psabi
SPACE := $() $()
COMMA := ,
C_STANDARD?=gnu11
CXX_STANDARD?=gnu++20
DEPDIR := .d
$(shell mkdir -p $(DEPDIR))
DEPFLAGS = -MT $$@ -MMD -MP -MF $(DEPDIR)/$$*.Td
MAKEDEPFOLDER = -$(VV)mkdir -p $(DEPDIR)/$$(dir $$(patsubst $(BINDIR)/%, %, $(ROOT)/$$@))
RENAMEDEPENDENCYFILE = -$(VV)mv -f $(DEPDIR)/$$*.Td $$(patsubst $(SRCDIR)/%, $(DEPDIR)/%.d, $(ROOT)/$$<) && touch $$@
LIBRARIES+=$(wildcard $(FWDIR)/*.a)
# Cannot include newlib and libc because not all of the req'd stubs are implemented
EXCLUDE_COLD_LIBRARIES+=$(FWDIR)/libc.a $(FWDIR)/libm.a
COLD_LIBRARIES=$(filter-out $(EXCLUDE_COLD_LIBRARIES), $(LIBRARIES))
wlprefix=-Wl,$(subst $(SPACE),$(COMMA),$1)
LNK_FLAGS=--gc-sections --start-group $(strip $(LIBRARIES)) -lgcc -lstdc++ --end-group -T$(FWDIR)/v5-common.ld
ASMFLAGS=$(MFLAGS) $(WARNFLAGS)
CFLAGS=$(MFLAGS) $(CPPFLAGS) $(WARNFLAGS) $(GCCFLAGS) --std=$(C_STANDARD)
CXXFLAGS=$(MFLAGS) $(CPPFLAGS) $(WARNFLAGS) $(GCCFLAGS) --std=$(CXX_STANDARD)
LDFLAGS=$(MFLAGS) $(WARNFLAGS) -nostdlib $(GCCFLAGS)
SIZEFLAGS=-d --common
NUMFMTFLAGS=--to=iec --format %.2f --suffix=B
AR:=$(ARCHTUPLE)ar
# using arm-none-eabi-as generates a listing by default. This produces a super verbose output.
# Using gcc accomplishes the same thing without the extra output
AS:=$(ARCHTUPLE)gcc
CC:=$(ARCHTUPLE)gcc
CXX:=$(ARCHTUPLE)g++
LD:=$(ARCHTUPLE)g++
OBJCOPY:=$(ARCHTUPLE)objcopy
SIZETOOL:=$(ARCHTUPLE)size
READELF:=$(ARCHTUPLE)readelf
STRIP:=$(ARCHTUPLE)strip
ifneq (, $(shell command -v gnumfmt 2> /dev/null))
SIZES_NUMFMT:=| gnumfmt --field=-4 --header $(NUMFMTFLAGS)
else
ifneq (, $(shell command -v numfmt 2> /dev/null))
SIZES_NUMFMT:=| numfmt --field=-4 --header $(NUMFMTFLAGS)
else
SIZES_NUMFMT:=
endif
endif
ifneq (, $(shell command -v sed 2> /dev/null))
SIZES_SED:=| sed -e 's/ dec/total/'
else
SIZES_SED:=
endif
rwildcard=$(foreach d,$(filter-out $3,$(wildcard $1*)),$(call rwildcard,$d/,$2,$3)$(filter $(subst *,%,$2),$d))
# Colors
NO_COLOR=$(shell printf "%b" "\033[0m")
OK_COLOR=$(shell printf "%b" "\033[32;01m")
ERROR_COLOR=$(shell printf "%b" "\033[31;01m")
WARN_COLOR=$(shell printf "%b" "\033[33;01m")
STEP_COLOR=$(shell printf "%b" "\033[37;01m")
OK_STRING=$(OK_COLOR)[OK]$(NO_COLOR)
DONE_STRING=$(OK_COLOR)[DONE]$(NO_COLOR)
ERROR_STRING=$(ERROR_COLOR)[ERRORS]$(NO_COLOR)
WARN_STRING=$(WARN_COLOR)[WARNINGS]$(NO_COLOR)
ECHO=/bin/printf "%s\n"
echo=@$(ECHO) "$2$1$(NO_COLOR)"
echon=@/bin/printf "%s" "$2$1$(NO_COLOR)"
define test_output_2
@if test $(BUILD_VERBOSE) -eq $(or $4,1); then printf "%s\n" "$2"; fi;
@output="$$($2 2>&1)"; exit=$$?; \
if test 0 -ne $$exit; then \
printf "%s%s\n" "$1" "$(ERROR_STRING)"; \
printf "%s\n" "$$output"; \
exit $$exit; \
elif test -n "$$output"; then \
printf "%s%s\n" "$1" "$(WARN_STRING)"; \
printf "%s\n" "$$output"; \
else \
printf "%s%s\n" "$1" "$3"; \
fi;
endef
define test_output
@output=$$($1 2>&1); exit=$$?; \
if test 0 -ne $$exit; then \
printf "%s\n" "$(ERROR_STRING)" $$?; \
printf "%s\n" $$output; \
exit $$exit; \
elif test -n "$$output"; then \
printf "%s\n" "$(WARN_STRING)"; \
printf "%s" $$output; \
else \
printf "%s\n" "$2"; \
fi;
endef
# Makefile Verbosity
ifeq ("$(origin VERBOSE)", "command line")
BUILD_VERBOSE = $(VERBOSE)
endif
ifeq ("$(origin V)", "command line")
BUILD_VERBOSE = $(V)
endif
ifndef BUILD_VERBOSE
BUILD_VERBOSE = 0
endif
# R is reduced (default messages) - build verbose = 0
# V is verbose messages - verbosity = 1
# VV is super verbose - verbosity = 2
ifeq ($(BUILD_VERBOSE), 0)
R = @echo
D = @
VV = @
endif
ifeq ($(BUILD_VERBOSE), 1)
R = @echo
D =
VV = @
endif
ifeq ($(BUILD_VERBOSE), 2)
R =
D =
VV =
endif
INCLUDE=$(foreach dir,$(INCDIR) $(EXTRA_INCDIR),-iquote"$(dir)")
ASMSRC=$(foreach asmext,$(ASMEXTS),$(call rwildcard, $(SRCDIR),*.$(asmext), $1))
ASMOBJ=$(addprefix $(BINDIR)/,$(patsubst $(SRCDIR)/%,%.o,$(call ASMSRC,$1)))
CSRC=$(foreach cext,$(CEXTS),$(call rwildcard, $(SRCDIR),*.$(cext), $1))
COBJ=$(addprefix $(BINDIR)/,$(patsubst $(SRCDIR)/%,%.o,$(call CSRC, $1)))
CXXSRC=$(foreach cxxext,$(CXXEXTS),$(call rwildcard, $(SRCDIR),*.$(cxxext), $1))
CXXOBJ=$(addprefix $(BINDIR)/,$(patsubst $(SRCDIR)/%,%.o,$(call CXXSRC,$1)))
GETALLOBJ=$(sort $(call ASMOBJ,$1) $(call COBJ,$1) $(call CXXOBJ,$1))
ARCHIVE_TEXT_LIST=$(subst $(SPACE),$(COMMA),$(notdir $(basename $(LIBRARIES))))
LDTIMEOBJ:=$(BINDIR)/_pros_ld_timestamp.o
MONOLITH_BIN:=$(BINDIR)/monolith.bin
MONOLITH_ELF:=$(basename $(MONOLITH_BIN)).elf
HOT_BIN:=$(BINDIR)/hot.package.bin
HOT_ELF:=$(basename $(HOT_BIN)).elf
COLD_BIN:=$(BINDIR)/cold.package.bin
COLD_ELF:=$(basename $(COLD_BIN)).elf
# Check if USE_PACKAGE is defined to check for migration steps from purduesigbots/pros#87
ifndef USE_PACKAGE
$(error Your Makefile must be migrated! Visit https://pros.cs.purdue.edu/v5/releases/kernel3.1.6.html to learn how)
endif
DEFAULT_BIN=$(MONOLITH_BIN)
ifeq ($(USE_PACKAGE),1)
DEFAULT_BIN=$(HOT_BIN)
endif
-include $(wildcard $(FWDIR)/*.mk)
.PHONY: all clean quick
quick: $(DEFAULT_BIN)
all: clean $(DEFAULT_BIN)
clean:
@echo Cleaning project
-$Drm -rf $(BINDIR)
-$Drm -rf $(DEPDIR)
ifeq ($(IS_LIBRARY),1)
ifeq ($(LIBNAME),libbest)
$(errror "You should rename your library! libbest is the default library name and should be changed")
endif
LIBAR=$(BINDIR)/$(LIBNAME).a
TEMPLATE_DIR=$(ROOT)/template
clean-template:
@echo Cleaning $(TEMPLATE_DIR)
-$Drm -rf $(TEMPLATE_DIR)
$(LIBAR): $(call GETALLOBJ,$(EXCLUDE_SRC_FROM_LIB)) $(EXTRA_LIB_DEPS)
-$Drm -f $@
$(call test_output_2,Creating $@ ,$(AR) rcs $@ $^, $(DONE_STRING))
.PHONY: library
library: $(LIBAR)
.PHONY: template
template: clean-template $(LIBAR)
$Dpros c create-template . $(LIBNAME) $(VERSION) $(foreach file,$(TEMPLATE_FILES) $(LIBAR),--system "$(file)") --target v5 $(CREATE_TEMPLATE_FLAGS)
endif
# if project is a library source, compile the archive and link output.elf against the archive rather than source objects
ifeq ($(IS_LIBRARY),1)
ELF_DEPS+=$(filter-out $(call GETALLOBJ,$(EXCLUDE_SRC_FROM_LIB)), $(call GETALLOBJ,$(EXCLUDE_SRCDIRS)))
LIBRARIES+=$(LIBAR)
else
ELF_DEPS+=$(call GETALLOBJ,$(EXCLUDE_SRCDIRS))
endif
$(MONOLITH_BIN): $(MONOLITH_ELF) $(BINDIR)
$(call test_output_2,Creating $@ for $(DEVICE) ,$(OBJCOPY) $< -O binary -R .hot_init $@,$(DONE_STRING))
$(MONOLITH_ELF): $(ELF_DEPS) $(LIBRARIES)
$(call _pros_ld_timestamp)
$(call test_output_2,Linking project with $(ARCHIVE_TEXT_LIST) ,$(LD) $(LDFLAGS) $(ELF_DEPS) $(LDTIMEOBJ) $(call wlprefix,-T$(FWDIR)/v5.ld $(LNK_FLAGS)) -o $@,$(OK_STRING))
@echo Section sizes:
-$(VV)$(SIZETOOL) $(SIZEFLAGS) $@ $(SIZES_SED) $(SIZES_NUMFMT)
$(COLD_BIN): $(COLD_ELF)
$(call test_output_2,Creating cold package binary for $(DEVICE) ,$(OBJCOPY) $< -O binary -R .hot_init $@,$(DONE_STRING))
$(COLD_ELF): $(COLD_LIBRARIES)
$(VV)mkdir -p $(dir $@)
$(call test_output_2,Creating cold package with $(ARCHIVE_TEXT_LIST) ,$(LD) $(LDFLAGS) $(call wlprefix,--gc-keep-exported --whole-archive $^ -lstdc++ --no-whole-archive) $(call wlprefix,-T$(FWDIR)/v5.ld $(LNK_FLAGS) -o $@),$(OK_STRING))
$(call test_output_2,Stripping cold package ,$(OBJCOPY) --strip-symbol=install_hot_table --strip-symbol=__libc_init_array --strip-symbol=_PROS_COMPILE_DIRECTORY --strip-symbol=_PROS_COMPILE_TIMESTAMP --strip-symbol=_PROS_COMPILE_TIMESTAMP_INT $@ $@, $(DONE_STRING))
@echo Section sizes:
-$(VV)$(SIZETOOL) $(SIZEFLAGS) $@ $(SIZES_SED) $(SIZES_NUMFMT)
$(HOT_BIN): $(HOT_ELF) $(COLD_BIN)
$(call test_output_2,Creating $@ for $(DEVICE) ,$(OBJCOPY) $< -O binary $@,$(DONE_STRING))
$(HOT_ELF): $(COLD_ELF) $(ELF_DEPS)
$(call _pros_ld_timestamp)
$(call test_output_2,Linking hot project with $(COLD_ELF) and $(ARCHIVE_TEXT_LIST) ,$(LD) -nostartfiles $(LDFLAGS) $(call wlprefix,-R $<) $(filter-out $<,$^) $(LDTIMEOBJ) $(LIBRARIES) $(call wlprefix,-T$(FWDIR)/v5-hot.ld $(LNK_FLAGS) -o $@),$(OK_STRING))
@printf "%s\n" "Section sizes:"
-$(VV)$(SIZETOOL) $(SIZEFLAGS) $@ $(SIZES_SED) $(SIZES_NUMFMT)
define asm_rule
$(BINDIR)/%.$1.o: $(SRCDIR)/%.$1
$(VV)mkdir -p $$(dir $$@)
$$(call test_output_2,Compiled $$< ,$(AS) -c $(ASMFLAGS) -o $$@ $$<,$(OK_STRING))
endef
$(foreach asmext,$(ASMEXTS),$(eval $(call asm_rule,$(asmext))))
define c_rule
$(BINDIR)/%.$1.o: $(SRCDIR)/%.$1
$(BINDIR)/%.$1.o: $(SRCDIR)/%.$1 $(DEPDIR)/$(basename $1).d
$(VV)mkdir -p $$(dir $$@)
$(MAKEDEPFOLDER)
$$(call test_output_2,Compiled $$< ,$(CC) -c $(INCLUDE) -iquote"$(INCDIR)/$$(dir $$*)" $(CFLAGS) $(EXTRA_CFLAGS) $(DEPFLAGS) -o $$@ $$<,$(OK_STRING))
$(RENAMEDEPENDENCYFILE)
endef
$(foreach cext,$(CEXTS),$(eval $(call c_rule,$(cext))))
define cxx_rule
$(BINDIR)/%.$1.o: $(SRCDIR)/%.$1
$(BINDIR)/%.$1.o: $(SRCDIR)/%.$1 $(DEPDIR)/$(basename %).d
$(VV)mkdir -p $$(dir $$@)
$(MAKEDEPFOLDER)
$$(call test_output_2,Compiled $$< ,$(CXX) -c $(INCLUDE) -iquote"$(INCDIR)/$$(dir $$*)" $(CXXFLAGS) $(EXTRA_CXXFLAGS) $(DEPFLAGS) -o $$@ $$<,$(OK_STRING))
$(RENAMEDEPENDENCYFILE)
endef
$(foreach cxxext,$(CXXEXTS),$(eval $(call cxx_rule,$(cxxext))))
define _pros_ld_timestamp
$(VV)mkdir -p $(dir $(LDTIMEOBJ))
@# Pipe a line of code defining _PROS_COMPILE_TOOLSTAMP and _PROS_COMPILE_DIRECTORY into GCC,
@# which allows compilation from stdin. We define _PROS_COMPILE_DIRECTORY using a command line-defined macro
@# which is the pwd | tail bit, which will truncate the path to the last 23 characters
@#
@# const int _PROS_COMPILE_TIMESTAMP_INT = $(( $(date +%s) - $(date +%z) * 3600 ))
@# char const * const _PROS_COMPILE_TIEMSTAMP = __DATE__ " " __TIME__
@# char const * const _PROS_COMPILE_DIRECTORY = "$(shell pwd | tail -c 23)";
@#
@# The shell command $$(($$(date +%s)+($$(date +%-z)/100*3600))) fetches the current
@# unix timestamp, and then adds the UTC timezone offset to account for time zones.
$(call test_output_2,Adding timestamp ,echo 'const int _PROS_COMPILE_TIMESTAMP_INT = $(shell echo $$(($$(date +%s)+($$(date +%-z)/100*3600)))); char const * const _PROS_COMPILE_TIMESTAMP = __DATE__ " " __TIME__; char const * const _PROS_COMPILE_DIRECTORY = "$(wildcard $(shell pwd | tail -c 23))";' | $(CC) -c -x c $(CFLAGS) $(EXTRA_CFLAGS) -o $(LDTIMEOBJ) -,$(OK_STRING))
endef
# these rules are for build-compile-commands, which just print out sysroot information
cc-sysroot:
@echo | $(CC) -c -x c $(CFLAGS) $(EXTRA_CFLAGS) --verbose -o /dev/null -
cxx-sysroot:
@echo | $(CXX) -c -x c++ $(CXXFLAGS) $(EXTRA_CXXFLAGS) --verbose -o /dev/null -
$(DEPDIR)/%.d: ;
.PRECIOUS: $(DEPDIR)/%.d
include $(wildcard $(patsubst $(SRCDIR)/%,$(DEPDIR)/%.d,$(CSRC) $(CXXSRC)))