BINDIR := bin LCOV_DIRECTORY := lcov OUTPUT_BINARY := $(BINDIR)/host_tests CORE_PATH := ../../cores/esp8266 LIBRARIES_PATH := ../../libraries FORCE32 ?= 1 OPTZ ?= -Os V ?= 0 DEFSYM_FS ?= -Wl,--defsym,_FS_start=0x40300000 -Wl,--defsym,_FS_end=0x411FA000 -Wl,--defsym,_FS_page=0x100 -Wl,--defsym,_FS_block=0x2000 -Wl,--defsym,_EEPROM_start=0x411fb000 MAKEFILE = $(word 1, $(MAKEFILE_LIST)) # I wasn't able to build with clang when -coverage flag is enabled, forcing GCC on OS X ifeq ($(shell uname -s),Darwin) CC ?= gcc CXX ?= g++ endif GCOV ?= gcov VALGRIND ?= valgrind LCOV ?= lcov GENHTML ?= genhtml ifeq ($(FORCE32),1) SIZEOFLONG = $(shell echo 'int main(){return sizeof(long);}'|$(CXX) -m32 -x c++ - -o sizeoflong 2>/dev/null && ./sizeoflong; echo $$?; rm -f sizeoflong;) ifneq ($(SIZEOFLONG),4) $(warning Cannot compile in 32 bit mode, switching to native mode) else N32 = 32 M32 = -m32 E32 = .32 endif endif ifeq ($(N32),32) $(warning compiling in 32 bits mode) else $(warning compiling in native mode) endif ifeq ($(V), 0) VERBC = @echo "C $@"; VERBCXX = @echo "C++ $@"; VERBLD = @echo "LD $@"; VERBAR = @echo "AR $@"; else VERBC = VERBCXX = VERBLD = VERBAR = endif $(shell mkdir -p $(BINDIR)) CORE_CPP_FILES := $(addprefix $(CORE_PATH)/,\ StreamString.cpp \ Stream.cpp \ WString.cpp \ Print.cpp \ FS.cpp \ spiffs_api.cpp \ MD5Builder.cpp \ ../../libraries/LittleFS/src/LittleFS.cpp \ core_esp8266_noniso.cpp \ spiffs/spiffs_cache.cpp \ spiffs/spiffs_check.cpp \ spiffs/spiffs_gc.cpp \ spiffs/spiffs_hydrogen.cpp \ spiffs/spiffs_nucleus.cpp \ libb64/cencode.cpp \ libb64/cdecode.cpp \ Schedule.cpp \ HardwareSerial.cpp \ crc32.cpp \ Updater.cpp \ ) \ $(addprefix $(LIBRARIES_PATH)/ESP8266SdFat/src/, \ FatLib/FatFile.cpp \ FatLib/FatFileLFN.cpp \ FatLib/FatFilePrint.cpp \ FatLib/FatFileSFN.cpp \ FatLib/FatVolume.cpp \ FatLib/FmtNumber.cpp \ FatLib/StdioStream.cpp \ ) \ $(LIBRARIES_PATH)/SDFS/src/SDFS.cpp \ $(LIBRARIES_PATH)/SD/src/SD.cpp CORE_C_FILES := $(addprefix $(CORE_PATH)/,\ ../../libraries/LittleFS/src/lfs.c \ ../../libraries/LittleFS/src/lfs_util.c \ ) MOCK_CPP_FILES_COMMON := $(addprefix common/,\ Arduino.cpp \ flash_hal_mock.cpp \ spiffs_mock.cpp \ littlefs_mock.cpp \ sdfs_mock.cpp \ WMath.cpp \ MockUART.cpp \ MockTools.cpp \ MocklwIP.cpp \ MockDigital.cpp \ ) MOCK_CPP_FILES := $(MOCK_CPP_FILES_COMMON) $(addprefix common/,\ ArduinoCatch.cpp \ ) MOCK_CPP_FILES_EMU := $(MOCK_CPP_FILES_COMMON) $(addprefix common/,\ ArduinoMain.cpp \ ArduinoMainUdp.cpp \ ArduinoMainSpiffs.cpp \ ArduinoMainLittlefs.cpp \ user_interface.cpp \ ) MOCK_C_FILES := $(addprefix common/,\ md5.c \ noniso.c \ ) INC_PATHS += $(addprefix -I, \ . \ common \ $(CORE_PATH) \ ) INC_PATHS += $(addprefix -I,\ $(shell echo ../../libraries/*/src) \ $(shell echo ../../libraries/*) \ ../../tools/sdk/include \ ../../tools/sdk/lwip2/include \ ) TEST_CPP_FILES := \ fs/test_fs.cpp \ core/test_pgmspace.cpp \ core/test_md5builder.cpp \ core/test_string.cpp \ core/test_PolledTimeout.cpp \ core/test_Print.cpp \ core/test_Updater.cpp PREINCLUDES := \ -include common/mock.h \ -include common/c_types.h \ ifneq ($(D),) OPTZ=-O0 DEBUG += -DDEBUG_ESP_PORT=Serial DEBUG += -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP_HTTP_SERVER -DDEBUG_ESP_CORE -DDEBUG_ESP_WIFI -DDEBUG_ESP_HTTP_UPDATE -DDEBUG_ESP_UPDATER -DDEBUG_ESP_OTA -DDEBUG_ESP_MDNS endif FLAGS += $(DEBUG) -Wall $(OPTZ) -fno-common -g $(M32) FLAGS += -fstack-check -fstack-protector-all FLAGS += -DHTTPCLIENT_1_1_COMPATIBLE=0 FLAGS += -DLWIP_IPV6=0 FLAGS += -DHOST_MOCK=1 FLAGS += -DNONOSDK221=1 FLAGS += $(MKFLAGS) FLAGS += -Wimplicit-fallthrough=2 # allow "// fall through" comments to stop spurious warnings CXXFLAGS += -std=c++11 -fno-rtti $(FLAGS) -funsigned-char CFLAGS += -std=c99 $(FLAGS) -funsigned-char LDFLAGS += -coverage $(OPTZ) -g $(M32) VALGRINDFLAGS += --leak-check=full --track-origins=yes --error-limit=no --show-leak-kinds=all --error-exitcode=999 CXXFLAGS += -Wno-error=format-security # cores/esp8266/Print.cpp:42:24: error: format not a string literal and no format arguments [-Werror=format-security] -- (os_printf_plus(not_the_best_way)) #CXXFLAGS += -Wno-format-security # cores/esp8266/Print.cpp:42:40: warning: format not a string literal and no format arguments [-Wformat-security] -- (os_printf_plus(not_the_best_way)) remduplicates = $(strip $(if $1,$(firstword $1) $(call remduplicates,$(filter-out $(firstword $1),$1)))) C_SOURCE_FILES = $(MOCK_C_FILES) $(CORE_C_FILES) CPP_SOURCE_FILES = $(MOCK_CPP_FILES) $(CORE_CPP_FILES) $(TEST_CPP_FILES) C_OBJECTS = $(C_SOURCE_FILES:.c=.c$(E32).o) CPP_OBJECTS_CORE = $(MOCK_CPP_FILES:.cpp=.cpp$(E32).o) $(CORE_CPP_FILES:.cpp=.cpp$(E32).o) CPP_OBJECTS_TESTS = $(TEST_CPP_FILES:.cpp=.cpp$(E32).o) CPP_OBJECTS = $(CPP_OBJECTS_CORE) $(CPP_OBJECTS_TESTS) OBJECTS = $(C_OBJECTS) $(CPP_OBJECTS) COVERAGE_FILES = $(OBJECTS:.o=.gc*) all: help CI: # run CI $(MAKE) -f $(MAKEFILE) MKFLAGS="-Werror -coverage" FORCE32=0 OPTZ=-O0 doCI doCI: build-info $(OUTPUT_BINARY) valgrind test gcov test: $(OUTPUT_BINARY) # run host test for CI $(OUTPUT_BINARY) clean: make FORCE32=0 cleanarch; make FORCE32=1 cleanarch cleanarch: clean-objects clean-coverage # clean everything rm -rf $(BINDIR) clean-objects: rm -rf $(C_OBJECTS) $(CPP_OBJECTS_CORE) $(CPP_OBJECTS_CORE_EMU) $(CPP_OBJECTS_TESTS) clean-coverage: rm -rf $(COVERAGE_FILES) $(LCOV_DIRECTORY) *.gcov gcov: test # run coverage for CI find $(CORE_PATH) -name "*.gcno" -exec $(GCOV) -r -pb {} + valgrind: $(OUTPUT_BINARY) mkdir -p $(LCOV_DIRECTORY) $(LCOV) --directory ../../cores/esp8266/ --zerocounters $(VALGRIND) $(VALGRINDFLAGS) $(OUTPUT_BINARY) $(LCOV) --directory $(CORE_PATH) --capture --output-file $(LCOV_DIRECTORY)/app.info -$(GENHTML) $(LCOV_DIRECTORY)/app.info -o $(LCOV_DIRECTORY) build-info: # show toolchain version @echo "-------- build tools info --------" @echo "CC: " $(CC) $(CC) -v @echo "CXX: " $(CXX) $(CXX) -v @echo "GCOV: " $(GCOV) $(GCOV) -v @echo "----------------------------------" -include $(BINDIR)/.*.d .SUFFIXES: %.c$(E32).o: %.c $(VERBC) $(CC) $(PREINCLUDES) $(CFLAGS) $(INC_PATHS) -MD -MF $(BINDIR)/.$(notdir $<).d -c -o $@ $< .PRECIOUS: %.cpp$(E32).o %.cpp$(E32).o: %.cpp $(VERBCXX) $(CXX) $(PREINCLUDES) $(CXXFLAGS) $(INC_PATHS) -MD -MF $(BINDIR)/.$(notdir $<).d -c -o $@ $< $(BINDIR)/core.a: $(C_OBJECTS) $(CPP_OBJECTS_CORE) ar -rcu $@ $^ ranlib -c $@ $(OUTPUT_BINARY): $(CPP_OBJECTS_TESTS) $(BINDIR)/core.a $(VERBLD) $(CXX) $(DEFSYM_FS) $(LDFLAGS) $^ -o $@ ################################################# # building ino sources ARDUINO_LIBS := \ $(addprefix $(CORE_PATH)/,\ IPAddress.cpp \ Updater.cpp \ base64.cpp \ ) \ $(addprefix ../../libraries/ESP8266WiFi/src/,\ ESP8266WiFi.cpp \ ESP8266WiFiAP.cpp \ ESP8266WiFiGeneric.cpp \ ESP8266WiFiMulti.cpp \ ESP8266WiFiSTA-WPS.cpp \ ESP8266WiFiSTA.cpp \ ESP8266WiFiScan.cpp \ WiFiClient.cpp \ WiFiUdp.cpp \ WiFiClientSecureBearSSL.cpp \ WiFiServerSecureBearSSL.cpp \ BearSSLHelpers.cpp \ CertStoreBearSSL.cpp \ ) OPT_ARDUINO_LIBS ?= $(addprefix ../../libraries/,\ $(addprefix ESP8266WebServer/src/,\ detail/mimetable.cpp \ ) \ $(addprefix ESP8266mDNS/src/,\ LEAmDNS.cpp \ LEAmDNS_Control.cpp \ LEAmDNS_Helpers.cpp \ LEAmDNS_Structs.cpp \ LEAmDNS_Transfer.cpp \ ESP8266mDNS.cpp \ ) \ ArduinoOTA/ArduinoOTA.cpp \ DNSServer/src/DNSServer.cpp \ ESP8266AVRISP/src/ESP8266AVRISP.cpp \ ESP8266HTTPClient/src/ESP8266HTTPClient.cpp \ ) MOCK_ARDUINO_LIBS := $(addprefix common/,\ ClientContextSocket.cpp \ ClientContextTools.cpp \ MockWiFiServerSocket.cpp \ MockWiFiServer.cpp \ UdpContextSocket.cpp \ HostWiring.cpp \ MockEsp.cpp \ MockEEPROM.cpp \ MockSPI.cpp \ strl.cpp \ ) CPP_SOURCES_CORE_EMU = \ $(MOCK_CPP_FILES_EMU) \ $(CORE_CPP_FILES) \ $(MOCK_ARDUINO_LIBS) \ $(OPT_ARDUINO_LIBS) \ $(ARDUINO_LIBS) \ LIBSSLFILE = ../../tools/sdk/ssl/bearssl/build$(N32)/libbearssl.a ifeq (,$(wildcard $(LIBSSLFILE))) LIBSSL = else LIBSSL = $(LIBSSLFILE) endif ssl: # download source and build BearSSL cd ../../tools/sdk/ssl && make native$(N32) ULIBPATHS = $(shell echo $(ULIBDIRS) | sed 's,:, ,g') USERLIBDIRS = $(shell test -z "$(ULIBPATHS)" || for d in $(ULIBPATHS); do for dd in $$d $$d/src; do test -d $$dd && { echo -I$$dd; echo "userlib: using directory '$$dd'" 1>&2; } done; done) USERLIBSRCS = $(shell test -z "$(ULIBPATHS)" || for d in $(ULIBPATHS); do for ss in $$d/*.cpp $$d/src/*.cpp; do test -r $$ss && echo $$ss; done; done) INC_PATHS += $(USERLIBDIRS) INC_PATHS += -I$(INODIR)/.. CPP_OBJECTS_CORE_EMU = $(CPP_SOURCES_CORE_EMU:.cpp=.cpp$(E32).o) $(USERLIBSRCS:.cpp=.cpp$(E32).o) bin/fullcore.a: $(C_OBJECTS) $(CPP_OBJECTS_CORE_EMU) $(VERBAR) ar -rcu $@ $^ $(VERBAR) ranlib -c $@ %: %.ino.cpp$(E32).o bin/fullcore.a $(VERBLD) $(CXX) $(LDFLAGS) $< bin/fullcore.a $(LIBSSL) -o $@ @echo "----> $@ <----" ################################################# # are we in primary make call ? ifeq ($(INO),) %: %.ino @# recursive 'make' with paths $(MAKE) -f $(MAKEFILE) MKFLAGS=-Wextra INODIR=$(dir $@) INO=$(notdir $@) $(BINDIR)/$(notdir $@)/$(notdir $@) @# see below the new build rule with fixed output path outside from core location ##################### # recursive call on ino target else $(BINDIR)/$(INO)/$(INO).ino.cpp: @# arduino builder would come around here (.ino -> .ino.cpp) @mkdir -p $(BINDIR)/$(INO); \ ( \ echo "#include <$(INODIR)/$(INO).ino>"; \ for i in $(INODIR)/*.ino; do \ test "$$i" = $(INODIR)/$(INO).ino || echo "#include \"$$i\""; \ done; \ ) > $(BINDIR)/$(INO)/$(INO).ino.cpp endif # recursive ##################### ################################################# .PHONY: list list: # show core example list @for dir in ../../libraries/*/examples/* \ ../../libraries/*/examples/*/*; do \ test -d $$dir || continue; \ examplename=$${dir##*/}; \ test -f $${dir}/$${examplename}.ino || continue; \ echo $${dir}/$${examplename}; \ done | sort; \ ################################################# # help .PHONY: help help: @cat README.txt @echo "" @echo "Make rules:" @echo "" @sed -rne 's,([^: \t]*):[^=#]*#[\t ]*(.*),\1 - \2,p' $(MAKEFILE) @echo ""