2 # Main Project Makefile
3 # This Makefile is included directly from the user project Makefile in order to call the Makefiles of all the
4 # components (in a separate make process) to build all the libraries, then links them together
5 # into the final file. If so, PWD is the project dir (we assume).
9 # This Makefile requires the environment variable SDK_PATH to be set to the directory where this
10 # Makefile is located.
13 .PHONY: build-components menuconfig all build clean
16 # disable built-in make rules, makes debugging saner
19 # Figure out PROJECT_PATH if not set, check for unacceptable Makefile entry points
20 ifeq ("$(PROJECT_PATH)","")
21 #The path to the project: we assume the Makefile including this file resides
22 #in the root of that directory.
23 PROJECT_PATH := $(abspath $(dir $(firstword $(MAKEFILE_LIST))))
26 #The directory where we put all objects/libraries/binaries. The project Makefile can
27 #configure this if needed.
28 BUILD_DIR_BASE ?= $(PROJECT_PATH)/build
30 #Component directories. These directories are searched for components.
31 #The project Makefile can override these component dirs, or define extra component directories.
32 COMPONENT_DIRS ?= $(PROJECT_PATH)/components $(EXTRA_COMPONENT_DIRS) $(SDK_PATH)/components
35 #The project Makefile can define a list of components, but if it does not do this we just take
36 #all available components in the component dirs.
37 ifeq ("$(COMPONENTS)","")
38 #Find all component names. The component names are the same as the
39 #directories they're in, so /bla/components/mycomponent/ -> mycomponent. We later use
40 #the COMPONENT_DIRS bit to find back the component path.
41 COMPONENTS := $(foreach dir,$(COMPONENT_DIRS),$(wildcard $(dir)/*))
42 COMPONENTS := $(sort $(foreach comp,$(COMPONENTS),$(lastword $(subst /, ,$(comp)))))
46 #Sources default to only "main"
49 #Here, we resolve and add all the components and source paths into absolute paths.
50 #If a component exists in multiple COMPONENT_DIRS, we take the first match.
51 #WARNING: These directories paths must be generated WITHOUT a trailing / so we
52 #can use $(notdir x) to get the component name.
53 COMPONENT_PATHS := $(foreach comp,$(COMPONENTS),$(firstword $(foreach dir,$(COMPONENT_DIRS),$(wildcard $(dir)/$(comp)))))
54 COMPONENT_PATHS += $(abspath $(SRCDIRS))
56 #A component is buildable if it has a Makefile; we assume that a 'make -C $(component dir) build' results in a
57 #lib$(componentname).a.
58 COMPONENT_PATHS_BUILDABLE := $(foreach cp,$(COMPONENT_PATHS),$(if $(wildcard $(cp)/Makefile),$(cp)))
60 # Assemble global list of include dirs (COMPONENT_INCLUDES), and
61 # LDFLAGS args (COMPONENT_LDFLAGS) supplied by each component.
63 # Also add any inter-component dependencies for each component.
65 # Extract a variable from a child make process
67 # $(1) - path to directory to invoke make in
68 # $(2) - name of variable to print via the getvariable target (passed in GET_VARIABLE)
70 # needs 'sed' processing of stdout because make sometimes echoes other stuff on stdout,
71 # even if asked not to.
73 # Debugging this? Replace $(shell with $(error and you'll see the full command as-run.
75 $(shell "$(MAKE)" -s --no-print-directory -C $(1) get_variable COMPONENT_INCLUDES=dummy COMPONENT_LDFLAGS=dummy PROJECT_PATH=$(PROJECT_PATH) GET_VARIABLE=$(2) | sed -En "s/^$(2)=(.+)/\1/p" )
78 ifeq ("$(COMPONENT_INCLUDES)","")
79 COMPONENT_INCLUDES := $(abspath $(foreach comp,$(COMPONENT_PATHS_BUILDABLE),$(addprefix $(comp)/, \
80 $(call GetVariable,$(comp),COMPONENT_ADD_INCLUDEDIRS))))
83 #Also add project include path, for sdk includes
84 COMPONENT_INCLUDES += $(PROJECT_PATH)/build/include/
85 export COMPONENT_INCLUDES
87 #COMPONENT_LDFLAGS has a list of all flags that are needed to link the components together. It's collected
88 #in the same way as COMPONENT_INCLUDES is.
89 ifeq ("$(COMPONENT_LDFLAGS)","")
90 COMPONENT_LDFLAGS := $(foreach comp,$(COMPONENT_PATHS_BUILDABLE), \
91 $(call GetVariable,$(comp),COMPONENT_ADD_LDFLAGS))
92 export COMPONENT_LDFLAGS
95 # Generate component dependency targets from dependencies lists
96 # each component gains a target of its own <name>-build with dependencies
97 # of the names of any other components (-build) that need building first
99 # the actual targets (that invoke submakes) are generated below by
100 # GenerateComponentTarget macro.
101 define GenerateComponentDependencies
102 # $(1) = component path
103 .PHONY: $$(notdir $(1))
104 $$(notdir $(1))-build: $(addsuffix -build,$(call GetVariable,$(1),COMPONENT_DEPENDS))
106 $(foreach comp,$(COMPONENT_PATHS_BUILDABLE), $(eval $(call GenerateComponentDependencies,$(comp))))
108 #Make sure submakes can also use this.
111 #Include functionality common to both project & component
112 -include $(SDK_PATH)/make/common.mk
114 #Set host compiler and binutils
118 HOSTOBJCOPY := $(OBJCOPY)
120 #Set target compiler. Defaults to whatever the user has
121 #configured as prefix + yer olde gcc commands
122 CC := $(call dequote,$(CONFIG_TOOLPREFIX))gcc
123 CXX := $(call dequote,$(CONFIG_TOOLPREFIX))c++
124 LD := $(call dequote,$(CONFIG_TOOLPREFIX))ld
125 AR := $(call dequote,$(CONFIG_TOOLPREFIX))ar
126 OBJCOPY := $(call dequote,$(CONFIG_TOOLPREFIX))objcopy
127 export CC CXX LD AR OBJCOPY
129 PYTHON=$(call dequote,$(CONFIG_PYTHON))
131 PROJECT_ELF:=$(BUILD_DIR_BASE)/$(PROJECT_NAME).elf
132 PROJECT_BIN:=$(PROJECT_ELF:.elf=.bin)
134 # Include any Makefile.projbuild file letting components add
135 # configuration at the project level
136 define includeProjBuildMakefile
137 COMPONENT_PATH := $(1)
138 -include $(1)/Makefile.projbuild
140 $(foreach componentpath,$(COMPONENT_PATHS),$(eval $(call includeProjBuildMakefile,$(componentpath))))
142 # ELF depends on the -build target of every component
143 $(PROJECT_ELF): $(addsuffix -build,$(notdir $(COMPONENT_PATHS_BUILDABLE)))
144 $(vecho) LD $(notdir $@)
145 $(Q) $(CC) $(LDFLAGS) -o $@ -Wl,-Map=$(patsubst %.elf,%.map,$@)
147 # Generation of $(PROJECT_BIN) from $(PROJECT_ELF) is added by the esptool
148 # component's Makefile.projbuild
150 project: $(PROJECT_BIN)
151 @echo "App built. Default flash app command is:"
152 @echo $(PROJECT_FLASH_COMMAND) # PROJECT_FLASH_COMMAND is set in esptool_py's Makefile.projbuild
155 mkdir -p $(BUILD_DIR_BASE)
157 define GenerateComponentTarget
158 # $(1) - path to component dir
159 # $(2) - target to generate (build, clean)
160 # $(3) - optional dependencies to add
161 .PHONY: $(notdir $(1))-$(2)
162 $(notdir $(1))-$(2): $(3) | $(BUILD_DIR_BASE)/$(notdir $(1))
163 @+$(MAKE) -C $(BUILD_DIR_BASE)/$(notdir $(1)) -f $(1)/Makefile COMPONENT_BUILD_DIR=$(BUILD_DIR_BASE)/$(notdir $(1)) $(2)
166 define GenerateComponentBuildDirTarget
167 # $(1) - path to component dir
168 $(BUILD_DIR_BASE)/$(notdir $(1)):
169 @mkdir -p $(BUILD_DIR_BASE)/$(notdir $(1))
172 $(foreach component,$(COMPONENT_PATHS_BUILDABLE),$(eval $(call GenerateComponentBuildDirTarget,$(component))))
174 $(foreach component,$(COMPONENT_PATHS_BUILDABLE),$(eval $(call GenerateComponentTarget,$(component),build,$(PROJECT_PATH)/build/include/sdkconfig.h)))
175 $(foreach component,$(COMPONENT_PATHS_BUILDABLE),$(eval $(call GenerateComponentTarget,$(component),clean)))
177 include $(SDK_PATH)/make/project_config.mk
179 clean: $(addsuffix -clean,$(notdir $(COMPONENT_PATHS_BUILDABLE))) $(EXTRA_CLEAN_TARGETS)
180 $(vecho) RM $(PROJECT_ELF)
181 $(Q) rm -f $(PROJECT_ELF)
182 $(Q) rm -rf $(PROJECT_PATH)/build/include/config $(PROJECT_PATH)/build/include/sdkconfig.h