-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMakefile
170 lines (133 loc) · 4.26 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
# SPDX-License-Identifier: MIT
# Copyright (c) 2021 Bart Bilos
# For conditions of distribution and use, see LICENSE file
# Generic project makefile
# Heavily inspired by: https://github.com/bronson/makefile-death
#
# Version: 20210425
# User definable settings are here
# Define a default project to compile, replace with wanted project
PROJECT ?= PC
# Verbose output?
VERBOSE ?= 0
# --- nothing user definable below ---
# get the root directory of the build, used below for reproducable builds
ROOT_DIR:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST))))
# Project settings like sources and target specifics
ifndef PROJECT
$(error no PROJECT defined!)
else
ifneq ("$(wildcard $(PROJECT)/$(PROJECT).mk)","")
include $(PROJECT)/$(PROJECT).mk
else
$(error $(PROJECT)/$(PROJECT).mk does not exist!)
endif
endif
# Target definition handling
ifndef TARGET
$(error Target is not defined!)
else
include targets/$(TARGET).mk
endif
# --- build engine ---
# load first config as default configuration
CONFIG ?= $(firstword $(CONFIGS))
# check if it is a valid configuration
ifeq (, $(findstring $(CONFIG),$(CONFIGS)))
$(error Unknown configuration $(CONFIG)!)
endif
# transform build specific variables to variables used by the build
COPYVARS += SOURCE CFLAGS CXXFLAGS INCLUDES LIBS DEFINES
$(foreach V,$(COPYVARS),$(eval $(V) += $$($(V)_$(CONFIG))))
# specific handling for linker script
LDFLAGS += $(LDSCRIPT)
# add defines to flags
CFLAGS += $(DEFINES)
CXXFLAGS += $(DEFINES)
ASMFLAGS += $(DEFINES)
# substitute absolute paths with relative ones
CFLAGS += -fdebug-prefix-map=$(ROOT_DIR)=.
CXXFLAGS += -fdebug-prefix-map=$(ROOT_DIR)=.
ASMFLAGS += -fdebug-prefix-map=$(ROOT_DIR)=.
# root paths for various outputs
DOC_ROOT := doxyOutput
BIN_ROOT := bin
OBJ_ROOT := build
# for a multi project build pipeline
ifdef PROJECT
DOC_PATH := $(DOC_ROOT)/$(PROJECT)
BIN_PATH := $(BIN_ROOT)/$(PROJECT)/$(CONFIG)
OBJ_PATH := $(OBJ_ROOT)/$(PROJECT)/$(CONFIG)
EXECUTABLE := $(BIN_PATH)/$(PROJECT).elf
SIZELOG_PATH := $(PROJECT)/
else
DOC_PATH := $(DOC_ROOT)
BIN_PATH := $(BIN_ROOT)/$(CONFIG)
OBJ_PATH := $(OBJ_ROOT)/$(CONFIG)
EXECUTABLE := $(BIN_PATH)/$(PROJECT).elf
endif
# create lists of prerequisites for the build
OBJECTS += $(addprefix $(OBJ_PATH)/, $(addsuffix .o,$(FILES)))
DEPS = $(OBJECTS:.o=.d)
BINDEPS += $(OBJ_PATH)/build-tag $(BIN_PATH)/build-tag
DOCDEPS += $(DOC_PATH)/build-tag
# Verbosity handling
ifeq ($(VERBOSE),1)
C =
U = @true
else
C = @
U = @echo
endif
all: post-build
.PHONY: all
main-build: pre-build $(EXECUTABLE)
.PHONY: main-build
main-build: pre-build $(EXECUTABLE)
.PHONY: pre-build
-include $(DEPS)
$(DOC_PATH)/build-tag:
$(C)$(MKDIR) -p $(DOC_PATH)
$(C)$(TOUCH) $@
$(BIN_PATH)/build-tag:
$(C)$(MKDIR) -p $(BIN_PATH)
$(C)$(TOUCH) $@
$(OBJ_PATH)/build-tag:
$(C)$(MKDIR) -p $(OBJ_PATH)
$(C)$(TOUCH) $@
doc: $(DOCDEPS)
$(C)$(MKDIR) -p $(DOC_PATH)
$(C)( cat doxygen/Doxyfile ; echo "@INCLUDE = $(PROJECT)/$(PROJECT).doxy" ) | doxygen -
.PHONY: doc
$(EXECUTABLE): $(OBJECTS)
$(U) "Linking $(EXECUTABLE)"
$(C)$(TOOLCHAIN_PREFIX)$(CXX_COMPILER) $(LDFLAGS) $(OBJECTS) -Xlinker -Map="[email protected]" -o $@ $(LIBS)
$(C)date >> $(SIZELOG_PATH)size$(CONFIG).log
$(C)$(TOOLCHAIN_PREFIX)$(SIZE) $@ >> $(SIZELOG_PATH)size$(CONFIG).log
$(C)$(TOOLCHAIN_PREFIX)$(OBJCOPY) -R .stack -O binary $@ $(BIN_PATH)/$(PROJECT).bin
$(C)$(TOOLCHAIN_PREFIX)$(OBJDUMP) -h -S "$@" > "$(BIN_PATH)/$(PROJECT).lss"
$(OBJ_PATH)/%.c.o: %.c $(BINDEPS)
$(U) "C $(basename $(notdir $@))"
$(C)$(MKDIR) -p $(dir $@)
$(C)$(TOOLCHAIN_PREFIX)$(C_COMPILER) $(CFLAGS) $(INCLUDES) -MP -MMD -c -o $@ $<
$(OBJ_PATH)/%.cpp.o: %.cpp $(BINDEPS)
$(U) "C++ $(basename $(notdir $@))"
$(C)$(MKDIR) -p $(dir $@)
$(C)$(TOOLCHAIN_PREFIX)$(CXX_COMPILER) $(CXXFLAGS) $(INCLUDES) -MP -MMD -c -o $@ $<
$(OBJ_PATH)/%.s.o: %.s $(BINDEPS)
$(U) "ASM $(basename $(notdir $@))"
$(C)$(MKDIR) -p $(dir $@)
$(C)$(TOOLCHAIN_PREFIX)$(C_COMPILER) $(ASMFLAGS) $(INCLUDES) -MP -MMD -c -o $@ $<
clean: $(BINDEPS) $(DOCDEPS)
$(U) "Cleaning"
$(C)$(RM) -rf $(BIN_ROOT)
$(C)$(RM) -rf $(OBJ_ROOT)
$(C)$(RM) -rf $(DOC_ROOT)
.PHONY: clean
# project specific makefile rules
include $(PROJECT)/$(PROJECT)_rules.mk
# Function used to check variables. Use on the command line:
# make print-VARNAME
# Useful for debugging
print-%: ; @echo $*=$($*)
.Phony: print-%