eive-obsw/Makefile-Hosted

431 lines
13 KiB
Plaintext

#-------------------------------------------------------------------------------
# Makefile for SOURCE OBSW
#-------------------------------------------------------------------------------
# User-modifiable options
#-------------------------------------------------------------------------------
# Fundamentals on the build process of C/C++ Software:
# https://www3.ntu.edu.sg/home/ehchua/programming/cpp/gcc_make.html
# Make documentation: https://www.gnu.org/software/make/manual/make.pdf
# Online: https://www.gnu.org/software/make/manual/make.html
# General rules: http://make.mad-scientist.net/papers/rules-of-makefiles/#rule3
SHELL = /bin/sh
CUSTOM_DEFINES :=
# Chip & board used for compilation
# (can be overriden by adding CHIP=chip and BOARD=board to the command-line)
BOARD_FILE_ROOT = hosted
BOARD = host
OS_FSFW = host
CUSTOM_DEFINES += -D$(OS_FSFW)
# Copied from stackoverflow, can be used to differentiate between Windows
# and Linux
ifeq ($(OS),Windows_NT)
CUSTOM_DEFINES += -DWIN32
ifeq ($(PROCESSOR_ARCHITEW6432),AMD64)
CUSTOM_DEFINES += -DAMD64
else
ifeq ($(PROCESSOR_ARCHITECTURE),AMD64)
CUSTOM_DEFINES += -DAMD64
endif
ifeq ($(PROCESSOR_ARCHITECTURE),x86)
CUSTOM_DEFINES += -DIA32
endif
endif
else
UNAME_S := $(shell uname -s)
ifeq ($(UNAME_S),Linux)
DETECTED_OS = LINUX
CUSTOM_DEFINES += -DLINUX
endif
ifeq ($(UNAME_S),Darwin)
CUSTOM_DEFINES += -DOSX
endif
UNAME_P := $(shell uname -p)
ifeq ($(UNAME_P),x86_64)
CUSTOM_DEFINES += -DAMD64
endif
ifneq ($(filter %86,$(UNAME_P)),)
CUSTOM_DEFINES += -DIA32
endif
ifneq ($(filter arm%,$(UNAME_P)),)
CUSTOM_DEFINES += -DARM
endif
endif
# General folder paths
FRAMEWORK_PATH = fsfw
MISSION_PATH = mission
CONFIG_PATH = $(BOARD_FILE_ROOT)/config
TEST_PATH = test
UNITTEST_PATH = unittest
# Board specific paths
BSP_PATH = $(BOARD_FILE_ROOT)
BOARDTEST_PATH = $(BOARD_FILE_ROOT)/boardtest
# Output file basename
BASENAME = eiveobsw
BINARY_NAME = $(BASENAME)-$(BOARD)
# Output files will be put in this directory inside
OUTPUT_FOLDER = $(OS_FSFW)
# Default debug output
DEBUG_LEVEL = -g3
# Optimization level. -O0 default, -Os for size, -O3 for speed and size.
OPTIMIZATION = -O0
ifdef GCOV
CUSTOM_DEFINES += -DGCOV
endif
# Output directories
BUILDPATH = _bin
DEPENDPATH = _dep
OBJECTPATH = _obj
ifeq ($(MAKECMDGOALS),release)
BUILD_FOLDER = mission
else
BUILD_FOLDER = devel
endif
DEPENDDIR = $(DEPENDPATH)/$(OUTPUT_FOLDER)/$(BUILD_FOLDER)
OBJDIR = $(OBJECTPATH)/$(OUTPUT_FOLDER)/$(BUILD_FOLDER)
BINDIR = $(BUILDPATH)/$(OUTPUT_FOLDER)/$(BUILD_FOLDER)
CLEANDEP = $(DEPENDPATH)/$(OUTPUT_FOLDER)
CLEANOBJ = $(OBJECTPATH)/$(OUTPUT_FOLDER)
CLEANBIN = $(BUILDPATH)/$(OUTPUT_FOLDER)
#-------------------------------------------------------------------------------
# Tools and Includes
#-------------------------------------------------------------------------------
# Tool suffix when cross-compiling
CROSS_COMPILE =
# C Compiler
CC = $(CROSS_COMPILE)gcc
# C++ compiler
CXX = $(CROSS_COMPILE)g++
# Additional Tools
SIZE = $(CROSS_COMPILE)size
STRIP = $(CROSS_COMPILE)strip
CP = $(CROSS_COMPILE)objcopy
HEXCOPY = $(CP) -O ihex
BINCOPY = $(CP) -O binary
# files to be compiled, will be filled in by include makefiles
# := assignment here is neccessary as initialization so that the +=
# operator can be used in the submakefiles to achieve immediate evaluation.
# See: http://make.mad-scientist.net/evaluation-and-expansion/
CSRC :=
CXXSRC :=
ASRC :=
INCLUDES :=
# Directories where $(directoryname).mk files should be included from
SUBDIRS := $(FRAMEWORK_PATH) $(TEST_PATH) $(BSP_PATH) \
$(CONFIG_PATH) $(MISSION_PATH)
# $(MISSION_PATH) $(CONFIG_PATH)
# INCLUDES += framework/test/catch2
# ETL library include.
ETL_PATH = etl/include
I_INCLUDES += -I$(ETL_PATH)
I_INCLUDES += $(addprefix -I, $(INCLUDES))
# This is a hack from http://make.mad-scientist.net/the-eval-function/
#
# The problem is, that included makefiles should be aware of their relative path
# but not need to guess or hardcode it. So we set $(CURRENTPATH) for them. If
# we do this globally and the included makefiles want to include other makefiles as
# well, they would overwrite $(CURRENTPATH), screwing the include after them.
#
# By using a for-loop with an eval'd macro, we can generate the code to include all
# sub-makefiles (with the correct $(CURRENTPATH) set) before actually evaluating
# (and by this possibly changing $(CURRENTPATH)) them.
#
# This works recursively, if an included makefile wants to include, it can safely set
# $(SUBDIRS) (which has already been evaluated here) and do
# "$(foreach S,$(SUBDIRS),$(eval $(INCLUDE_FILE)))"
# $(SUBDIRS) must be relative to the project root, so to include subdir foo, set
# $(SUBDIRS) = $(CURRENTPATH)/foo.
define INCLUDE_FILE
CURRENTPATH := $S
include $(S)/$(notdir $S).mk
endef
$(foreach S,$(SUBDIRS),$(eval $(INCLUDE_FILE)))
#-------------------------------------------------------------------------------
# Source Files
#-------------------------------------------------------------------------------
# Additional source files which were not includes by other .mk
# files are added here.
# To help Makefile find source files, the source location paths
# can be added by using the VPATH variable
# See: https://www.gnu.org/software/make/manual/html_node/General-Search.html
# It is recommended to only use VPATH to add source locations
# See: http://make.mad-scientist.net/papers/how-not-to-use-vpath/
# Please ensure that no files are included by both .mk file and here !
# VPATH += mission/pus/
ifeq ($(DETECTED_OS), LINUX)
CXXSRC += $(FRAMEWORK_PATH)/osal/linux/TcUnixUdpPollingTask.cpp
CXXSRC += $(FRAMEWORK_PATH)/osal/linux/TmTcUnixUdpBridge.cpp
endif
# All C Sources included by .mk files are assigned here
# Add the objects to sources so dependency handling works
C_OBJECTS += $(CSRC:.c=.o)
# Objects built from Assembly source files
ASM_OBJECTS = $(ASRC:.S=.o)
# Objects built from C++ source files
CXX_OBJECTS += $(CXXSRC:.cpp=.o)
#-------------------------------------------------------------------------------
# Build Configuration + Output
#-------------------------------------------------------------------------------
TARGET = Debug
DEBUG_MESSAGE = Off
OPTIMIZATION_MESSAGE = Off
# Define Messages
MSG_INFO = Software: Hosted EIVE OBSW.
MSG_LINKING = Linking:
MSG_COMPILING = Compiling:
MSG_ASSEMBLING = Assembling:
MSG_BINARY = Generate binary:
MSG_OPTIMIZATION = Optimization: $(OPTIMIZATION), $(OPTIMIZATION_MESSAGE)
MSG_TARGET = Target Build: $(TARGET)
MSG_DEBUG = FSFW Debugging: $(DEBUG_MESSAGE)
MSG_COMIF = TMTC Communication Interface: $(COMIF_MESSAGE)
# See: https://stackoverflow.com/questions/6687630/how-to-remove-unused-c-c-symbols-with-gcc-and-ld
# Used to throw away unused code. Reduces code size significantly !
# -Wl,--gc-sections: needs to be passed to the linker to throw aways unused code
ifdef KEEP_UNUSED_CODE
PROTOTYPE_OPTIMIZATION =
DEAD_CODE_REMOVAL =
else
PROTOTYPE_OPTIMIZATION = -ffunction-sections -fdata-sections
DEAD_CODE_REMOVAL = -Wl,--gc-sections
# Link time optimization
# See https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html for reference
# Link time is larger and size of object files can not be retrieved
# but resulting binary is smaller. Could be used in mission/deployment build
# Requires -ffunction-section in linker call
LINK_TIME_OPTIMIZATION = -flto
OPTIMIZATION += $(PROTOTYPE_OPTIMIZATION)
endif
# Dependency Flags
# These flags tell the compiler to build dependencies
# See: https://www.gnu.org/software/make/manual/html_node/Automatic-Prerequisites.html
# Using following guide:
# http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/
DEPFLAGS = -MT $@ -MMD -MP -MF $(DEPENDDIR)/$*.d
# Flags for the compiler call
# - std: Which C++ version to use. Common versions: c++11, c++14 and c++17
# - Wall: enable all warnings
# - Wextra: enable extra warnings
# - g: defines debug level
# - fmessage-length: to control the formatting algorithm for diagnostic messages;
# =0 means no line-wrapping, each error message appears on a single line
# - fno-exceptions: stops generating extra code needed to propagate exceptions,
# which can produce significant data size overhead
WARNING_FLAGS = -Wall -Wshadow=local -Wextra -Wimplicit-fallthrough=1 \
-Wno-unused-parameter
CXXDEFINES := $(CUSTOM_DEFINES)
CFLAGS +=
CXXFLAGS += -I. $(DEBUG_LEVEL) $(WARNIING_FLAGS) $(I_INCLUDES) $(DEPFLAGS) \
-fmessage-length=0 $(CXXDEFINES) $(OPTIMIZATION)
CPPFLAGS += -std=c++2a -fno-exceptions
ASFLAGS = -Wall -g $(OPTIMIZATION) $(I_INCLUDES) -D__ASSEMBLY__
# Flags for the linker call
# LINK_INCLUDES specify the path to used libraries and the linker script
# LINK_LIBRARIES link HCC and HAL library and enable float support
LDFLAGS := -g3 -pthread $(DEAD_CODE_REMOVAL) $(OPTIMIZATION)
LINK_INCLUDES :=
LINK_LIBRARIES :=
ifeq ($(OS),Windows_NT)
LINK_LIBRARIES += -lwsock32 -lws2_32
endif
# Gnu Coverage Tools Flags
ifdef GCOV
GCOV_CXXFLAGS = -fprofile-arcs -ftest-coverage
CXXFLAGS += $(GCOV_CXXFLAGS)
GCOV_LINKER_LIBS = -lgcov -fprofile-arcs -ftest-coverage
LINK_LIBRARIES += $(GCOV_LINKER_LIBS)
endif
#-------------------------------------------------------------------------------
# Rules
#-------------------------------------------------------------------------------
# Makefile rules: https://www.gnu.org/software/make/manual/html_node/Rules.html
# This is the primary section which defines the ruleset to build
# the executable from the sources.
default: all
# Cleans all files
hardclean:
-rm -rf $(BUILDPATH)
-rm -rf $(OBJECTPATH)
-rm -rf $(DEPENDPATH)
# Only clean files for current build
clean:
-rm -rf $(CLEANOBJ)
-rm -rf $(CLEANBIN)
-rm -rf $(CLEANDEP)
# Only clean binaries. Useful for changing the binary type when object files are already compiled
# so complete rebuild is not necessary
cleanbin:
-rm -rf $(BUILDPATH)/$(OUTPUT_FOLDER)
# In this section, the binaries are built for all selected memories
all: executable
# Build target configuration
release: OPTIMIZATION = -Os $(PROTOTYPE_OPTIMIZATION) $(LINK_TIME_OPTIMIZATION)
release: LINK_TIME_OPTIMIZATION = -flto
release: TARGET = Release
release: OPTIMIZATION_MESSAGE = On with Link Time Optimization
release: DEBUG_LEVEL = -g0
debug: CXXDEFINES += -DDEBUG
debug: DEBUG_MESSAGE = On
ifndef KEEP_UNUSED_CODE
debug release: OPTIMIZATION_MESSAGE = Off with unused code removal
else
debug release: OPTIMIZATION_MESSAGE = Off
endif
debug release: executable
# executable: $(BINDIR)/$(BINARY_NAME).bin
ifeq ($(OS),Windows_NT)
executable: $(BINDIR)/$(BINARY_NAME).exe
else
executable: $(BINDIR)/$(BINARY_NAME).elf
endif
@echo
@echo $(MSG_INFO)
@echo $(MSG_TARGET)
@echo $(MSG_OPTIMIZATION)
@echo $(MSG_DEBUG)
C_OBJECTS_PREFIXED = $(addprefix $(OBJDIR)/, $(C_OBJECTS))
CXX_OBJECTS_PREFIXED = $(addprefix $(OBJDIR)/, $(CXX_OBJECTS))
ASM_OBJECTS_PREFIXED = $(addprefix $(OBJDIR)/, $(ASM_OBJECTS))
ALL_OBJECTS_PREFIXED = $(ASM_OBJECTS_PREFIXED) $(C_OBJECTS_PREFIXED) \
$(CXX_OBJECTS_PREFIXED)
# Useful for debugging the Makefile
# Also see: https://www.oreilly.com/openbook/make3/book/ch12.pdf
# $$(info $${CXXDEFINES} is [${CXXDEFINES}])
# $$(info $${CXXSRC} is [${CXXSRC}])
# Automatic variables are used here extensively. Some of them
# are escaped($$) to suppress immediate evaluation. The most important ones are:
# $@: Name of Target (left side of rule)
# $<: Name of the first prerequisite (right side of rule)
# @^: List of all prerequisite, omitting duplicates
# @D: Directory and file-within-directory part of $@
# Generates binary and displays all build properties
# -p with mkdir ignores error and creates directory when needed.
# SHOW_DETAILS = 1
ifeq ($(OS),Windows_NT)
$(BINDIR)/$(BINARY_NAME).exe: $(ALL_OBJECTS_PREFIXED)
else
$(BINDIR)/$(BINARY_NAME).elf: $(ALL_OBJECTS_PREFIXED)
endif
@echo
@echo $(MSG_LINKING) Target $@
@mkdir -p $(@D)
@$(CXX) $(LDFLAGS) $(LINK_INCLUDES) -o $@ $^ $(LINK_LIBRARIES)
ifeq ($(BUILD_FOLDER), mission)
# With Link Time Optimization, section size is not available
$(SIZE) $@
else
$(SIZE) $^ $@
endif
# Build new objects for changed dependencies.
$(OBJDIR)/%.o: %.cpp
$(OBJDIR)/%.o: %.cpp $(DEPENDDIR)/%.d | $(DEPENDDIR)
@echo
@echo $(MSG_COMPILING) $<
@mkdir -p $(@D)
ifdef SHOW_DETAILS
$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $<
else
@$(CXX) $(CXXFLAGS) $(CPPFLAGS) -c -o $@ $<
endif
$(OBJDIR)/%.o: %.c
$(OBJDIR)/%.o: %.c $(DEPENDDIR)/%.d | $(DEPENDDIR)
@echo
@echo $(MSG_COMPILING) $<
@mkdir -p $(@D)
ifdef SHOW_DETAILS
$(CC) $(CXXFLAGS) $(CFLAGS) -c -o $@ $<
else
@$(CC) $(CXXFLAGS) $(CFLAGS) -c -o $@ $<
endif
$(OBJDIR)/%.o: %.S Makefile
@echo
@echo $(MSG_ASSEMBLING) $<
@mkdir -p $(@D)
ifdef SHOW_DETAILS
$(CC) $(ASFLAGS) -c -o $@ $<
else
@$(CC) $(ASFLAGS) -c -o $@ $<
endif
#-------------------------------------------------------------------------------
# Dependency Handling
#-------------------------------------------------------------------------------
# Dependency Handling according to following guide:
# http://make.mad-scientist.net/papers/advanced-auto-dependency-generation/
$(DEPENDDIR):
@mkdir -p $(@D)
DEPENDENCY_RELATIVE = $(CSRC:.c=.d) $(CXXSRC:.cpp=.d)
# This is the list of all dependencies
DEPFILES = $(addprefix $(DEPENDDIR)/, $(DEPENDENCY_RELATIVE))
# Create subdirectories for dependencies
$(DEPFILES):
@mkdir -p $(@D)
# Include all dependencies
include $(wildcard $(DEPFILES))
# .PHONY tells make that these targets aren't files
.PHONY: clean sdramCfg release debug all hardclean