From 8748f867a8bf9da2dc64b5aadb01952486f492ee Mon Sep 17 00:00:00 2001 From: Dong Heng Date: Thu, 3 May 2018 19:42:19 +0800 Subject: [PATCH] chore(make): Update make to support cmake --- make/README | 4 +- make/common.mk | 10 ++++- make/component_wrapper.mk | 83 +++++++++++++++++++++++++++++---------- make/project.mk | 56 ++++++++++++++++++++------ make/project_config.mk | 10 +++-- 5 files changed, 125 insertions(+), 38 deletions(-) diff --git a/make/README b/make/README index 12a20184..ddc1b7d1 100644 --- a/make/README +++ b/make/README @@ -6,5 +6,5 @@ The SDK uses 'make' of esp-idf, and changed things are following: Information of esp-idf is following: -URL: https://github.com/espressif/esp-idf -tag: v3.1-dev +commit: 48c3ad37 + diff --git a/make/common.mk b/make/common.mk index ccee3227..2eb0f0d3 100644 --- a/make/common.mk +++ b/make/common.mk @@ -62,7 +62,7 @@ endef # # example $(call resolvepath,$(CONFIG_PATH),$(CONFIG_DIR)) define resolvepath -$(foreach dir,$(1),$(if $(filter /%,$(dir)),$(dir),$(subst //,/,$(2)/$(dir)))) +$(abspath $(foreach dir,$(1),$(if $(filter /%,$(dir)),$(dir),$(subst //,/,$(2)/$(dir))))) endef @@ -86,3 +86,11 @@ endef define uniq $(if $1,$(firstword $1) $(call uniq,$(filter-out $(firstword $1),$1))) endef + +# macro to strip leading ../s from a path +# Given $(1) which is a directory, remove any leading ../s from it +# (recursively keeps removing ../ until not found) +# if the path contains nothing but ../.., a single . is returned (cwd) +define stripLeadingParentDirs +$(foreach path,$(1),$(if $(subst ..,,$(path)),$(if $(filter ../%,$(path)),$(call stripLeadingParentDirs,$(patsubst ../%,%,$(path))),$(path)),.)) +endef diff --git a/make/component_wrapper.mk b/make/component_wrapper.mk index 84edc0a8..f2b23642 100644 --- a/make/component_wrapper.mk +++ b/make/component_wrapper.mk @@ -47,7 +47,7 @@ COMPONENT_ADD_INCLUDEDIRS = include COMPONENT_ADD_LDFLAGS = -l$(COMPONENT_NAME) # Define optional compiling macros -define compile_exclude +define compile_exclude COMPONENT_OBJEXCLUDE += $(1) endef @@ -59,7 +59,7 @@ define compile_only_if $(eval $(if $(1), $(call compile_include, $(2)), $(call compile_exclude, $(2)))) endef -define compile_only_if_not +define compile_only_if_not $(eval $(if $(1), $(call compile_exclude, $(2)), $(call compile_include, $(2)))) endef @@ -73,11 +73,36 @@ COMPONENT_SUBMODULES ?= ################################################################################ # 2) Include the component.mk for the specific component (COMPONENT_MAKEFILE) to -# override variables & optionally define custom targets. +# override variables & optionally define custom targets. Also include global +# component makefiles. ################################################################################ + +# Include any Makefile.componentbuild file letting components add +# configuration at the global component level + +# Save component_path; we pass it to the called Makefile.componentbuild +# as COMPILING_COMPONENT_PATH, and we use it to restore the current +# COMPONENT_PATH later. +COMPILING_COMPONENT_PATH := $(COMPONENT_PATH) + +define includeCompBuildMakefile +$(if $(V),$(info including $(1)/Makefile.componentbuild...)) +COMPONENT_PATH := $(1) +include $(1)/Makefile.componentbuild +endef +$(foreach componentpath,$(COMPONENT_PATHS), \ + $(if $(wildcard $(componentpath)/Makefile.componentbuild), \ + $(eval $(call includeCompBuildMakefile,$(componentpath))))) + +#Restore COMPONENT_PATH to what it was +COMPONENT_PATH := $(COMPILING_COMPONENT_PATH) + + +# Include component.mk for this component. include $(COMPONENT_MAKEFILE) + ################################################################################ # 3) Set variables that depend on values that may changed by component.mk ################################################################################ @@ -85,11 +110,12 @@ include $(COMPONENT_MAKEFILE) ifndef COMPONENT_CONFIG_ONLY # Skip steps 3-5 if COMPONENT_CONFIG_ONLY is set # Object files which need to be linked into the library -# By default we take all .c, .cpp & .S files in COMPONENT_SRCDIRS. +# By default we take all .c, .cpp, .cc & .S files in COMPONENT_SRCDIRS. ifndef COMPONENT_OBJS # Find all source files in all COMPONENT_SRCDIRS COMPONENT_OBJS := $(foreach compsrcdir,$(COMPONENT_SRCDIRS),$(patsubst %.c,%.o,$(wildcard $(COMPONENT_PATH)/$(compsrcdir)/*.c))) COMPONENT_OBJS += $(foreach compsrcdir,$(COMPONENT_SRCDIRS),$(patsubst %.cpp,%.o,$(wildcard $(COMPONENT_PATH)/$(compsrcdir)/*.cpp))) +COMPONENT_OBJS += $(foreach compsrcdir,$(COMPONENT_SRCDIRS),$(patsubst %.cc,%.o,$(wildcard $(COMPONENT_PATH)/$(compsrcdir)/*.cc))) COMPONENT_OBJS += $(foreach compsrcdir,$(COMPONENT_SRCDIRS),$(patsubst %.S,%.o,$(wildcard $(COMPONENT_PATH)/$(compsrcdir)/*.S))) # Make relative by removing COMPONENT_PATH from all found object paths COMPONENT_OBJS := $(patsubst $(COMPONENT_PATH)/%,%,$(COMPONENT_OBJS)) @@ -97,13 +123,21 @@ else # Add in components defined by conditional compiling macros COMPONENT_OBJS += $(COMPONENT_OBJINCLUDE) endif +# Remove any leading ../ from paths, so everything builds inside build dir +COMPONENT_OBJS := $(call stripLeadingParentDirs,$(COMPONENT_OBJS)) + +# Do the same for COMPONENT_OBJEXCLUDE (used below) +COMPONENT_OBJEXCLUDE := $(call stripLeadingParentDirs,$(COMPONENT_OBJEXCLUDE)) + +# COMPONENT_OBJDIRS is COMPONENT_SRCDIRS with the same transform applied +COMPONENT_OBJDIRS := $(call stripLeadingParentDirs,$(COMPONENT_SRCDIRS)) + # Remove items disabled by optional compilation -COMPONENT_OBJS := $(foreach obj,$(COMPONENT_OBJS),$(if $(filter $(realpath $(obj)),$(realpath $(COMPONENT_OBJEXCLUDE))), ,$(obj))) +COMPONENT_OBJS := $(foreach obj,$(COMPONENT_OBJS),$(if $(filter $(abspath $(obj)),$(abspath $(COMPONENT_OBJEXCLUDE))), ,$(obj))) # Remove duplicates COMPONENT_OBJS := $(call uniq,$(COMPONENT_OBJS)) - # Object files with embedded binaries to add to the component library # Correspond to the files named in COMPONENT_EMBED_FILES & COMPONENT_EMBED_TXTFILES COMPONENT_EMBED_OBJS ?= $(addsuffix .bin.o,$(notdir $(COMPONENT_EMBED_FILES))) $(addsuffix .txt.o,$(notdir $(COMPONENT_EMBED_TXTFILES))) @@ -154,10 +188,10 @@ endef component_project_vars.mk:: $(details) "Building component project variables list $(abspath $@)" @echo '# Automatically generated build file. Do not edit.' > $@ - @echo 'COMPONENT_INCLUDES += $(call MakeVariablePath,$(addprefix $(COMPONENT_PATH)/,$(COMPONENT_ADD_INCLUDEDIRS)))' >> $@ + @echo 'COMPONENT_INCLUDES += $(call MakeVariablePath,$(abspath $(addprefix $(COMPONENT_PATH)/,$(COMPONENT_ADD_INCLUDEDIRS))))' >> $@ @echo 'COMPONENT_LDFLAGS += $(call MakeVariablePath,-L$(COMPONENT_BUILD_DIR) $(COMPONENT_ADD_LDFLAGS))' >> $@ @echo 'COMPONENT_LINKER_DEPS += $(call MakeVariablePath,$(call resolvepath,$(COMPONENT_ADD_LINKER_DEPS),$(COMPONENT_PATH)))' >> $@ - @echo 'COMPONENT_SUBMODULES += $(call MakeVariablePath,$(addprefix $(COMPONENT_PATH)/,$(COMPONENT_SUBMODULES)))' >> $@ + @echo 'COMPONENT_SUBMODULES += $(call MakeVariablePath,$(abspath $(addprefix $(COMPONENT_PATH)/,$(COMPONENT_SUBMODULES))))' >> $@ @echo 'COMPONENT_LIBRARIES += $(COMPONENT_NAME)' >> $@ @echo 'component-$(COMPONENT_NAME)-build: $(addprefix component-,$(addsuffix -build,$(COMPONENT_DEPENDS)))' >> $@ @@ -210,36 +244,45 @@ endef # This pattern is generated for each COMPONENT_SRCDIR to compile the files in it. define GenerateCompileTargets # $(1) - directory containing source files, relative to $(COMPONENT_PATH) - one of $(COMPONENT_SRCDIRS) +# $(2) - output build directory, which is $(1) with any leading ".."s converted to "."s to ensure output is always under build/ # -$(1)/%.o: $$(COMPONENT_PATH)/$(1)/%.c $(COMMON_MAKEFILES) $(COMPONENT_MAKEFILE) | $(COMPONENT_SRCDIRS) + +$(2)/%.o: $$(COMPONENT_PATH)/$(1)/%.c $(COMMON_MAKEFILES) $(COMPONENT_MAKEFILE) | $(COMPONENT_OBJDIRS) $$(summary) CC $$(patsubst $$(PWD)/%,%,$$(CURDIR))/$$@ - $$(CC) $$(CFLAGS) $$(CPPFLAGS) $$(addprefix -I ,$$(COMPONENT_INCLUDES)) $$(addprefix -I ,$$(COMPONENT_EXTRA_INCLUDES)) -I$(1) -c $$< -o $$@ + $$(CC) $$(CFLAGS) $$(CPPFLAGS) $$(addprefix -I ,$$(COMPONENT_INCLUDES)) $$(addprefix -I ,$$(COMPONENT_EXTRA_INCLUDES)) -I $(1) -c $$(abspath $$<) -o $$@ $(call AppendSourceToDependencies,$$<,$$@) -$(1)/%.o: $$(COMPONENT_PATH)/$(1)/%.cpp $(COMMON_MAKEFILES) $(COMPONENT_MAKEFILE) | $(COMPONENT_SRCDIRS) +$(2)/%.o: $$(COMPONENT_PATH)/$(1)/%.cpp $(COMMON_MAKEFILES) $(COMPONENT_MAKEFILE) | $(COMPONENT_OBJDIRS) $$(summary) CXX $$(patsubst $$(PWD)/%,%,$$(CURDIR))/$$@ - $$(CXX) $$(CXXFLAGS) $$(CPPFLAGS) $$(addprefix -I,$$(COMPONENT_INCLUDES)) $$(addprefix -I,$$(COMPONENT_EXTRA_INCLUDES)) -I$(1) -c $$< -o $$@ + $$(CXX) $$(CXXFLAGS) $$(CPPFLAGS) $$(addprefix -I ,$$(COMPONENT_INCLUDES)) $$(addprefix -I ,$$(COMPONENT_EXTRA_INCLUDES)) -I $(1) -c $$(abspath $$<) -o $$@ $(call AppendSourceToDependencies,$$<,$$@) -$(1)/%.o: $$(COMPONENT_PATH)/$(1)/%.S $(COMMON_MAKEFILES) $(COMPONENT_MAKEFILE) | $(COMPONENT_SRCDIRS) +$(2)/%.o: $$(COMPONENT_PATH)/$(1)/%.cc $(COMMON_MAKEFILES) $(COMPONENT_MAKEFILE) | $(COMPONENT_OBJDIRS) + $$(summary) CXX $$(patsubst $$(PWD)/%,%,$$(CURDIR))/$$@ + $$(CXX) $$(CXXFLAGS) $$(CPPFLAGS) $$(addprefix -I ,$$(COMPONENT_INCLUDES)) $$(addprefix -I ,$$(COMPONENT_EXTRA_INCLUDES)) -I $(1) -c $$(abspath $$<) -o $$@ + $(call AppendSourceToDependencies,$$<,$$@) + +$(2)/%.o: $$(COMPONENT_PATH)/$(1)/%.S $(COMMON_MAKEFILES) $(COMPONENT_MAKEFILE) | $(COMPONENT_OBJDIRS) $$(summary) AS $$(patsubst $$(PWD)/%,%,$$(CURDIR))/$$@ - $$(CC) $$(CPPFLAGS) $$(DEBUG_FLAGS) $$(addprefix -I ,$$(COMPONENT_INCLUDES)) $$(addprefix -I ,$$(COMPONENT_EXTRA_INCLUDES)) -I$(1) -c $$< -o $$@ + $$(CC) $$(CPPFLAGS) $$(DEBUG_FLAGS) $$(addprefix -I ,$$(COMPONENT_INCLUDES)) $$(addprefix -I ,$$(COMPONENT_EXTRA_INCLUDES)) -I $(1) -c $$(abspath $$<) -o $$@ $(call AppendSourceToDependencies,$$<,$$@) # CWD is build dir, create the build subdirectory if it doesn't exist # -# (NB: Each .o file depends on all relative component build dirs $(COMPONENT_SRCDIRS), rather than just $(1), to work +# (NB: Each .o file depends on all relative component build dirs $(COMPONENT_OBJDIRS), including $(2), to work # around a behaviour make 3.81 where the first pattern (randomly) seems to be matched rather than the best fit. ie if # you have objects a/y.o and a/b/c.o then c.o can be matched with $(1)=a & %=b/c, meaning that subdir 'a/b' needs to be -# created but wouldn't be created if $(1)=a. Make 4.x doesn't have this problem, it seems to preferentially -# choose the better match ie $(1)=a/b and %=c ) +# created but wouldn't be created if $(2)=a. Make 4.x doesn't have this problem, it seems to preferentially +# choose the better match ie $(2)=a/b and %=c ) # -$(1): - mkdir -p $(1) +# Note: This may cause some issues for out-of-tree source files and make 3.81 :/ +# +$(2): + mkdir -p $(2) endef # Generate all the compile target patterns -$(foreach srcdir,$(COMPONENT_SRCDIRS), $(eval $(call GenerateCompileTargets,$(srcdir)))) +$(foreach srcdir,$(COMPONENT_SRCDIRS), $(eval $(call GenerateCompileTargets,$(srcdir),$(call stripLeadingParentDirs,$(srcdir))))) ## Support for embedding binary files into the ELF as symbols diff --git a/make/project.mk b/make/project.mk index 52a88d7b..a2f26e8f 100644 --- a/make/project.mk +++ b/make/project.mk @@ -10,7 +10,9 @@ # where this file is located. # -.PHONY: build-components menuconfig defconfig all build clean all_binaries check-submodules size size-components size-files list-components +.PHONY: build-components menuconfig defconfig all build clean all_binaries check-submodules size size-components size-files size-symbols list-components + +MAKECMDGOALS ?= all all: all_binaries # see below for recipe of 'all' target # @@ -30,6 +32,7 @@ help: @echo "make clean - Remove all build output" @echo "make size - Display the static memory footprint of the app" @echo "make size-components, size-files - Finer-grained memory footprints" + @echo "make size-symbols - Per symbol memory footprint. Requires COMPONENT=" @echo "make erase_flash - Erase entire flash contents" @echo "make monitor - Run idf_monitor tool to monitor serial output from app" @echo "make simple_monitor - Monitor serial output on terminal console" @@ -43,6 +46,9 @@ help: @echo "See also 'make bootloader', 'make bootloader-flash', 'make bootloader-clean', " @echo "'make partition_table', etc, etc." +# Non-interactive targets. Mostly, those for which you do not need to build a binary +NON_INTERACTIVE_TARGET += defconfig clean% %clean help list-components print_flash_cmd + # dependency checks ifndef MAKE_RESTARTS ifeq ("$(filter 4.% 3.81 3.82,$(MAKE_VERSION))","") @@ -145,6 +151,10 @@ COMPONENTS := $(dir $(foreach cd,$(COMPONENT_DIRS), \ )) COMPONENTS := $(sort $(foreach comp,$(COMPONENTS),$(lastword $(subst /, ,$(comp))))) endif +# After a full manifest of component names is determined, subtract the ones explicitly omitted by the project Makefile. +ifdef EXCLUDE_COMPONENTS +COMPONENTS := $(filter-out $(EXCLUDE_COMPONENTS), $(COMPONENTS)) +endif export COMPONENTS # Resolve all of COMPONENTS into absolute paths in COMPONENT_PATHS. @@ -154,6 +164,7 @@ export COMPONENTS # NOTE: These paths must be generated WITHOUT a trailing / so we # can use $(notdir x) to get the component name. COMPONENT_PATHS := $(foreach comp,$(COMPONENTS),$(firstword $(foreach cd,$(COMPONENT_DIRS),$(wildcard $(dir $(cd))$(comp) $(cd)/$(comp))))) +export COMPONENT_PATHS TEST_COMPONENTS ?= TESTS_ALL ?= @@ -217,7 +228,12 @@ endif @echo $(ESPTOOLPY_WRITE_FLASH) $(ESPTOOL_ALL_FLASH_ARGS) +# If we have `version.txt` then prefer that for extracting IDF version +ifeq ("$(wildcard ${IDF_PATH}/version.txt)","") IDF_VER := $(shell cd ${IDF_PATH} && git describe --always --tags --dirty) +else +IDF_VER := `cat ${IDF_PATH}/version.txt` +endif # Set default LDFLAGS EXTRA_LDFLAGS ?= @@ -257,6 +273,10 @@ COMMON_WARNING_FLAGS = -Wall -Werror=all \ -Wextra \ -Wno-unused-parameter -Wno-sign-compare +ifdef CONFIG_WARN_WRITE_STRINGS +COMMON_WARNING_FLAGS += -Wwrite-strings +endif #CONFIG_WARN_WRITE_STRINGS + # Flags which control code generation and dependency generation, both for C and C++ COMMON_FLAGS = \ -ffunction-sections -fdata-sections \ @@ -325,20 +345,19 @@ endif export CFLAGS CPPFLAGS CXXFLAGS +# Set default values that were not previously defined +CC ?= gcc +LD ?= ld +AR ?= ar +OBJCOPY ?= objcopy +SIZE ?= size + # Set host compiler and binutils HOSTCC := $(CC) HOSTLD := $(LD) HOSTAR := $(AR) -ifdef OBJCOPY HOSTOBJCOPY := $(OBJCOPY) -else -HOSTOBJCOPY := objcopy -endif -ifdef SIZE HOSTSIZE := $(SIZE) -else -HOSTSIZE := size -endif export HOSTCC HOSTLD HOSTAR HOSTOBJCOPY SIZE # Set target compiler. Defaults to whatever the user has @@ -361,7 +380,7 @@ APP_BIN:=$(APP_ELF:.elf=.bin) # Include any Makefile.projbuild file letting components add # configuration at the project level define includeProjBuildMakefile -$(if $(V),$(info including $(1)/Makefile.projbuild...)) +$(if $(V),$$(info including $(1)/Makefile.projbuild...)) COMPONENT_PATH := $(1) include $(1)/Makefile.projbuild endef @@ -461,6 +480,13 @@ size-files: $(APP_ELF) size-components: $(APP_ELF) $(PYTHON) $(IDF_PATH)/tools/idf_size.py --archives $(APP_MAP) +size-symbols: $(APP_ELF) +ifndef COMPONENT + $(error "ERROR: Please enter the component to look symbols for, e.g. COMPONENT=heap") +else + $(PYTHON) $(IDF_PATH)/tools/idf_size.py --archive_details lib$(COMPONENT).a $(APP_MAP) +endif + # NB: this ordering is deliberate (app-clean & bootloader-clean before # _config-clean), so config remains valid during all component clean # targets @@ -472,6 +498,8 @@ clean: app-clean bootloader-clean config-clean # # This only works for components inside IDF_PATH check-submodules: +# Check if .gitmodules exists, otherwise skip submodule check, assuming flattened structure +ifneq ("$(wildcard ${IDF_PATH}/.gitmodules)","") # Dump the git status for the whole working copy once, then grep it for each submodule. This saves a lot of time on Windows. GIT_STATUS := $(shell cd ${IDF_PATH} && git status --porcelain --ignore-submodules=dirty) @@ -496,6 +524,7 @@ endef # filter/subst in expression ensures all submodule paths begin with $(IDF_PATH), and then strips that prefix # so the argument is suitable for use with 'git submodule' commands $(foreach submodule,$(subst $(IDF_PATH)/,,$(filter $(IDF_PATH)/%,$(COMPONENT_SUBMODULES))),$(eval $(call GenerateSubmoduleCheckTarget,$(submodule)))) +endif # End check for .gitmodules existence # PHONY target to list components in the build and their paths @@ -507,6 +536,9 @@ list-components: $(info COMPONENTS (list of component names)) $(info $(COMPONENTS)) $(info $(call dequote,$(SEPARATOR))) + $(info EXCLUDE_COMPONENTS (list of excluded names)) + $(info $(if $(EXCLUDE_COMPONENTS),$(EXCLUDE_COMPONENTS),(none provided))) + $(info $(call dequote,$(SEPARATOR))) $(info COMPONENT_PATHS (paths to all components):) $(foreach cp,$(COMPONENT_PATHS),$(info $(cp))) @@ -525,7 +557,7 @@ TOOLCHAIN_COMMIT_DESC := $(shell $(CC) --version | sed -E -n 's|.*crosstool-ng-( TOOLCHAIN_GCC_VER := $(shell $(CC) --version | sed -E -n 's|xtensa-esp32-elf-gcc.*\ \(.*\)\ (.*)|\1|gp') # Officially supported version(s) -SUPPORTED_TOOLCHAIN_COMMIT_DESC := 1.22.0-75-gbaf03c2 +SUPPORTED_TOOLCHAIN_COMMIT_DESC := 1.22.0-80-g6c4433a SUPPORTED_TOOLCHAIN_GCC_VERSIONS := 5.2.0 ifdef TOOLCHAIN_COMMIT_DESC @@ -540,7 +572,7 @@ $(info Expected to see version(s): $(SUPPORTED_TOOLCHAIN_GCC_VERSIONS)) $(info Please check ESP-IDF setup instructions and update the toolchain, or proceed at your own risk.) endif else -#$(info WARNING: Failed to find Xtensa toolchain, may need to alter PATH or set one in the configuration menu) +$(info WARNING: Failed to find Xtensa toolchain, may need to alter PATH or set one in the configuration menu) endif # TOOLCHAIN_COMMIT_DESC endif #MAKE_RESTARTS diff --git a/make/project_config.mk b/make/project_config.mk index 0a212cd2..8f0006c7 100644 --- a/make/project_config.mk +++ b/make/project_config.mk @@ -15,15 +15,19 @@ SDKCONFIG ?= $(PROJECT_PATH)/sdkconfig # overrides (usually used for esp-idf examples) SDKCONFIG_DEFAULTS ?= $(PROJECT_PATH)/sdkconfig.defaults +# Workaround to run make parallel (-j). mconf and conf cannot be made simultaneously +$(KCONFIG_TOOL_DIR)/mconf: $(KCONFIG_TOOL_DIR)/conf + # reset MAKEFLAGS as the menuconfig makefile uses implicit compile rules $(KCONFIG_TOOL_DIR)/mconf $(KCONFIG_TOOL_DIR)/conf: $(wildcard $(KCONFIG_TOOL_DIR)/*.c) MAKEFLAGS="" CC=$(HOSTCC) LD=$(HOSTLD) \ $(MAKE) -C $(KCONFIG_TOOL_DIR) ifeq ("$(wildcard $(SDKCONFIG))","") -ifeq ("$(filter defconfig clean% %clean, $(MAKECMDGOALS))","") -# if no configuration file is present and defconfig or clean -# is not a named target, run defconfig then menuconfig to get the initial config +# if no configuration file is present we need a rule for it +ifeq ("$(filter $(NON_INTERACTIVE_TARGET), $(MAKECMDGOALS))","") +# if special non-interactive item is not a named target (eg. 'defconfig', 'clean') +# run defconfig then menuconfig to get the initial config $(SDKCONFIG): menuconfig menuconfig: defconfig else