Merge branch 'bugfix/build_dir_base' into 'master'

Build system: Fix BUILD_DIR_BASE out of tree

See github issue https://github.com/espressif/esp-idf/issues/38

See merge request !130
This commit is contained in:
Angus Gratton 2016-10-20 13:58:48 +08:00
commit 0704deca63
7 changed files with 210 additions and 162 deletions

3
.gitignore vendored
View file

@ -19,6 +19,3 @@ GPATH
examples/*/sdkconfig examples/*/sdkconfig
examples/*/sdkconfig.old examples/*/sdkconfig.old
examples/*/build examples/*/build
# Bootloader files
components/bootloader/src/sdkconfig.old

View file

@ -11,20 +11,23 @@
ifeq ("$(IS_BOOTLOADER_BUILD)","") ifeq ("$(IS_BOOTLOADER_BUILD)","")
BOOTLOADER_COMPONENT_PATH := $(COMPONENT_PATH) BOOTLOADER_COMPONENT_PATH := $(COMPONENT_PATH)
BOOTLOADER_BUILD_DIR=$(BUILD_DIR_BASE)/bootloader BOOTLOADER_BUILD_DIR=$(abspath $(BUILD_DIR_BASE)/bootloader)
BOOTLOADER_BIN=$(BOOTLOADER_BUILD_DIR)/bootloader.bin BOOTLOADER_BIN=$(BOOTLOADER_BUILD_DIR)/bootloader.bin
BOOTLOADER_SDKCONFIG=$(BOOTLOADER_BUILD_DIR)/sdkconfig
# Custom recursive make for bootloader sub-project
BOOTLOADER_MAKE=+$(MAKE) -C $(BOOTLOADER_COMPONENT_PATH)/src \
V=$(V) SDKCONFIG=$(BOOTLOADER_SDKCONFIG) \
BUILD_DIR_BASE=$(BOOTLOADER_BUILD_DIR) \
.PHONY: bootloader-clean bootloader-flash bootloader $(BOOTLOADER_BIN) .PHONY: bootloader-clean bootloader-flash bootloader $(BOOTLOADER_BIN)
$(BOOTLOADER_BIN): $(COMPONENT_PATH)/src/sdkconfig $(BOOTLOADER_BIN): | $(BOOTLOADER_BUILD_DIR)/sdkconfig
$(Q) PROJECT_PATH= \ $(Q) $(BOOTLOADER_MAKE) $@
BUILD_DIR_BASE=$(BOOTLOADER_BUILD_DIR) \
$(MAKE) -C $(BOOTLOADER_COMPONENT_PATH)/src MAKEFLAGS= V=$(V) TARGET_BIN_LAYOUT="$(BOOTLOADER_TARGET_BIN_LAYOUT)" $(BOOTLOADER_BIN)
bootloader-clean: bootloader-clean:
$(Q) PROJECT_PATH= \ $(Q) $(BOOTLOADER_MAKE) app-clean config-clean
BUILD_DIR_BASE=$(BOOTLOADER_BUILD_DIR) \ $(Q) rm -f $(BOOTLOADER_SDKCONFIG) $(BOOTLOADER_SDKCONFIG).old
$(MAKE) -C $(BOOTLOADER_COMPONENT_PATH)/src app-clean MAKEFLAGS= V=$(V)
clean: bootloader-clean clean: bootloader-clean
@ -36,14 +39,17 @@ all_binaries: $(BOOTLOADER_BIN)
ESPTOOL_ALL_FLASH_ARGS += 0x1000 $(BOOTLOADER_BIN) ESPTOOL_ALL_FLASH_ARGS += 0x1000 $(BOOTLOADER_BIN)
# synchronise the project level config to the component's
# config
$(COMPONENT_PATH)/src/sdkconfig: $(PROJECT_PATH)/sdkconfig
$(Q) cp $< $@
# bootloader-flash calls flash in the bootloader dummy project # bootloader-flash calls flash in the bootloader dummy project
bootloader-flash: $(BOOTLOADER_BIN) bootloader-flash: $(BOOTLOADER_BIN)
$(MAKE) -C $(BOOTLOADER_COMPONENT_PATH)/src flash MAKEFLAGS= V=$(V) $(BOOTLOADER_MAKE) flash
# synchronise the project level config to the bootloader's
# config
$(BOOTLOADER_SDKCONFIG): $(PROJECT_PATH)/sdkconfig | $(BOOTLOADER_BUILD_DIR)
$(Q) cp $< $@
$(BOOTLOADER_BUILD_DIR):
$(Q) mkdir -p $@
else else
CFLAGS += -D BOOTLOADER_BUILD=1 -I $(IDF_PATH)/components/esp32/include CFLAGS += -D BOOTLOADER_BUILD=1 -I $(IDF_PATH)/components/esp32/include

View file

@ -6,7 +6,7 @@
# lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable, # lib(subdirectory_name).a in the build directory. This behaviour is entirely configurable,
# please read the esp-idf build system document if you need to do this. # please read the esp-idf build system document if you need to do this.
# #
-include $(PROJECT_PATH)/build/include/config/auto.conf -include include/config/auto.conf
COMPONENT_SRCDIRS := . hwcrypto COMPONENT_SRCDIRS := . hwcrypto
@ -44,6 +44,8 @@ $(COMPONENT_LIBRARY): $(ALL_LIB_FILES)
# saves us from having to add the target to a Makefile.projbuild # saves us from having to add the target to a Makefile.projbuild
$(COMPONENT_LIBRARY): esp32_out.ld $(COMPONENT_LIBRARY): esp32_out.ld
# .. is BUILD_DIR_BASE here, as component makefiles
# are evaluated with CWD=component build dir
esp32_out.ld: $(COMPONENT_PATH)/ld/esp32.ld ../include/sdkconfig.h esp32_out.ld: $(COMPONENT_PATH)/ld/esp32.ld ../include/sdkconfig.h
$(CC) -I ../include -C -P -x c -E $< -o $@ $(CC) -I ../include -C -P -x c -E $< -o $@

View file

@ -6,7 +6,7 @@
# #
# (Note that we only rebuild auto.conf automatically for some targets, # (Note that we only rebuild auto.conf automatically for some targets,
# see project_config.mk for details.) # see project_config.mk for details.)
-include $(PROJECT_PATH)/build/include/config/auto.conf -include $(BUILD_DIR_BASE)/include/config/auto.conf
#Handling of V=1/VERBOSE=1 flag #Handling of V=1/VERBOSE=1 flag
# #

View file

@ -37,6 +37,7 @@ help:
@echo "'make partition_table', etc, etc." @echo "'make partition_table', etc, etc."
# disable built-in make rules, makes debugging saner # disable built-in make rules, makes debugging saner
MAKEFLAGS_OLD := $(MAKEFLAGS)
MAKEFLAGS +=-rR MAKEFLAGS +=-rR
# Figure out PROJECT_PATH if not set # Figure out PROJECT_PATH if not set
@ -50,6 +51,7 @@ endif
#The directory where we put all objects/libraries/binaries. The project Makefile can #The directory where we put all objects/libraries/binaries. The project Makefile can
#configure this if needed. #configure this if needed.
BUILD_DIR_BASE ?= $(PROJECT_PATH)/build BUILD_DIR_BASE ?= $(PROJECT_PATH)/build
export BUILD_DIR_BASE
#Component directories. These directories are searched for components. #Component directories. These directories are searched for components.
#The project Makefile can override these component dirs, or define extra component directories. #The project Makefile can override these component dirs, or define extra component directories.
@ -105,7 +107,7 @@ COMPONENT_INCLUDES := $(abspath $(foreach comp,$(COMPONENT_PATHS_BUILDABLE),$(ad
$(call GetVariable,$(comp),COMPONENT_ADD_INCLUDEDIRS)))) $(call GetVariable,$(comp),COMPONENT_ADD_INCLUDEDIRS))))
#Also add project include path, for sdk includes #Also add project include path, for sdk includes
COMPONENT_INCLUDES += $(PROJECT_PATH)/build/include/ COMPONENT_INCLUDES += $(abspath $(BUILD_DIR_BASE)/include/)
export COMPONENT_INCLUDES export COMPONENT_INCLUDES
#COMPONENT_LDFLAGS has a list of all flags that are needed to link the components together. It's collected #COMPONENT_LDFLAGS has a list of all flags that are needed to link the components together. It's collected
@ -230,7 +232,7 @@ define GenerateComponentPhonyTarget
# $(2) - target to generate (build, clean) # $(2) - target to generate (build, clean)
.PHONY: $(notdir $(1))-$(2) .PHONY: $(notdir $(1))-$(2)
$(notdir $(1))-$(2): | $(BUILD_DIR_BASE)/$(notdir $(1)) $(notdir $(1))-$(2): | $(BUILD_DIR_BASE)/$(notdir $(1))
@+$(MAKE) -C $(BUILD_DIR_BASE)/$(notdir $(1)) -f $(1)/component.mk COMPONENT_BUILD_DIR=$(BUILD_DIR_BASE)/$(notdir $(1)) $(2) $(Q) +$(MAKE) -C $(BUILD_DIR_BASE)/$(notdir $(1)) -f $(1)/component.mk COMPONENT_BUILD_DIR=$(BUILD_DIR_BASE)/$(notdir $(1)) $(2)
endef endef
define GenerateComponentTargets define GenerateComponentTargets

View file

@ -7,38 +7,38 @@ COMPONENT_KCONFIGS_PROJBUILD := $(foreach component,$(COMPONENT_PATHS),$(wildcar
#For doing make menuconfig etc #For doing make menuconfig etc
KCONFIG_TOOL_DIR=$(IDF_PATH)/tools/kconfig KCONFIG_TOOL_DIR=$(IDF_PATH)/tools/kconfig
# clear MAKEFLAGS as the menuconfig makefile uses implicit compile rules # set SDKCONFIG to the project's sdkconfig,
# unless it's overriden (happens for bootloader)
SDKCONFIG ?= $(PROJECT_PATH)/sdkconfig
# reset MAKEFLAGS as the menuconfig makefile uses implicit compile rules
$(KCONFIG_TOOL_DIR)/mconf $(KCONFIG_TOOL_DIR)/conf: $(KCONFIG_TOOL_DIR)/mconf $(KCONFIG_TOOL_DIR)/conf:
MAKEFLAGS="" \ MAKEFLAGS=$(ORIGINAL_MAKEFLAGS) CC=$(HOSTCC) LD=$(HOSTLD) \
CC=$(HOSTCC) LD=$(HOSTLD) \
$(MAKE) -C $(KCONFIG_TOOL_DIR) $(MAKE) -C $(KCONFIG_TOOL_DIR)
# use a wrapper environment for where we run Kconfig tools
KCONFIG_TOOL_ENV=KCONFIG_AUTOHEADER=$(abspath $(BUILD_DIR_BASE)/include/sdkconfig.h) \
COMPONENT_KCONFIGS="$(COMPONENT_KCONFIGS)" KCONFIG_CONFIG=$(SDKCONFIG) \
COMPONENT_KCONFIGS_PROJBUILD="$(COMPONENT_KCONFIGS_PROJBUILD)"
menuconfig: $(KCONFIG_TOOL_DIR)/mconf $(IDF_PATH)/Kconfig $(BUILD_DIR_BASE) menuconfig: $(KCONFIG_TOOL_DIR)/mconf $(IDF_PATH)/Kconfig $(BUILD_DIR_BASE)
$(summary) MENUCONFIG $(summary) MENUCONFIG
$(Q) KCONFIG_AUTOHEADER=$(PROJECT_PATH)/build/include/sdkconfig.h \ $(Q) $(KCONFIG_TOOL_ENV) $(KCONFIG_TOOL_DIR)/mconf $(IDF_PATH)/Kconfig
KCONFIG_CONFIG=$(PROJECT_PATH)/sdkconfig \
COMPONENT_KCONFIGS="$(COMPONENT_KCONFIGS)" \
COMPONENT_KCONFIGS_PROJBUILD="$(COMPONENT_KCONFIGS_PROJBUILD)" \
$(KCONFIG_TOOL_DIR)/mconf $(IDF_PATH)/Kconfig
ifeq ("$(wildcard $(PROJECT_PATH)/sdkconfig)","") ifeq ("$(wildcard $(SDKCONFIG))","")
#No sdkconfig found. Need to run menuconfig to make this if we need it. #No sdkconfig found. Need to run menuconfig to make this if we need it.
$(PROJECT_PATH)/sdkconfig: menuconfig $(SDKCONFIG): menuconfig
endif endif
defconfig: $(KCONFIG_TOOL_DIR)/mconf $(IDF_PATH)/Kconfig $(BUILD_DIR_BASE) defconfig: $(KCONFIG_TOOL_DIR)/mconf $(IDF_PATH)/Kconfig $(BUILD_DIR_BASE)
$(summary) DEFCONFIG $(summary) DEFCONFIG
$(Q) mkdir -p $(PROJECT_PATH)/build/include/config $(Q) mkdir -p $(BUILD_DIR_BASE)/include/config
$(Q) KCONFIG_AUTOHEADER=$(PROJECT_PATH)/build/include/sdkconfig.h \ $(Q) $(KCONFIG_TOOL_ENV) $(KCONFIG_TOOL_DIR)/conf --olddefconfig $(IDF_PATH)/Kconfig
KCONFIG_CONFIG=$(PROJECT_PATH)/sdkconfig \
COMPONENT_KCONFIGS="$(COMPONENT_KCONFIGS)" \
COMPONENT_KCONFIGS_PROJBUILD="$(COMPONENT_KCONFIGS_PROJBUILD)" \
$(KCONFIG_TOOL_DIR)/conf --olddefconfig $(IDF_PATH)/Kconfig
# Work out of whether we have to build the Kconfig makefile # Work out of whether we have to build the Kconfig makefile
# (auto.conf), or if we're in a situation where we don't need it # (auto.conf), or if we're in a situation where we don't need it
NON_CONFIG_TARGETS := clean %-clean get_variable help menuconfig defconfig NON_CONFIG_TARGETS := clean %-clean get_variable help menuconfig defconfig
AUTO_CONF_REGEN_TARGET := $(PROJECT_PATH)/build/include/config/auto.conf AUTO_CONF_REGEN_TARGET := $(BUILD_DIR_BASE)/include/config/auto.conf
# disable AUTO_CONF_REGEN_TARGET if all targets are non-config targets # disable AUTO_CONF_REGEN_TARGET if all targets are non-config targets
# (and not building default target) # (and not building default target)
@ -46,19 +46,15 @@ ifneq ("$(MAKECMDGOALS)","")
ifeq ($(filter $(NON_CONFIG_TARGETS), $(MAKECMDGOALS)),$(MAKECMDGOALS)) ifeq ($(filter $(NON_CONFIG_TARGETS), $(MAKECMDGOALS)),$(MAKECMDGOALS))
AUTO_CONF_REGEN_TARGET := AUTO_CONF_REGEN_TARGET :=
# dummy target # dummy target
$(PROJECT_PATH)/build/include/config/auto.conf: $(BUILD_DIR_BASE)/include/config/auto.conf:
endif endif
endif endif
$(AUTO_CONF_REGEN_TARGET) $(PROJECT_PATH)/build/include/sdkconfig.h: $(PROJECT_PATH)/sdkconfig $(KCONFIG_TOOL_DIR)/conf $(COMPONENT_KCONFIGS) $(COMPONENT_KCONFIGS_PROJBUILD) $(AUTO_CONF_REGEN_TARGET) $(BUILD_DIR_BASE)/include/sdkconfig.h: $(SDKCONFIG) $(KCONFIG_TOOL_DIR)/conf $(COMPONENT_KCONFIGS) $(COMPONENT_KCONFIGS_PROJBUILD)
$(summary) GENCONFIG $(summary) GENCONFIG
$(Q) mkdir -p $(PROJECT_PATH)/build/include/config $(Q) mkdir -p $(BUILD_DIR_BASE)/include/config
$(Q) cd build; KCONFIG_AUTOHEADER="$(PROJECT_PATH)/build/include/sdkconfig.h" \ $(Q) cd $(BUILD_DIR_BASE); $(KCONFIG_TOOL_ENV) $(KCONFIG_TOOL_DIR)/conf --silentoldconfig $(IDF_PATH)/Kconfig
KCONFIG_CONFIG=$(PROJECT_PATH)/sdkconfig \ $(Q) touch $(AUTO_CONF_REGEN_TARGET) $(BUILD_DIR_BASE)/include/sdkconfig.h
COMPONENT_KCONFIGS="$(COMPONENT_KCONFIGS)" \
COMPONENT_KCONFIGS_PROJBUILD="$(COMPONENT_KCONFIGS_PROJBUILD)" \
$(KCONFIG_TOOL_DIR)/conf --silentoldconfig $(IDF_PATH)/Kconfig
$(Q) touch $(AUTO_CONF_REGEN_TARGET) $(PROJECT_PATH)/build/include/sdkconfig.h
# touch to ensure both output files are newer - as 'conf' can also update sdkconfig (a dependency). Without this, # touch to ensure both output files are newer - as 'conf' can also update sdkconfig (a dependency). Without this,
# sometimes you can get an infinite make loop on Windows where sdkconfig always gets regenerated newer # sometimes you can get an infinite make loop on Windows where sdkconfig always gets regenerated newer
# than the target(!) # than the target(!)
@ -68,4 +64,4 @@ clean: config-clean
config-clean: config-clean:
$(summary RM CONFIG) $(summary RM CONFIG)
$(MAKE) -C $(KCONFIG_TOOL_DIR) clean $(MAKE) -C $(KCONFIG_TOOL_DIR) clean
$(Q) rm -rf $(PROJECT_PATH)/build/include/config $(PROJECT_PATH)/build/include/sdkconfig.h $(Q) rm -rf $(BUILD_DIR_BASE)/include/config $(BUILD_DIR_BASE)/include/sdkconfig.h

View file

@ -2,7 +2,7 @@
# #
# Test the build system for basic consistency # Test the build system for basic consistency
# #
# Just a bash script that tests some likely make failure scenarios in a row # A bash script that tests some likely make failure scenarios in a row
# Creates its own test build directory under TMP and cleans it up when done. # Creates its own test build directory under TMP and cleans it up when done.
# #
# Environment variables: # Environment variables:
@ -11,6 +11,18 @@
# ESP_IDF_TEMPLATE_GIT - Can override git clone source for template app. Otherwise github. # ESP_IDF_TEMPLATE_GIT - Can override git clone source for template app. Otherwise github.
# NOCLEANUP - Set to '1' if you want the script to leave its temporary directory when done, for post-mortem. # NOCLEANUP - Set to '1' if you want the script to leave its temporary directory when done, for post-mortem.
# #
#
# Internals:
# * The tests run in sequence & the system keeps track of all failures to print at the end.
# * BUILD directory is set to default BUILD_DIR_BASE
# * The "print_status" function both prints a status line to the log and keeps track of which test is running.
# * Calling the "failure" function prints a failure message to the log and also adds to the list of failures to print at the end.
# * The function "assert_built" tests for a file relative to the BUILD directory.
# * The function "take_build_snapshot" can be paired with the functions "assert_rebuilt" and "assert_not_rebuilt" to compare file timestamps and verify if they were rebuilt or not since the snapshot was taken.
#
# To add a new test case, add it to the end of the run_tests function. Note that not all test cases do comprehensive cleanup
# (although very invasive ones like appending CRLFs to all files take a copy of the esp-idf tree), however the clean_build_dir
# function can be used to force-delete all files from the build output directory.
# Set up some variables # Set up some variables
# #
@ -21,110 +33,137 @@ export V=1
function run_tests() function run_tests()
{ {
FAILURES= FAILURES=
STATUS="Starting" STATUS="Starting"
print_status "Checking prerequisites" print_status "Checking prerequisites"
[ -z ${IDF_PATH} ] && echo "IDF_PATH is not set. Need path to esp-idf installation." && exit 2 [ -z ${IDF_PATH} ] && echo "IDF_PATH is not set. Need path to esp-idf installation." && exit 2
print_status "Cloning template from ${ESP_IDF_TEMPLATE_GIT}..." print_status "Cloning template from ${ESP_IDF_TEMPLATE_GIT}..."
git clone ${ESP_IDF_TEMPLATE_GIT} template git clone ${ESP_IDF_TEMPLATE_GIT} template
cd template cd template
git checkout ${CI_BUILD_REF_NAME} || echo "Using esp-idf-template default branch..." git checkout ${CI_BUILD_REF_NAME} || echo "Using esp-idf-template default branch..."
print_status "Updating template config..." print_status "Updating template config..."
make defconfig || exit $? make defconfig || exit $?
BOOTLOADER_BINS="bootloader/bootloader.elf bootloader/bootloader.bin" BOOTLOADER_BINS="bootloader/bootloader.elf bootloader/bootloader.bin"
APP_BINS="app-template.elf app-template.bin" APP_BINS="app-template.elf app-template.bin"
print_status "Initial clean build" print_status "Initial clean build"
# if make fails here, everything fails # if make fails here, everything fails
make || exit $? make || exit $?
# check all the expected build artifacts from the clean build # check all the expected build artifacts from the clean build
assert_built ${APP_BINS} ${BOOTLOADER_BINS} partitions_singleapp.bin assert_built ${APP_BINS} ${BOOTLOADER_BINS} partitions_singleapp.bin
[ -f ${BUILD}/partition*.bin ] || failure "A partition table should have been built" [ -f ${BUILD}/partition*.bin ] || failure "A partition table should have been built"
print_status "Updating component source file rebuilds component" print_status "Updating component source file rebuilds component"
# touch a file & do a build # touch a file & do a build
take_build_snapshot take_build_snapshot
touch ${IDF_PATH}/components/esp32/syscalls.c touch ${IDF_PATH}/components/esp32/syscalls.c
make || failure "Failed to partial build" make || failure "Failed to partial build"
assert_rebuilt ${APP_BINS} esp32/libesp32.a esp32/syscalls.o assert_rebuilt ${APP_BINS} esp32/libesp32.a esp32/syscalls.o
assert_not_rebuilt lwip/liblwip.a freertos/libfreertos.a ${BOOTLOADER_BINS} partitions_singleapp.bin assert_not_rebuilt lwip/liblwip.a freertos/libfreertos.a ${BOOTLOADER_BINS} partitions_singleapp.bin
print_status "Bootloader source file rebuilds bootloader" print_status "Bootloader source file rebuilds bootloader"
take_build_snapshot take_build_snapshot
touch ${IDF_PATH}/components/bootloader/src/main/bootloader_start.c touch ${IDF_PATH}/components/bootloader/src/main/bootloader_start.c
make bootloader || failure "Failed to partial build bootloader" make bootloader || failure "Failed to partial build bootloader"
assert_rebuilt ${BOOTLOADER_BINS} bootloader/main/bootloader_start.o assert_rebuilt ${BOOTLOADER_BINS} bootloader/main/bootloader_start.o
assert_not_rebuilt ${APP_BINS} partitions_singleapp.bin assert_not_rebuilt ${APP_BINS} partitions_singleapp.bin
print_status "Partition CSV file rebuilds partitions" print_status "Partition CSV file rebuilds partitions"
take_build_snapshot take_build_snapshot
touch ${IDF_PATH}/components/partition_table/partitions_singleapp.csv touch ${IDF_PATH}/components/partition_table/partitions_singleapp.csv
make partition_table make partition_table || failure "Failed to build partition table"
assert_rebuilt partitions_singleapp.bin assert_rebuilt partitions_singleapp.bin
assert_not_rebuilt app-template.bin app-template.elf ${BOOTLOADER_BINS} assert_not_rebuilt app-template.bin app-template.elf ${BOOTLOADER_BINS}
print_status "Partial build doesn't compile anything by default" print_status "Partial build doesn't compile anything by default"
take_build_snapshot take_build_snapshot
# verify no build files are refreshed by a partial make # verify no build files are refreshed by a partial make
ALL_BUILD_FILES=$(find ${BUILD} -type f | sed "s@${BUILD}/@@") ALL_BUILD_FILES=$(find ${BUILD} -type f | sed "s@${BUILD}/@@")
make make || failure "Partial build failed"
assert_not_rebuilt ${ALL_BUILD_FILES} assert_not_rebuilt ${ALL_BUILD_FILES}
print_status "Cleaning should remove all files from build" print_status "Cleaning should remove all files from build"
make clean make clean || failure "Failed to make clean"
ALL_BUILD_FILES=$(find ${BUILD} -type f) ALL_BUILD_FILES=$(find ${BUILD} -type f)
if [ -n "${ALL_BUILD_FILES}" ]; then if [ -n "${ALL_BUILD_FILES}" ]; then
failure "Files weren't cleaned: ${ALL_BUILD_FILES}" failure "Files weren't cleaned: ${ALL_BUILD_FILES}"
fi fi
print_status "Bootloader build shouldn't leave build output anywhere else" print_status "Bootloader build shouldn't leave build output anywhere else"
rm -rf --preserve-root ${BUILD} clean_build_dir
make bootloader make bootloader
# find wizardry: find any file not named sdkconfig.h that # find wizardry: find any file not named sdkconfig.h that
# isn't in the "bootloader" or "config" directories # isn't in the "bootloader" or "config" directories
find ${BUILD} -type d \( -name bootloader -o -name config \) -prune , -type f ! -name sdkconfig.h || failure "Bootloader built files outside the bootloader or config directories" find ${BUILD} -type d \( -name bootloader -o -name config \) -prune , -type f ! -name sdkconfig.h || failure "Bootloader built files outside the bootloader or config directories"
print_status "Can still clean build if all text files are CRLFs" print_status "Moving BUILD_DIR_BASE out of tree"
make clean clean_build_dir
find . -exec unix2dos {} \; # CRLFify template dir OUTOFTREE_BUILD=${TESTDIR}/alt_build
# make a copy of esp-idf and CRLFify it make BUILD_DIR_BASE=${OUTOFTREE_BUILD} || failure "Failed to build with BUILD_DIR_BASE overriden"
CRLF_ESPIDF=${TESTDIR}/esp-idf-crlf NEW_BUILD_FILES=$(find ${OUTOFREE_BUILD} -type f)
mkdir -p ${CRLF_ESPIDF} if [ -z "${NEW_BUILD_FILES}" ]; then
cp -rv ${IDF_PATH}/* ${CRLF_ESPIDF} failure "No files found in new build directory!"
# don't CRLFify executable files, as Linux will fail to execute them fi
find ${CRLF_ESPIDF} -type f ! -perm 755 -exec unix2dos {} \; DEFAULT_BUILD_FILES=$(find ${BUILD} -mindepth 1)
make IDF_PATH=${CRLF_ESPIDF} if [ -n "${DEFAULT_BUILD_FILES}" ]; then
# do the same checks we do for the clean build failure "Some files were incorrectly put into the default build directory: ${DEFAULT_BUILD_FILES}"
assert_built ${APP_BINS} ${BOOTLOADER_BINS} partitions_singleapp.bin fi
[ -f ${BUILD}/partition*.bin ] || failure "A partition table should have been built in CRLF mode"
# NOTE: If adding new tests, add them above this CRLF test... print_status "BUILD_DIR_BASE inside default build directory"
clean_build_dir
make BUILD_DIR_BASE=build/subdirectory || failure "Failed to build with BUILD_DIR_BASE as subdir"
NEW_BUILD_FILES=$(find ${BUILD}/subdirectory -type f)
if [ -z "${NEW_BUILD_FILES}" ]; then
failure "No files found in new build directory!"
fi
print_status "All tests completed" print_status "Parallel builds should work OK"
if [ -n "${FAILURES}" ]; then clean_build_dir
echo "Some failures were detected:" (make -j5 2>&1 | tee ${TESTDIR}/parallel_build.log) || failure "Failed to build in parallel"
echo -e "${FAILURES}" if grep -q "warning: jobserver unavailable" ${TESTDIR}/parallel_build.log; then
exit 1 failure "Parallel build prints 'warning: jobserver unavailable' errors"
else fi
echo "Build tests passed."
fi print_status "Can still clean build if all text files are CRLFs"
make clean || failure "Unexpected failure to make clean"
find . -exec unix2dos {} \; # CRLFify template dir
# make a copy of esp-idf and CRLFify it
CRLF_ESPIDF=${TESTDIR}/esp-idf-crlf
mkdir -p ${CRLF_ESPIDF}
cp -rv ${IDF_PATH}/* ${CRLF_ESPIDF}
# don't CRLFify executable files, as Linux will fail to execute them
find ${CRLF_ESPIDF} -type f ! -perm 755 -exec unix2dos {} \;
make IDF_PATH=${CRLF_ESPIDF} || failure "Failed to build with CRLFs in source"
# do the same checks we do for the clean build
assert_built ${APP_BINS} ${BOOTLOADER_BINS} partitions_singleapp.bin
[ -f ${BUILD}/partition*.bin ] || failure "A partition table should have been built in CRLF mode"
print_status "All tests completed"
if [ -n "${FAILURES}" ]; then
echo "Some failures were detected:"
echo -e "${FAILURES}"
exit 1
else
echo "Build tests passed."
fi
} }
function print_status() function print_status()
{ {
echo "******** $1" echo "******** $1"
STATUS="$1" STATUS="$1"
} }
function failure() function failure()
{ {
echo "!!!!!!!!!!!!!!!!!!!" echo "!!!!!!!!!!!!!!!!!!!"
echo "FAILURE: $1" echo "FAILURE: $1"
echo "!!!!!!!!!!!!!!!!!!!" echo "!!!!!!!!!!!!!!!!!!!"
FAILURES="${FAILURES}${STATUS} :: $1\n" FAILURES="${FAILURES}${STATUS} :: $1\n"
} }
TESTDIR=${TMP}/build_system_tests_$$ TESTDIR=${TMP}/build_system_tests_$$
@ -140,62 +179,68 @@ BUILD=${TESTDIR}/template/build
# copy all the build output to a snapshot directory # copy all the build output to a snapshot directory
function take_build_snapshot() function take_build_snapshot()
{ {
rm -rf ${SNAPSHOT} rm -rf ${SNAPSHOT}
cp -ap ${TESTDIR}/template/build ${SNAPSHOT} cp -ap ${TESTDIR}/template/build ${SNAPSHOT}
} }
# verify that all the arguments are present in the build output directory # verify that all the arguments are present in the build output directory
function assert_built() function assert_built()
{ {
until [ -z "$1" ]; do until [ -z "$1" ]; do
if [ ! -f "${BUILD}/$1" ]; then if [ ! -f "${BUILD}/$1" ]; then
failure "File $1 should be in the build output directory" failure "File $1 should be in the build output directory"
fi fi
shift shift
done done
} }
# Test if a file has been rebuilt. # Test if a file has been rebuilt.
function file_was_rebuilt() function file_was_rebuilt()
{ {
# can't use [ a -ot b ] here as -ot only gives second resolution # can't use [ a -ot b ] here as -ot only gives second resolution
# but stat -c %y seems to be microsecond at least for tmpfs, ext4.. # but stat -c %y seems to be microsecond at least for tmpfs, ext4..
if [ "$(stat -c %y ${SNAPSHOT}/$1)" != "$(stat -c %y ${BUILD}/$1)" ]; then if [ "$(stat -c %y ${SNAPSHOT}/$1)" != "$(stat -c %y ${BUILD}/$1)" ]; then
return 0 return 0
else else
return 1 return 1
fi fi
} }
# verify all the arguments passed in were rebuilt relative to the snapshot # verify all the arguments passed in were rebuilt relative to the snapshot
function assert_rebuilt() function assert_rebuilt()
{ {
until [ -z "$1" ]; do until [ -z "$1" ]; do
assert_built "$1" assert_built "$1"
if [ ! -f "${SNAPSHOT}/$1" ]; then if [ ! -f "${SNAPSHOT}/$1" ]; then
failure "File $1 should have been original build snapshot" failure "File $1 should have been original build snapshot"
fi fi
if ! file_was_rebuilt "$1"; then if ! file_was_rebuilt "$1"; then
failure "File $1 should have been rebuilt" failure "File $1 should have been rebuilt"
fi fi
shift shift
done done
} }
# verify all the arguments are in the build directory & snapshot, # verify all the arguments are in the build directory & snapshot,
# but were not rebuilt # but were not rebuilt
function assert_not_rebuilt() function assert_not_rebuilt()
{ {
until [ -z "$1" ]; do until [ -z "$1" ]; do
assert_built "$1" assert_built "$1"
if [ ! -f "${SNAPSHOT}/$1" ]; then if [ ! -f "${SNAPSHOT}/$1" ]; then
failure "File $1 should be in snapshot build directory" failure "File $1 should be in snapshot build directory"
fi fi
if file_was_rebuilt "$1"; then if file_was_rebuilt "$1"; then
failure "File $1 should not have been rebuilt" failure "File $1 should not have been rebuilt"
fi fi
shift shift
done done
}
# do a "clean" that doesn't depend on 'make clean'
function clean_build_dir()
{
rm -rf --preserve-root ${BUILD}/*
} }
cd ${TESTDIR} cd ${TESTDIR}