-
Notifications
You must be signed in to change notification settings - Fork 491
/
common.mk
280 lines (228 loc) · 8.93 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
# esp-open-rtos common Makefile
#
# ******************************************************************
# Run 'make help' in any example subdirectory to see a usage summary
# (or skip to the bottom of this file!)
#
# For example, from the top level run:
# make help -C examples/http_get
# ******************************************************************
#
# In-depth documentation is at https://github.com/SuperHouse/esp-open-rtos/wiki/Build-Process
#
# Most sections Copyright 2015 Superhouse Automation Pty Ltd
# BSD Licensed as described in the file LICENSE at top level.
#
# This makefile is adapted from the esp-mqtt makefile by @tuanpmt
# https://github.com/tuanpmt/esp_mqtt, but it has changed significantly
# since then.
#
# assume the 'root' directory (ie top of the tree) is the directory common.mk is in
ROOT := $(dir $(lastword $(MAKEFILE_LIST)))
# include local overrides (if present) at top level, then in program directory
-include $(ROOT)local.mk
-include local.mk
ifndef TARGET
$(error "Set the TARGET environment variable in your Makefile before including common.mk"
endif
# esptool defaults
ESPTOOL ?= esptool.py
ESPBAUD ?= 115200
# Output directors to store intermediate compiled files
# relative to the target directory
BUILD_DIR ?= $(TARGET_DIR)build/
FW_BASE ?= $(TARGET_DIR)firmware/
# we create two different files for uploading into the flash
# these are the names and options to generate them
FW_1 = 0x00000
FW_2 = 0x40000
FLAVOR ?= release # or debug
# Compiler names, etc. assume gdb
ESPPORT ?= /dev/ttyUSB0
CROSS ?= xtensa-lx106-elf-
AR = $(CROSS)ar
CC = $(CROSS)gcc
LD = $(CROSS)gcc
NM = $(CROSS)nm
CPP = $(CROSS)g++
SIZE = $(CROSS)size
OBJCOPY = $(CROSS)objcopy
OBJDUMP = $(CROSS)objdump
# Source components to compile and link. Each of these are subdirectories
# of the root, with a 'component.mk' file.
COMPONENTS ?= FreeRTOS lwip axtls
# binary esp-iot-rtos SDK libraries to link. These are pre-processed prior to linking.
SDK_LIBS ?= main net80211 phy pp wpa
# open source libraries linked in
LIBS ?= gcc hal
# Note: this isn't overridable without a not-yet-merged patch to esptool
ENTRY_SYMBOL = call_user_start
CFLAGS = -Wall -Werror -Wl,-EL -nostdlib -mlongcalls -mtext-section-literals -std=gnu99
LDFLAGS = -nostdlib -Wl,--no-check-sections -Wl,-L$(BUILD_DIR)sdklib -Wl,-L$(ROOT)lib -u $(ENTRY_SYMBOL) -Wl,-static -Wl,-Map=build/${TARGET}.map
ifeq ($(FLAVOR),debug)
CFLAGS += -g -O0
LDFLAGS += -g -O0
else
CFLAGS += -g -O2
LDFLAGS += -g -O2
endif
GITSHORTREV=\"$(shell cd $(ROOT); git rev-parse --short -q HEAD)\"
CFLAGS += -DGITSHORTREV=$(GITSHORTREV)
LINKER_SCRIPTS = ld/eagle.app.v6.ld ld/eagle.rom.addr.v6.ld
####
#### no user configurable options below here
####
# hacky way to get a single space value
empty :=
space := $(empty) $(empty)
# assume the target_dir is the directory the top-level makefile was run in
TARGET_DIR := $(dir $(firstword $(MAKEFILE_LIST)))
# derive various parts of compiler/linker arguments
SDK_LIB_ARGS = $(addprefix -l,$(SDK_LIBS))
LIB_ARGS = $(addprefix -l,$(LIBS))
TARGET_OUT = $(BUILD_DIR)$(TARGET).out
LDFLAGS += $(addprefix -T$(ROOT),$(LINKER_SCRIPTS))
FW_FILE_1 = $(addprefix $(FW_BASE),$(FW_1).bin)
FW_FILE_2 = $(addprefix $(FW_BASE),$(FW_2).bin)
# Common include directories, shared across all "components"
# components will add their include directories to this argument
#
# Placing $(TARGET_DIR) and $(TARGET_DIR)include first allows
# targets to have their own copies of header config files for components
# , which is useful for overriding things.
INC_DIRS = $(TARGET_DIR) $(TARGET_DIR)include $(ROOT)include
ifeq ("$(V)","1")
Q :=
vecho := @true
else
Q := @
vecho := @echo
endif
.PHONY: all clean debug_print
all: $(TARGET_OUT) $(FW_FILE_1) $(FW_FILE_2)
# component_compile_rules: Produces compilation rules for a given
# component
#
# Call arguments are:
# $(1) - component name
#
# Expects that the following component-specific variables are defined:
#
# $(1)_ROOT = Top-level dir containing component. Can be in-tree or out-of-tree.
# $(1)_SRC_DIR = List of source directories for the component. All must be under $(1)_ROOT
# $(1)_INC_DIR = List of include directories specific for the component
#
# Optional variables:
# $(1)_CFLAGS = CFLAGS to override the default CFLAGS for this component only.
#
# Each call appends to COMPONENT_ARS which is a list of archive files for compiled components
COMPONENT_ARS =
define component_compile_rules
$(1)_OBJ_DIR = $(BUILD_DIR)$(1)/
### determine source files and object files ###
$(1)_SRC_FILES = $$(foreach sdir,$$($(1)_SRC_DIR),$$(realpath $$(wildcard $$(sdir)/*.c)))
$(1)_REAL_ROOT = $$(realpath $$($(1)_ROOT))
# patsubst here substitutes real paths for the relative OBJ_DIR path, making things short again
$(1)_OBJ_FILES = $$(patsubst $$($(1)_REAL_ROOT)%.c,$$($(1)_OBJ_DIR)%.o,$$($(1)_SRC_FILES))
### determine compiler arguments ###
$(1)_CFLAGS ?= $(CFLAGS)
$(1)_CC_ARGS = $(Q) $(CC) $(addprefix -I,$(INC_DIRS)) $$(addprefix -I,$$($(1)_INC_DIR)) $$($(1)_CFLAGS)
$(1)_AR = $(BUILD_DIR)$(1).a
$$($(1)_OBJ_DIR)%.o: $$($(1)_REAL_ROOT)%.c | $$($(1)_SRC_DIR)
$(vecho) "CC $$<"
$(Q) mkdir -p $$(dir $$@)
$$($(1)_CC_ARGS) -c $$< -o $$@
$$($(1)_CC_ARGS) -MM -MT $$@ -MF $$(@:.o=.d) $$<
$(Q) $(OBJCOPY) --rename-section .text=.irom0.text --rename-section .literal=.irom0.literal $$@
$$($(1)_AR): $$($(1)_OBJ_FILES)
$(vecho) "AR $$@"
$(Q) $(AR) cru $$@ $$^
COMPONENT_ARS += $$($(1)_AR)
-include $$($(1)_OBJ_FILES:.o=.d)
endef
## Linking rules for SDK libraries
## SDK libraries are preprocessed to:
# - prefix all defined symbols with 'sdk_'
# - weaken all global symbols so they can be overriden from the open SDK side
# SDK binary libraries are preprocessed into build/lib
SDK_PROCESSED_LIBS = $(addsuffix .a,$(addprefix $(BUILD_DIR)sdklib/lib,$(SDK_LIBS)))
# Make rule for preprocessing each SDK library
#
$(BUILD_DIR)sdklib/%.a: $(ROOT)lib/%.a $(BUILD_DIR)sdklib/allsymbols.rename
$(vecho) "Pre-processing SDK library $< -> $@"
$(Q) $(OBJCOPY) --redefine-syms $(word 2,$^) --weaken $< $@
# Generate a regex to match symbols we don't want to rename, by parsing
# a list of symbol names
$(BUILD_DIR)sdklib/norename.match: $(ROOT)lib/symbols_norename.txt | $(BUILD_DIR)sdklib
grep -v "^#" $< | sed ':begin;$!N;s/\n/\\|/;tbegin' > $@
# Generate list of defined symbols to rename from a single library. Uses grep & sed.
$(BUILD_DIR)sdklib/%.rename: $(ROOT)lib/%.a $(BUILD_DIR)sdklib/norename.match
$(vecho) "Building symbol list for $< -> $@"
$(Q) $(OBJDUMP) -t $< | grep ' g ' \
| sed -r 's/^.+ ([^ ]+)$$/\1 sdk_\1/' \
| grep -v `cat $(BUILD_DIR)sdklib/norename.match` > $@
# Build master list of all SDK-defined symbols to rename
$(BUILD_DIR)sdklib/allsymbols.rename: $(patsubst %.a,%.rename,$(SDK_PROCESSED_LIBS))
cat $^ > $@
## Include components (this is where the actual compiler sections are generated)
$(foreach component,$(COMPONENTS), $(eval include $(ROOT)/$(component)/component.mk))
# include "dummy component" for the 'target' object file
target_SRC_DIR=$(TARGET_DIR)
target_ROOT=$(TARGET_DIR)
$(eval $(call component_compile_rules,target))
# final linking step to produce .elf
$(TARGET_OUT): $(COMPONENT_ARS) $(SDK_PROCESSED_LIBS)
$(vecho) "LD $@"
$(Q) $(LD) $(LD_SCRIPT) $(LDFLAGS) -Wl,--start-group $(SDK_LIB_ARGS) $(LIB_ARGS) $(COMPONENT_ARS) -Wl,--end-group -o $@
$(BUILD_DIR) $(FW_BASE) $(BUILD_DIR)sdklib:
$(Q) mkdir -p $@
$(FW_FILE_1) $(FW_FILE_2): $(TARGET_OUT) $(FW_BASE)
$(vecho) "FW $@"
$(ESPTOOL) elf2image $< -o $(FW_BASE)
flash: $(FW_FILE_1) $(FW_FILE_2)
$(ESPTOOL) -p $(ESPPORT) --baud $(ESPBAUD) write_flash $(FW_1) $(FW_FILE_1) $(FW_2) $(FW_FILE_2)
size: $(TARGET_OUT)
$(Q) $(CROSS)size --format=sysv $(TARGET_OUT)
test: flash
screen $(ESPPORT) 115200
# the rebuild target is written like this so it can be run in a parallel build
# environment without causing weird side effects
rebuild:
$(MAKE) clean
$(MAKE) all
clean:
$(Q) rm -rf $(BUILD_DIR)
$(Q) rm -rf $(FW_BASE)
# prevent "intermediate" files from being deleted
.SECONDARY:
# print some useful help stuff
help:
@echo "esp-open-rtos make"
@echo ""
@echo "Other targets:"
@echo ""
@echo "all"
@echo "Default target. Will build firmware including any changed source files."
@echo
@echo "clean"
@echo "Delete all build output."
@echo ""
@echo "rebuild"
@echo "Build everything fresh from scratch."
@echo ""
@echo "flash"
@echo "Build then upload firmware to MCU. Set ESPPORT & ESPBAUD to override port/baud rate."
@echo ""
@echo "test"
@echo "'flash', then start a GNU Screen session on the same serial port to see serial output."
@echo ""
@echo "size"
@echo "Build, then print a summary of built firmware size."
@echo ""
@echo "TIPS:"
@echo "* You can use -jN for parallel builds. Much faster! Use 'make rebuild' instead of 'make clean all' for parallel builds."
@echo "* You can create a local.mk file to create local overrides of variables like ESPPORT & ESPBAUD."
@echo ""
@echo "SAMPLE COMMAND LINE:"
@echo "make -j2 test ESPPORT=/dev/ttyUSB0"
@echo ""