Makefile.buildtests 10.7 KB
ifneq (, $(filter buildtest info-concurrency, $(MAKECMDGOALS)))
  ifeq (, $(strip $(NPROC)))
    # Linux (utility program)
    NPROC := $(shell nproc 2>/dev/null)

    ifeq (, $(strip $(NPROC)))
      # Linux (generic)
      NPROC := $(shell grep -c ^processor /proc/cpuinfo 2>/dev/null)
    endif
    ifeq (, $(strip $(NPROC)))
      # BSD (at least FreeBSD and Mac OSX)
      NPROC := $(shell sysctl -n hw.ncpu 2>/dev/null)
    endif
    ifeq (, $(strip $(NPROC)))
      # Fallback
      NPROC := 1
    endif

    NPROC := $(shell echo $$(($(NPROC) + 1)))

    ifneq (, $(NPROC_MAX))
      NPROC := $(shell if [ ${NPROC} -gt $(NPROC_MAX) ]; then echo $(NPROC_MAX); else echo ${NPROC}; fi)
    endif
    ifneq (, $(NPROC_MIN))
      NPROC := $(shell if [ ${NPROC} -lt $(NPROC_MIN) ]; then echo $(NPROC_MIN); else echo ${NPROC}; fi)
    endif
  endif
endif

.PHONY: buildtest info-objsize info-buildsize info-buildsizes \
        info-buildsizes-diff info-build info-boards-supported \
        info-features-missing info-boards-features-missing

ifeq ($(BUILD_IN_DOCKER),1)
buildtest: ..in-docker-container
else
buildtest:
	@ \
	BUILDTESTOK=true; \
	APP_RETRY=0; \
	for BOARD in $$($(MAKE) -s info-boards-supported); do \
	  RIOTNOLINK=$$(echo $(BOARD_INSUFFICIENT_MEMORY) | grep $${BOARD} 2>&1 >/dev/null && echo 1); \
	  ${COLOR_ECHO} -n "Building for $${BOARD} "; \
	  [ -n "$${RIOTNOLINK}" ] && ${COLOR_ECHO} -n "(no linking) "; \
	  for NTH_TRY in 1 2 3; do \
	    ${COLOR_ECHO} -n ".. "; \
	    if [ "$$NTH_TRY" != "3" ]; then export _CCACHE=$$CCACHE; else export _CCACHE=""; fi ; \
	    LOG=$$(env -i \
	        HOME=$${HOME} \
	        PATH=$${PATH} \
	        BOARD=$${BOARD} \
	        CCACHE=$${_CCACHE} \
	        $${CCACHE_DIR:+CCACHE_DIR=$${CCACHE_DIR}} \
	        $${GIT_CACHE_DIR:+GIT_CACHE_DIR=$${GIT_CACHE_DIR}} \
	        CCACHE_BASEDIR=$${CCACHE_BASEDIR} \
	        RIOTBASE=$${RIOTBASE} \
	        RIOTBOARD=$${RIOTBOARD} \
	        RIOTCPU=$${RIOTCPU} \
	        RIOTPKG=$${RIOTPKG} \
	        BINDIRBASE=$${BINDIRBASE} \
	        RIOTNOLINK=$${RIOTNOLINK} \
	        RIOT_VERSION=$${RIOT_VERSION} \
	        WERROR=$${WERROR} \
	        LTO=$${LTO} \
	        TOOLCHAIN=$${TOOLCHAIN} \
	        $(MAKE) -j$(NPROC) clean all 2>&1) ; \
	    if [ "$${?}" = "0" ]; then \
	      ${COLOR_ECHO} "${COLOR_GREEN}success${COLOR_RESET}"; \
	      if [ -n "$${BUILDTEST_VERBOSE}" ]; then \
	        echo "$${LOG}" | tail -n +2 | head -n -2 | grep -v -E '^Building application|^\"make|^patching' | awk 'NF'; \
	      fi; \
	    elif [ -n "$${RIOT_DO_RETRY}" ] && [ "$${APP_RETRY}" -lt "3" ] && [ $${NTH_TRY} != 3 ]; then \
	      ${COLOR_ECHO} -n "${COLOR_PURPLE}retrying${COLOR_RESET} "; \
	      continue; \
	    else \
	      ${COLOR_ECHO} "${COLOR_RED}failed${COLOR_RESET}"; \
	      if [ -n "$${BUILDTEST_VERBOSE}" ]; then \
	        echo "$${LOG}" | grep -v -E '^\"make'; \
	      fi; \
	      APP_RETRY=`expr $${APP_RETRY} + 1`; \
	      BUILDTESTOK=false; \
	    fi; \
	    break; \
	  done; \
	  env -i \
	    HOME=$${HOME} \
	    PATH=$${PATH} \
	    BOARD=$${BOARD} \
	    CCACHE=$${CCACHE} \
	    $${CCACHE_DIR:+CCACHE_DIR=$${CCACHE_DIR}} \
	    CCACHE_BASEDIR=$${CCACHE_BASEDIR} \
	    $${GIT_CACHE_DIR:+GIT_CACHE_DIR=$${GIT_CACHE_DIR}} \
	    RIOTBASE=$${RIOTBASE} \
	    RIOTBOARD=$${RIOTBOARD} \
	    RIOTCPU=$${RIOTCPU} \
	    RIOTPKG=$${RIOTPKG} \
	    BINDIRBASE=$${BINDIRBASE} \
	    RIOTNOLINK=$${RIOTNOLINK} \
	    RIOT_VERSION=$${RIOT_VERSION} \
	    $(MAKE) clean-intermediates 2>&1 >/dev/null || true; \
	done; \
	$${BUILDTESTOK}
endif # BUILD_IN_DOCKER

info-objsize:
	@case "${SORTROW}" in \
	  text) SORTROW=1 ;; \
	  data) SORTROW=2 ;; \
	  bss) SORTROW=3 ;; \
	  dec) SORTROW=4 ;; \
	  "") SORTROW=4 ;; \
	  *) echo "Usage: $(MAKE) info-objsize SORTROW=[text|data|bss|dec]" ; return ;; \
	esac; \
	echo -e '   text\t   data\t    bss\t    dec\t    hex\tfilename'; \
	$(SIZE) -dB $(BASELIBS) | \
	  tail -n+2 | \
	  sed -e 's#$(BINDIR)##' | \
	  sort -rnk$${SORTROW}

info-buildsize:
	@$(SIZE) -dB $(BINDIR)/$(APPLICATION).elf || echo ''

info-buildsizes: SHELL=bash
info-buildsizes:
	@echo -e "   text\t   data\t    bss\t    dec\tboard"; \
	for BOARD in $$($(MAKE) -s info-boards-supported); do \
	  echo "$$(env -i \
	    HOME=$${HOME} \
	    PATH=$${PATH} \
	    BOARD=$${BOARD} \
	    RIOTBASE=$${RIOTBASE} \
	    RIOTBOARD=$${RIOTBOARD} \
	    RIOTCPU=$${RIOTCPU} \
	    RIOTPKG=$${RIOTPKG} \
	    BINDIRBASE=$${BINDIRBASE} \
	    $(MAKE) info-buildsize 2>/dev/null | tail -n-1 | cut -f-4)" "$${BOARD}"; \
	done;

info-buildsizes-diff: SHELL=bash
info-buildsizes-diff:
	@echo -e "text\tdata\tbss\tdec\tBOARD/BINDIRBASE\n"; \
	for BOARD in $$($(MAKE) -s info-boards-supported); do \
	  for BINDIRBASE in $${OLDBIN} $${NEWBIN}; do \
	    env -i \
	      HOME=$${HOME} \
	      PATH=$${PATH} \
	      BOARD=$${BOARD} \
	      RIOTBASE=$${RIOTBASE} \
	      RIOTBOARD=$${RIOTBOARD} \
	      RIOTCPU=$${RIOTCPU} \
	      RIOTPKG=$${RIOTPKG} \
	      BINDIRBASE=$${BINDIRBASE} \
	      $(MAKE) info-buildsize 2>/dev/null | tail -n-1 | cut -f-4; \
	  done | \
	  while read -a OLD && read -a NEW; do \
	    for I in 0 1 2 3; do \
	      if [[ -n "$${NEW[I]}" && -n "$${OLD[I]}" ]]; then \
	        DIFF=$$(($${NEW[I]} - $${OLD[I]})); \
	        if [[ "$${DIFF}" -gt 0 ]]; then $(COLOR_ECHO) -n "${COLOR_RED}"; fi; \
	        if [[ "$${DIFF}" -lt 0 ]]; then $(COLOR_ECHO) -n "${COLOR_GREEN}"; fi; \
	      else \
	        DIFF="${COLOR_RED}ERR"; \
	      fi; \
	      echo -ne "$${DIFF}\t${COLOR_RESET}"; \
	    done; \
	    echo "$${BOARD}"; \
	    for I in 0 1 2 3; do echo -ne "$${OLD[I]-${COLOR_RED}ERR${COLOR_RESET}}\t"; done; echo -e "$${OLDBIN}"; \
	    for I in 0 1 2 3; do echo -ne "$${NEW[I]-${COLOR_RED}ERR${COLOR_RESET}}\t"; done; echo -e "$${NEWBIN}\n"; \
	  done; \
	done;

info-build:
	@echo 'APPLICATION: $(APPLICATION)'
	@echo ''
	@echo 'supported boards:'
	@$(foreach board,$(BOARDS),echo ' * $(board)';)
	@echo ''
	@echo 'BOARD:   $(BOARD)'
	@echo 'CPU:     $(CPU)'
	@echo 'MCU:     $(MCU)'
	@echo ''
	@echo 'RIOTBASE:  $(RIOTBASE)'
	@echo 'RIOTBOARD: $(RIOTBOARD)'
	@echo 'RIOTCPU:   $(RIOTCPU)'
	@echo 'RIOTPKG:   $(RIOTPKG)'
	@echo ''
	@echo 'DEFAULT_MODULE: $(sort $(filter-out $(DISABLE_MODULE), $(DEFAULT_MODULE)))'
	@echo 'DISABLE_MODULE: $(sort $(DISABLE_MODULE))'
	@echo 'USEMODULE:      $(sort $(filter-out $(DEFAULT_MODULE), $(USEMODULE)))'
	@echo ''
	@echo 'ELFFILE: $(ELFFILE)'
	@echo 'HEXFILE: $(HEXFILE)'
	@echo ''
	@echo 'FEATURES_REQUIRED (excl. optional features):'
	@echo '         $(or $(sort $(filter-out $(FEATURES_OPTIONAL), $(FEATURES_REQUIRED))), -none-)'
	@echo 'FEATURES_OPTIONAL (strictly "nice to have"):'
	@echo '         $(or $(sort $(FEATURES_OPTIONAL)), -none-)'
	@echo 'FEATURES_PROVIDED (by the board or USEMODULE'"'"'d drivers):'
	@echo '         $(or $(sort $(FEATURES_PROVIDED)), -none-)'
	@echo 'FEATURES_MISSING (incl. optional features):'
	@echo '         $(or $(sort $(filter-out $(FEATURES_PROVIDED), $(FEATURES_REQUIRED))), -none-)'
	@echo 'FEATURES_MISSING (only non-optional features):'
	@echo '         $(or $(sort $(filter-out $(FEATURES_OPTIONAL) $(FEATURES_PROVIDED), $(FEATURES_REQUIRED))), -none-)'
	@echo ''
	@echo 'FEATURES_CONFLICT:     $(FEATURES_CONFLICT)'
	@echo 'FEATURES_CONFLICT_MSG: $(FEATURES_CONFLICT_MSG)'
	@echo ''
	@echo 'CC:      $(CC)'
	@echo -e 'CFLAGS:$(patsubst %, \n\t%, $(CFLAGS))'
	@echo ''
	@echo 'CXX:     $(CXX)'
	@echo -e 'CXXUWFLAGS:$(patsubst %, \n\t%, $(CXXUWFLAGS))'
	@echo -e 'CXXEXFLAGS:$(patsubst %, \n\t%, $(CXXEXFLAGS))'
	@echo ''
	@echo 'LINK:    $(LINK)'
	@echo -e 'LINKFLAGS:$(patsubst %, \n\t%, $(LINKFLAGS))'
	@echo ''
	@echo 'OBJCOPY: $(OBJCOPY)'
	@echo 'OFLAGS:  $(OFLAGS)'
	@echo ''
	@echo 'FLASHER: $(FLASHER)'
	@echo 'FFLAGS:  $(FFLAGS)'
	@echo ''
	@echo 'TERMPROG:  $(TERMPROG)'
	@echo 'TERMFLAGS: $(TERMFLAGS)'
	@echo 'PORT:      $(PORT)'
	@echo ''
	@echo 'DEBUGGER:       $(DEBUGGER)'
	@echo 'DEBUGGER_FLAGS: $(DEBUGGER_FLAGS)'
	@echo
	@echo 'DOWNLOAD_TO_FILE:   $(DOWNLOAD_TO_FILE)'
	@echo 'DOWNLOAD_TO_STDOUT: $(DOWNLOAD_TO_STDOUT)'
	@echo 'UNZIP_HERE:         $(UNZIP_HERE)'
	@echo ''
	@echo 'DEBUGSERVER:       $(DEBUGSERVER)'
	@echo 'DEBUGSERVER_FLAGS: $(DEBUGSERVER_FLAGS)'
	@echo ''
	@echo 'RESET:       $(RESET)'
	@echo 'RESET_FLAGS: $(RESET_FLAGS)'
	@echo ''
	@echo -e 'MAKEFILE_LIST:$(patsubst %, \n\t%, $(abspath $(MAKEFILE_LIST)))'

info-boards-supported:
	@echo $(BOARDS)

info-features-missing:
	@echo $(filter-out $(FEATURES_PROVIDED), $(FEATURES_REQUIRED))

info-boards-features-missing:
	@for f in $(BOARDS_FEATURES_MISSING); do echo $${f}; done | column -t

FEATURES_REQUIRED += $(FEATURES_OPTIONAL)

ifneq (, $(filter info-boards-supported info-boards-features-missing info-build, $(MAKECMDGOALS)))
  FEATURES_PROVIDED_BAK := $(FEATURES_PROVIDED)

  define board_missing_features
    FEATURES_PROVIDED := $(FEATURES_PROVIDED_BAK)
    -include $${RIOTBOARD}/${1}/Makefile.features
    ifdef BUILDTEST_MCU_GROUP
      ifneq ($(BUILDTEST_MCU_GROUP), $$(FEATURES_MCU_GROUP))
        BOARDS_FEATURES_MISSING += "${1} $${BUILDTEST_MCU_GROUP}"
        BOARDS_WITH_MISSING_FEATURES += ${1}
      endif
    endif

    FEATURES_MISSING := $$(filter-out $$(FEATURES_PROVIDED), $$(FEATURES_REQUIRED))
    ifneq (, $${FEATURES_MISSING})
      BOARDS_FEATURES_MISSING += "${1} $${FEATURES_MISSING}"
      ifneq (, $$(filter-out $$(FEATURES_OPTIONAL), $$(FEATURES_MISSING)))
        BOARDS_WITH_MISSING_FEATURES += ${1}
      endif
    endif
  endef

  BOARDS ?= $(shell find $(RIOTBOARD)/* -maxdepth 0 -type d \! -name "*-common" -exec basename {} \;)
  BOARDS := $(filter $(if $(BOARD_WHITELIST), $(BOARD_WHITELIST), %), $(BOARDS))
  BOARDS := $(filter-out $(BOARD_BLACKLIST), $(BOARDS))

  BOARDS_WITH_MISSING_FEATURES :=
  BOARDS_FEATURES_MISSING :=
  $(foreach BOARD, $(BOARDS), $(eval $(call board_missing_features,$(BOARD))))
  BOARDS := $(filter-out $(BOARDS_WITH_MISSING_FEATURES), $(BOARDS))

  FEATURES_PROVIDED := $(FEATURES_PROVIDED_BAK)
endif

info-concurrency:
	@echo "$(NPROC)"

info-files: QUIET := 0
info-files:
	@( \
	  echo "$(abspath $(shell echo "$(MAKEFILE_LIST)"))" | tr ' ' '\n'; \
	  CSRC="$$($(MAKE) USEPKG="" -Bn | grep -o -e "[^ ]\+\.[csS]$$" -e "[^ ]\+\.[csS][ \']" | grep -v -e "^\s*-D")"; \
	  echo "$$CSRC"; \
	  echo "$(RIOTBASE)/Makefile.base"; \
	  echo "$$CSRC" | xargs dirname -- | sort | uniq | xargs -I{} find {} -name "Makefile*"; \
	  echo "$$CSRC" | xargs $(CC) $(CFLAGS) $(INCLUDES) -MM 2> /dev/null | grep -o "[^ ]\+\.h"; \
	  if [ -n "$$SRCXX" ]; then \
	    CPPSRC="$$($(MAKE) -Bn USEPKG="" | grep -o -e "[^ ]\+\.cpp" | grep -v -e "^\s*-D")"; \
	    echo "$$CPPSRC"; \
	    echo "$$CPPSRC" | xargs dirname -- | sort | uniq | xargs -I{} find {} -name "Makefile*"; \
	    echo "$$CPPSRC" | xargs $(CXX) $(CXXFLAGS) $(INCLUDES) -MM 2> /dev/null | grep -o "[^ ]\+\.h"; \
	  fi; \
	  $(foreach pkg,$(USEPKG),find $(RIOTPKG)/$(pkg) -type f;) \
	) | sort | uniq | sed 's#$(RIOTBASE)/##'