296 lines
11 KiB
Makefile
296 lines
11 KiB
Makefile
ARCHTUPLE=arm-none-eabi-
|
|
DEVICE=VEX EDR V5
|
|
|
|
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
|
|
|
|
WARNFLAGS+=-Wno-psabi
|
|
|
|
SPACE := $() $()
|
|
COMMA := ,
|
|
|
|
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=gnu11
|
|
CXXFLAGS=$(MFLAGS) $(CPPFLAGS) $(WARNFLAGS) $(GCCFLAGS) --std=gnu++17
|
|
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)))
|