|
| 1 | +ARCHTUPLE=arm-none-eabi- |
| 2 | +DEVICE=VEX EDR V5 |
| 3 | + |
| 4 | +MFLAGS=-mcpu=cortex-a9 -mfpu=neon-fp16 -mfloat-abi=softfp -Os -g |
| 5 | +CPPFLAGS=-D_POSIX_THREADS -D_UNIX98_THREAD_MUTEX_ATTRIBUTES |
| 6 | +GCCFLAGS=-ffunction-sections -fdata-sections -fdiagnostics-color -funwind-tables |
| 7 | + |
| 8 | +WARNFLAGS+=-Wno-psabi |
| 9 | + |
| 10 | +SPACE := $() $() |
| 11 | +COMMA := , |
| 12 | + |
| 13 | +DEPDIR := .d |
| 14 | +$(shell mkdir -p $(DEPDIR)) |
| 15 | +DEPFLAGS = -MT $$@ -MMD -MP -MF $(DEPDIR)/$$*.Td |
| 16 | +MAKEDEPFOLDER = -$(VV)mkdir -p $(DEPDIR)/$$(dir $$(patsubst $(BINDIR)/%, %, $(ROOT)/$$@)) |
| 17 | +RENAMEDEPENDENCYFILE = -$(VV)mv -f $(DEPDIR)/$$*.Td $$(patsubst $(SRCDIR)/%, $(DEPDIR)/%.d, $(ROOT)/$$<) && touch $$@ |
| 18 | + |
| 19 | +LIBRARIES+=$(wildcard $(FWDIR)/*.a) |
| 20 | +# Cannot include newlib and libc because not all of the req'd stubs are implemented |
| 21 | +EXCLUDE_COLD_LIBRARIES+=$(FWDIR)/libc.a $(FWDIR)/libm.a |
| 22 | +COLD_LIBRARIES=$(filter-out $(EXCLUDE_COLD_LIBRARIES), $(LIBRARIES)) |
| 23 | +wlprefix=-Wl,$(subst $(SPACE),$(COMMA),$1) |
| 24 | +LNK_FLAGS=--gc-sections --start-group $(strip $(LIBRARIES)) -lgcc -lstdc++ --end-group -T$(FWDIR)/v5-common.ld |
| 25 | + |
| 26 | +ASMFLAGS=$(MFLAGS) $(WARNFLAGS) |
| 27 | +CFLAGS=$(MFLAGS) $(CPPFLAGS) $(WARNFLAGS) $(GCCFLAGS) --std=gnu11 |
| 28 | +CXXFLAGS=$(MFLAGS) $(CPPFLAGS) $(WARNFLAGS) $(GCCFLAGS) --std=gnu++17 |
| 29 | +LDFLAGS=$(MFLAGS) $(WARNFLAGS) -nostdlib $(GCCFLAGS) |
| 30 | +SIZEFLAGS=-d --common |
| 31 | +NUMFMTFLAGS=--to=iec --format %.2f --suffix=B |
| 32 | + |
| 33 | +AR:=$(ARCHTUPLE)ar |
| 34 | +# using arm-none-eabi-as generates a listing by default. This produces a super verbose output. |
| 35 | +# Using gcc accomplishes the same thing without the extra output |
| 36 | +AS:=$(ARCHTUPLE)gcc |
| 37 | +CC:=$(ARCHTUPLE)gcc |
| 38 | +CXX:=$(ARCHTUPLE)g++ |
| 39 | +LD:=$(ARCHTUPLE)g++ |
| 40 | +OBJCOPY:=$(ARCHTUPLE)objcopy |
| 41 | +SIZETOOL:=$(ARCHTUPLE)size |
| 42 | +READELF:=$(ARCHTUPLE)readelf |
| 43 | +STRIP:=$(ARCHTUPLE)strip |
| 44 | + |
| 45 | +ifneq (, $(shell command -v gnumfmt 2> /dev/null)) |
| 46 | + SIZES_NUMFMT:=| gnumfmt --field=-4 --header $(NUMFMTFLAGS) |
| 47 | +else |
| 48 | +ifneq (, $(shell command -v numfmt 2> /dev/null)) |
| 49 | + SIZES_NUMFMT:=| numfmt --field=-4 --header $(NUMFMTFLAGS) |
| 50 | +else |
| 51 | + SIZES_NUMFMT:= |
| 52 | +endif |
| 53 | +endif |
| 54 | + |
| 55 | +ifneq (, $(shell command -v sed 2> /dev/null)) |
| 56 | +SIZES_SED:=| sed -e 's/ dec/total/' |
| 57 | +else |
| 58 | +SIZES_SED:= |
| 59 | +endif |
| 60 | + |
| 61 | +rwildcard=$(foreach d,$(filter-out $3,$(wildcard $1*)),$(call rwildcard,$d/,$2,$3)$(filter $(subst *,%,$2),$d)) |
| 62 | + |
| 63 | +# Colors |
| 64 | +NO_COLOR=$(shell printf "%b" "\033[0m") |
| 65 | +OK_COLOR=$(shell printf "%b" "\033[32;01m") |
| 66 | +ERROR_COLOR=$(shell printf "%b" "\033[31;01m") |
| 67 | +WARN_COLOR=$(shell printf "%b" "\033[33;01m") |
| 68 | +STEP_COLOR=$(shell printf "%b" "\033[37;01m") |
| 69 | +OK_STRING=$(OK_COLOR)[OK]$(NO_COLOR) |
| 70 | +DONE_STRING=$(OK_COLOR)[DONE]$(NO_COLOR) |
| 71 | +ERROR_STRING=$(ERROR_COLOR)[ERRORS]$(NO_COLOR) |
| 72 | +WARN_STRING=$(WARN_COLOR)[WARNINGS]$(NO_COLOR) |
| 73 | +ECHO=/bin/printf "%s\n" |
| 74 | +echo=@$(ECHO) "$2$1$(NO_COLOR)" |
| 75 | +echon=@/bin/printf "%s" "$2$1$(NO_COLOR)" |
| 76 | + |
| 77 | +define test_output_2 |
| 78 | +@if test $(BUILD_VERBOSE) -eq $(or $4,1); then printf "%s\n" "$2"; fi; |
| 79 | +@output="$$($2 2>&1)"; exit=$$?; \ |
| 80 | +if test 0 -ne $$exit; then \ |
| 81 | + printf "%s%s\n" "$1" "$(ERROR_STRING)"; \ |
| 82 | + printf "%s\n" "$$output"; \ |
| 83 | + exit $$exit; \ |
| 84 | +elif test -n "$$output"; then \ |
| 85 | + printf "%s%s\n" "$1" "$(WARN_STRING)"; \ |
| 86 | + printf "%s\n" "$$output"; \ |
| 87 | +else \ |
| 88 | + printf "%s%s\n" "$1" "$3"; \ |
| 89 | +fi; |
| 90 | +endef |
| 91 | + |
| 92 | +define test_output |
| 93 | +@output=$$($1 2>&1); exit=$$?; \ |
| 94 | +if test 0 -ne $$exit; then \ |
| 95 | + printf "%s\n" "$(ERROR_STRING)" $$?; \ |
| 96 | + printf "%s\n" $$output; \ |
| 97 | + exit $$exit; \ |
| 98 | +elif test -n "$$output"; then \ |
| 99 | + printf "%s\n" "$(WARN_STRING)"; \ |
| 100 | + printf "%s" $$output; \ |
| 101 | +else \ |
| 102 | + printf "%s\n" "$2"; \ |
| 103 | +fi; |
| 104 | +endef |
| 105 | + |
| 106 | +# Makefile Verbosity |
| 107 | +ifeq ("$(origin VERBOSE)", "command line") |
| 108 | +BUILD_VERBOSE = $(VERBOSE) |
| 109 | +endif |
| 110 | +ifeq ("$(origin V)", "command line") |
| 111 | +BUILD_VERBOSE = $(V) |
| 112 | +endif |
| 113 | + |
| 114 | +ifndef BUILD_VERBOSE |
| 115 | +BUILD_VERBOSE = 0 |
| 116 | +endif |
| 117 | + |
| 118 | +# R is reduced (default messages) - build verbose = 0 |
| 119 | +# V is verbose messages - verbosity = 1 |
| 120 | +# VV is super verbose - verbosity = 2 |
| 121 | +ifeq ($(BUILD_VERBOSE), 0) |
| 122 | +R = @echo |
| 123 | +D = @ |
| 124 | +VV = @ |
| 125 | +endif |
| 126 | +ifeq ($(BUILD_VERBOSE), 1) |
| 127 | +R = @echo |
| 128 | +D = |
| 129 | +VV = @ |
| 130 | +endif |
| 131 | +ifeq ($(BUILD_VERBOSE), 2) |
| 132 | +R = |
| 133 | +D = |
| 134 | +VV = |
| 135 | +endif |
| 136 | + |
| 137 | +INCLUDE=$(foreach dir,$(INCDIR) $(EXTRA_INCDIR),-iquote"$(dir)") |
| 138 | + |
| 139 | +ASMSRC=$(foreach asmext,$(ASMEXTS),$(call rwildcard, $(SRCDIR),*.$(asmext), $1)) |
| 140 | +ASMOBJ=$(addprefix $(BINDIR)/,$(patsubst $(SRCDIR)/%,%.o,$(call ASMSRC,$1))) |
| 141 | +CSRC=$(foreach cext,$(CEXTS),$(call rwildcard, $(SRCDIR),*.$(cext), $1)) |
| 142 | +COBJ=$(addprefix $(BINDIR)/,$(patsubst $(SRCDIR)/%,%.o,$(call CSRC, $1))) |
| 143 | +CXXSRC=$(foreach cxxext,$(CXXEXTS),$(call rwildcard, $(SRCDIR),*.$(cxxext), $1)) |
| 144 | +CXXOBJ=$(addprefix $(BINDIR)/,$(patsubst $(SRCDIR)/%,%.o,$(call CXXSRC,$1))) |
| 145 | + |
| 146 | +GETALLOBJ=$(sort $(call ASMOBJ,$1) $(call COBJ,$1) $(call CXXOBJ,$1)) |
| 147 | + |
| 148 | +ARCHIVE_TEXT_LIST=$(subst $(SPACE),$(COMMA),$(notdir $(basename $(LIBRARIES)))) |
| 149 | + |
| 150 | +LDTIMEOBJ:=$(BINDIR)/_pros_ld_timestamp.o |
| 151 | + |
| 152 | +MONOLITH_BIN:=$(BINDIR)/monolith.bin |
| 153 | +MONOLITH_ELF:=$(basename $(MONOLITH_BIN)).elf |
| 154 | + |
| 155 | +HOT_BIN:=$(BINDIR)/hot.package.bin |
| 156 | +HOT_ELF:=$(basename $(HOT_BIN)).elf |
| 157 | +COLD_BIN:=$(BINDIR)/cold.package.bin |
| 158 | +COLD_ELF:=$(basename $(COLD_BIN)).elf |
| 159 | + |
| 160 | +# Check if USE_PACKAGE is defined to check for migration steps from purduesigbots/pros#87 |
| 161 | +ifndef USE_PACKAGE |
| 162 | +$(error Your Makefile must be migrated! Visit https://pros.cs.purdue.edu/v5/releases/kernel3.1.6.html to learn how) |
| 163 | +endif |
| 164 | + |
| 165 | +DEFAULT_BIN=$(MONOLITH_BIN) |
| 166 | +ifeq ($(USE_PACKAGE),1) |
| 167 | +DEFAULT_BIN=$(HOT_BIN) |
| 168 | +endif |
| 169 | + |
| 170 | +-include $(wildcard $(FWDIR)/*.mk) |
| 171 | + |
| 172 | +.PHONY: all clean quick |
| 173 | + |
| 174 | +quick: $(DEFAULT_BIN) |
| 175 | + |
| 176 | +all: clean $(DEFAULT_BIN) |
| 177 | + |
| 178 | +clean: |
| 179 | + @echo Cleaning project |
| 180 | + -$Drm -rf $(BINDIR) |
| 181 | + -$Drm -rf $(DEPDIR) |
| 182 | + |
| 183 | +ifeq ($(IS_LIBRARY),1) |
| 184 | +ifeq ($(LIBNAME),libbest) |
| 185 | +$(errror "You should rename your library! libbest is the default library name and should be changed") |
| 186 | +endif |
| 187 | + |
| 188 | +LIBAR=$(BINDIR)/$(LIBNAME).a |
| 189 | +TEMPLATE_DIR=$(ROOT)/template |
| 190 | + |
| 191 | +clean-template: |
| 192 | + @echo Cleaning $(TEMPLATE_DIR) |
| 193 | + -$Drm -rf $(TEMPLATE_DIR) |
| 194 | + |
| 195 | +$(LIBAR): $(call GETALLOBJ,$(EXCLUDE_SRC_FROM_LIB)) $(EXTRA_LIB_DEPS) |
| 196 | + -$Drm -f $@ |
| 197 | + $(call test_output_2,Creating $@ ,$(AR) rcs $@ $^, $(DONE_STRING)) |
| 198 | + |
| 199 | +.PHONY: library |
| 200 | +library: $(LIBAR) |
| 201 | + |
| 202 | +.PHONY: template |
| 203 | +template: clean-template $(LIBAR) |
| 204 | + $Dprosv5 c create-template . $(LIBNAME) $(VERSION) $(foreach file,$(TEMPLATE_FILES) $(LIBAR),--system "$(file)") --target v5 $(CREATE_TEMPLATE_FLAGS) |
| 205 | +endif |
| 206 | + |
| 207 | +# if project is a library source, compile the archive and link output.elf against the archive rather than source objects |
| 208 | +ifeq ($(IS_LIBRARY),1) |
| 209 | +ELF_DEPS+=$(filter-out $(call GETALLOBJ,$(EXCLUDE_SRC_FROM_LIB)), $(call GETALLOBJ,$(EXCLUDE_SRCDIRS))) |
| 210 | +LIBRARIES+=$(LIBAR) |
| 211 | +else |
| 212 | +ELF_DEPS+=$(call GETALLOBJ,$(EXCLUDE_SRCDIRS)) |
| 213 | +endif |
| 214 | + |
| 215 | +$(MONOLITH_BIN): $(MONOLITH_ELF) $(BINDIR) |
| 216 | + $(call test_output_2,Creating $@ for $(DEVICE) ,$(OBJCOPY) $< -O binary -R .hot_init $@,$(DONE_STRING)) |
| 217 | + |
| 218 | +$(MONOLITH_ELF): $(ELF_DEPS) $(LIBRARIES) |
| 219 | + $(call _pros_ld_timestamp) |
| 220 | + $(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)) |
| 221 | + @echo Section sizes: |
| 222 | + -$(VV)$(SIZETOOL) $(SIZEFLAGS) $@ $(SIZES_SED) $(SIZES_NUMFMT) |
| 223 | + |
| 224 | +$(COLD_BIN): $(COLD_ELF) |
| 225 | + $(call test_output_2,Creating cold package binary for $(DEVICE) ,$(OBJCOPY) $< -O binary -R .hot_init $@,$(DONE_STRING)) |
| 226 | + |
| 227 | +$(COLD_ELF): $(COLD_LIBRARIES) |
| 228 | + $(VV)mkdir -p $(dir $@) |
| 229 | + $(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)) |
| 230 | + $(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 $@ $@, $(DONE_STRING)) |
| 231 | + @echo Section sizes: |
| 232 | + -$(VV)$(SIZETOOL) $(SIZEFLAGS) $@ $(SIZES_SED) $(SIZES_NUMFMT) |
| 233 | + |
| 234 | +$(HOT_BIN): $(HOT_ELF) $(COLD_BIN) |
| 235 | + $(call test_output_2,Creating $@ for $(DEVICE) ,$(OBJCOPY) $< -O binary $@,$(DONE_STRING)) |
| 236 | + |
| 237 | +$(HOT_ELF): $(COLD_ELF) $(ELF_DEPS) |
| 238 | + $(call _pros_ld_timestamp) |
| 239 | + $(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)) |
| 240 | + @printf "%s\n" "Section sizes:" |
| 241 | + -$(VV)$(SIZETOOL) $(SIZEFLAGS) $@ $(SIZES_SED) $(SIZES_NUMFMT) |
| 242 | + |
| 243 | +define asm_rule |
| 244 | +$(BINDIR)/%.$1.o: $(SRCDIR)/%.$1 |
| 245 | + $(VV)mkdir -p $$(dir $$@) |
| 246 | + $$(call test_output_2,Compiled $$< ,$(AS) -c $(ASMFLAGS) -o $$@ $$<,$(OK_STRING)) |
| 247 | +endef |
| 248 | +$(foreach asmext,$(ASMEXTS),$(eval $(call asm_rule,$(asmext)))) |
| 249 | + |
| 250 | +define c_rule |
| 251 | +$(BINDIR)/%.$1.o: $(SRCDIR)/%.$1 |
| 252 | +$(BINDIR)/%.$1.o: $(SRCDIR)/%.$1 $(DEPDIR)/$(basename $1).d |
| 253 | + $(VV)mkdir -p $$(dir $$@) |
| 254 | + $(MAKEDEPFOLDER) |
| 255 | + $$(call test_output_2,Compiled $$< ,$(CC) -c $(INCLUDE) -iquote"$(INCDIR)/$$(dir $$*)" $(CFLAGS) $(EXTRA_CFLAGS) $(DEPFLAGS) -o $$@ $$<,$(OK_STRING)) |
| 256 | + $(RENAMEDEPENDENCYFILE) |
| 257 | +endef |
| 258 | +$(foreach cext,$(CEXTS),$(eval $(call c_rule,$(cext)))) |
| 259 | + |
| 260 | +define cxx_rule |
| 261 | +$(BINDIR)/%.$1.o: $(SRCDIR)/%.$1 |
| 262 | +$(BINDIR)/%.$1.o: $(SRCDIR)/%.$1 $(DEPDIR)/$(basename %).d |
| 263 | + $(VV)mkdir -p $$(dir $$@) |
| 264 | + $(MAKEDEPFOLDER) |
| 265 | + $$(call test_output_2,Compiled $$< ,$(CXX) -c $(INCLUDE) -iquote"$(INCDIR)/$$(dir $$*)" $(CXXFLAGS) $(EXTRA_CXXFLAGS) $(DEPFLAGS) -o $$@ $$<,$(OK_STRING)) |
| 266 | + $(RENAMEDEPENDENCYFILE) |
| 267 | +endef |
| 268 | +$(foreach cxxext,$(CXXEXTS),$(eval $(call cxx_rule,$(cxxext)))) |
| 269 | + |
| 270 | +define _pros_ld_timestamp |
| 271 | +$(VV)mkdir -p $(dir $(LDTIMEOBJ)) |
| 272 | +@# Pipe a line of code defining _PROS_COMPILE_TOOLSTAMP and _PROS_COMPILE_DIRECTORY into GCC, |
| 273 | +@# which allows compilation from stdin. We define _PROS_COMPILE_DIRECTORY using a command line-defined macro |
| 274 | +@# which is the pwd | tail bit, which will truncate the path to the last 23 characters |
| 275 | +$(call test_output_2,Adding timestamp ,echo 'char const * const _PROS_COMPILE_TIMESTAMP = __DATE__ " " __TIME__; char const * const _PROS_COMPILE_DIRECTORY = "$(shell pwd | tail -c 23)";' | $(CC) -c -x c $(CFLAGS) $(EXTRA_CFLAGS) -o $(LDTIMEOBJ) -,$(OK_STRING)) |
| 276 | +endef |
| 277 | + |
| 278 | +# these rules are for build-compile-commands, which just print out sysroot information |
| 279 | +cc-sysroot: |
| 280 | + @echo | $(CC) -c -x c $(CFLAGS) $(EXTRA_CFLAGS) --verbose -o /dev/null - |
| 281 | +cxx-sysroot: |
| 282 | + @echo | $(CXX) -c -x c++ $(CXXFLAGS) $(EXTRA_CXXFLAGS) --verbose -o /dev/null - |
| 283 | + |
| 284 | +$(DEPDIR)/%.d: ; |
| 285 | +.PRECIOUS: $(DEPDIR)/%.d |
| 286 | + |
| 287 | +include $(wildcard $(patsubst $(SRCDIR)/%,$(DEPDIR)/%.d,$(CSRC) $(CXXSRC))) |
0 commit comments