# include Makefile.local if it exists -include Makefile.local # set undefined variables RIOTBASE ?= $(dir $(lastword $(MAKEFILE_LIST))) CCACHE_BASEDIR ?= $(RIOTBASE) RIOTCPU ?= $(RIOTBASE)/cpu RIOTBOARD ?= $(RIOTBASE)/boards RIOTMAKE ?= $(RIOTBASE)/makefiles RIOTPKG ?= $(RIOTBASE)/pkg RIOTPROJECT ?= $(shell git rev-parse --show-toplevel 2>/dev/null || pwd) GITCACHE ?= $(RIOTBASE)/dist/tools/git/git-cache APPDIR ?= $(CURDIR) BINDIRBASE ?= $(APPDIR)/bin BINDIR ?= $(BINDIRBASE)/$(BOARD) PKGDIRBASE ?= $(BINDIRBASE)/pkg/$(BOARD) DLCACHE ?= $(RIOTBASE)/dist/tools/dlcache/dlcache.sh DLCACHE_DIR ?= $(RIOTBASE)/.dlcache __DIRECTORY_VARIABLES := \ RIOTBASE \ RIOTCPU \ RIOTBOARD \ RIOTMAKE \ RIOTPKG \ RIOTPROJECT \ APPDIR \ BINDIRBASE \ BINDIR \ CCACHE_BASEDIR \ GITCACHE \ PKGDIRBASE \ DLCACHE_DIR \ # # Make all paths absolute. override RIOTBASE := $(abspath $(RIOTBASE)) override CCACHE_BASEDIR := $(abspath $(CCACHE_BASEDIR)) override RIOTCPU := $(abspath $(RIOTCPU)) override RIOTBOARD := $(abspath $(RIOTBOARD)) override RIOTMAKE := $(abspath $(RIOTMAKE)) override RIOTPKG := $(abspath $(RIOTPKG)) override RIOTPROJECT := $(abspath $(RIOTPROJECT)) override GITCACHE := $(abspath $(GITCACHE)) override APPDIR := $(abspath $(APPDIR)) override BINDIRBASE := $(abspath $(BINDIRBASE)) override BINDIR := $(abspath $(BINDIR)) override PKGDIRBASE := $(abspath $(PKGDIRBASE)) override DLCACHE_DIR := $(abspath $(DLCACHE_DIR)) # Ensure that all directories are set and don't contain spaces. ifneq (, $(filter-out 1, $(foreach v,${__DIRECTORY_VARIABLES},$(words ${${v}})))) $(info Aborting compilation for your safety.) $(info Related variables = ${__DIRECTORY_VARIABLES}) $(error Make sure no path override is empty or contains spaces!) endif # Use absolute paths in recusive "make" even if overriden on command line. MAKEOVERRIDES += $(foreach v,${__DIRECTORY_VARIABLES},${v}=${${v}}) # Path to the current directory relative to RIOTPROJECT BUILDRELPATH ?= ${PWD:${RIOTPROJECT}/%=%}/ # get host operating system OS := $(shell uname) # Include Docker settings near the top because we need to build the environment # command line before some of the variable origins are overwritten below when # using abspath, strip etc. include $(RIOTMAKE)/docker.inc.mk # include color echo macros include $(RIOTMAKE)/color.inc.mk # include concurrency helpers include $(RIOTMAKE)/info-nproc.inc.mk GLOBAL_GOALS := buildtest info-boards-supported info-boards-features-missing info-buildsizes info-buildsizes-diff ifneq (, $(filter $(GLOBAL_GOALS), $(MAKECMDGOALS))) BOARD=none endif ifeq (none,$(BOARD)) include $(RIOTMAKE)/info-global.inc.mk include $(RIOTMAKE)/buildtests.inc.mk else all: link include $(RIOTMAKE)/info.inc.mk # Static code analysis tools provided by LLVM include $(RIOTMAKE)/scan-build.inc.mk export RIOTBUILD_CONFIG_HEADER_C = $(BINDIR)/riotbuild/riotbuild.h ifeq ($(OS),Darwin) OPEN := open else OPEN := xdg-open endif QUIET ?= 1 ifeq ($(QUIET),1) Q=@ MAKEFLAGS += --no-print-directory else Q= endif QQ= # Fail on warnings. Can be overridden by `make WERROR=0`. WERROR ?= 1 export WERROR ifeq ($(WERROR),1) CFLAGS += -Werror endif ifneq (10,$(if ${RIOT_VERSION},1,0)$(if ${__RIOTBUILD_FLAG},1,0)) # Provide a shallow sanity check. You cannot call `make` in a module directory. export __RIOTBUILD_FLAG := RIOT BOARD := $(strip $(BOARD)) APPLICATION := $(strip $(APPLICATION)) # provide common external programs for `Makefile.include`s ifeq (,$(and $(DOWNLOAD_TO_STDOUT),$(DOWNLOAD_TO_FILE))) ifeq (,$(WGET)) ifeq (0,$(shell which wget 2>&1 > /dev/null ; echo $$?)) WGET := $(shell which wget) endif endif ifeq (,$(CURL)) ifeq (0,$(shell which curl 2>&1 > /dev/null ; echo $$?)) CURL := $(shell which curl) endif endif ifeq (,$(WGET)$(CURL)) $(error Neither wget nor curl is installed!) endif ifeq (,$(DOWNLOAD_TO_STDOUT)) DOWNLOAD_TO_STDOUT := $(if $(CURL),$(CURL) -s,$(WGET) -q -O-) endif ifeq (,$(DOWNLOAD_TO_FILE)) DOWNLOAD_TO_FILE := $(if $(WGET),$(WGET) -nv -c -O,$(CURL) -s -o) endif endif ifeq (,$(UNZIP_HERE)) ifeq (0,$(shell which unzip 2>&1 > /dev/null ; echo $$?)) UNZIP_HERE := $(shell which unzip) -q else ifeq (0,$(shell which 7z 2>&1 > /dev/null ; echo $$?)) UNZIP_HERE := $(shell which 7z) x -bd else $(error Neither unzip nor 7z is installed.) endif endif endif ifeq (, ${APPLICATION}) $(error An application name must be specified as APPLICATION.) endif ifneq (0,$(shell test -d $(RIOTBOARD)/$(BOARD); echo $$?)) $(error The specified board $(BOARD) does not exist.) endif # Use TOOLCHAIN environment variable to select the toolchain to use. # Default for macOS: llvm; for other OS: gnu ifeq ($(BOARD),native) ifeq ($(OS),Darwin) TOOLCHAIN ?= llvm endif endif TOOLCHAIN ?= gnu # TOOLCHAIN = clang is an alias for TOOLCHAIN = llvm ifeq (clang,$(TOOLCHAIN)) # use override so that we can redefine a variable set on the command line (as # opposed to one set in the environment) override TOOLCHAIN := llvm endif # TOOLCHAIN = gcc is an alias for TOOLCHAIN = gnu ifeq (gcc,$(TOOLCHAIN)) # use override so that we can redefine a variable set on the command line (as # opposed to one set in the environment) override TOOLCHAIN := gnu endif ifeq (,$(TOOLCHAIN)) override TOOLCHAIN := gnu endif export TOOLCHAIN # default toolchain prefix, defaults to target triple followed by a dash, you # will most likely not need to touch this. export PREFIX ?= $(if $(TARGET_ARCH),$(TARGET_ARCH)-) # Add standard include directories INCLUDES += -I$(RIOTBASE)/core/include -I$(RIOTBASE)/drivers/include -I$(RIOTBASE)/sys/include INCLUDES += -I$(RIOTCPU)/$(CPU)/include INCLUDES += -I$(RIOTBOARD)/$(BOARD)/include # mandatory includes! include $(RIOTMAKE)/pseudomodules.inc.mk include $(RIOTMAKE)/defaultmodules.inc.mk include $(RIOTBOARD)/$(BOARD)/Makefile.include include $(RIOTCPU)/$(CPU)/Makefile.include # Import all toolchain settings include $(RIOTMAKE)/toolchain/$(TOOLCHAIN).inc.mk # get number of interfaces straight before resolving dependencies GNRC_NETIF_NUMOF ?= 1 ifneq ($(GNRC_NETIF_NUMOF),1) CFLAGS += -DGNRC_NETIF_NUMOF=$(GNRC_NETIF_NUMOF) endif # process provided features include $(RIOTMAKE)/features.inc.mk # process dependencies include $(RIOTBASE)/Makefile.dep USEMODULE += $(filter-out $(DISABLE_MODULE), $(DEFAULT_MODULE)) ifeq ($(strip $(MCU)),) MCU = $(CPU) endif # set some settings useful for continuous integration builds ifeq ($(RIOT_CI_BUILD),1) RIOT_VERSION_OVERRIDE:=buildtest ifneq ($(filter $(BOARD_INSUFFICIENT_MEMORY), $(BOARD)),) $(info CI-build: skipping link step) RIOTNOLINK:=1 endif # be more quiet when building for CI QQ:=@ endif # if you want to publish the board into the sources as an uppercase #define BOARDDEF := $(shell echo $(BOARD) | tr 'a-z' 'A-Z' | tr '-' '_') CPUDEF := $(shell echo $(CPU) | tr 'a-z' 'A-Z' | tr '-' '_') MCUDEF := $(shell echo $(MCU) | tr 'a-z' 'A-Z' | tr '-' '_') CFLAGS += -DBOARD_$(BOARDDEF)=\"$(BOARD)\" -DRIOT_BOARD=BOARD_$(BOARDDEF) CFLAGS += -DCPU_$(CPUDEF)=\"$(CPU)\" -DRIOT_CPU=CPU_$(CPUDEF) CFLAGS += -DMCU_$(MCUDEF)=\"$(MCU)\" -DRIOT_MCU=MCU_$(MCUDEF) # OSX fails to create empty archives. Provide a wrapper to catch that error. ifneq (0, $(shell mkdir -p $(BINDIR); $(AR) rc $(BINDIR)/empty-archive.a 2> /dev/null; \ echo $$?; rm -f $(BINDIR)/empty-archive.a 2>&1 > /dev/null)) AR := $(RIOTBASE)/dist/ar-wrapper $(AR) endif # Feature test default CFLAGS and LINKFLAGS for the set compiled. include $(RIOTMAKE)/cflags.inc.mk # make the RIOT version available to the program ifeq ($(origin RIOT_VERSION), undefined) GIT_STRING := $(shell git --git-dir="$(RIOTBASE)/.git" describe --always --abbrev=4 --dirty=-`hostname` 2> /dev/null) ifneq (,$(GIT_STRING)) GIT_BRANCH := $(shell git --git-dir="$(RIOTBASE)/.git" rev-parse --abbrev-ref HEAD) ifeq ($(strip $(GIT_BRANCH)),master) RIOT_VERSION := $(GIT_STRING) else RIOT_VERSION := $(GIT_STRING)-$(GIT_BRANCH) endif else RIOT_VERSION := 'UNKNOWN (builddir: $(RIOTBASE))' endif endif # the binaries to link BASELIBS += $(BINDIR)/${APPLICATION}.a BASELIBS += $(APPDEPS) .PHONY: all link clean flash term doc debug debug-server reset objdump help info-modules .PHONY: ..in-docker-container ELFFILE ?= $(BINDIR)/$(APPLICATION).elf HEXFILE ?= $(ELFFILE:.elf=.hex) # variables used to compile and link c++ CPPMIX ?= $(if $(wildcard *.cpp),1,) # We assume $(LINK) to be gcc-like. Use `LINKFLAGPREFIX :=` for ld-like linker options. LINKFLAGPREFIX ?= -Wl, DIRS += $(EXTERNAL_MODULE_DIRS) _LINK = $(if $(CPPMIX),$(CXX),$(LINK)) $(UNDEF) $(LINKFLAGPREFIX)--start-group $(BASELIBS) -lm $(LINKFLAGPREFIX)--end-group $(LINKFLAGPREFIX)-Map=$(BINDIR)/$(APPLICATION).map $(LINKFLAGPREFIX)--cref $(LINKFLAGS) ifeq ($(BUILD_IN_DOCKER),1) link: ..in-docker-container else ## make script for your application. Build RIOT-base here! link: ..compiler-check ..build-message $(RIOTBUILD_CONFIG_HEADER_C) $(USEPKG:%=${BINDIR}/%.a) $(APPDEPS) $(Q)DIRS="$(DIRS)" "$(MAKE)" -C $(APPDIR) -f $(RIOTMAKE)/application.inc.mk ifeq (,$(RIOTNOLINK)) ifeq ($(BUILDOSXNATIVE),1) $(Q)$(if $(CPPMIX),$(CXX),$(LINK)) $(UNDEF) -o $(ELFFILE) $$(find $(BASELIBS) -size +8c) $(LINKFLAGS) $(LINKFLAGPREFIX)-no_pie else $(Q)$(_LINK) -o $(ELFFILE) endif $(Q)$(SIZE) $(ELFFILE) $(Q)$(OBJCOPY) $(OFLAGS) $(ELFFILE) $(HEXFILE) endif endif # BUILD_IN_DOCKER ..compiler-check: @command -v $(CC) >/dev/null 2>&1 || \ { $(COLOR_ECHO) \ '${COLOR_RED}Compiler $(CC) is required but not found in PATH. Aborting.${COLOR_RESET}'; \ exit 1; } ..build-message: @$(COLOR_ECHO) '${COLOR_GREEN}Building application "$(APPLICATION)" for "$(BOARD)" with MCU "$(MCU)".${COLOR_RESET}' @$(COLOR_ECHO) # add extra include paths for packages in $(USEMODULE) export USEMODULE_INCLUDES = include $(RIOTBASE)/sys/Makefile.include include $(RIOTBASE)/drivers/Makefile.include # The `clean` needs to be serialized before everything else. ifneq (, $(filter clean, $(MAKECMDGOALS))) all $(BASELIBS) $(USEPKG:%=$(RIOTPKG)/%/Makefile.include) $(RIOTBUILD_CONFIG_HEADER_C) pkg-prepare: clean endif # include Makefile.includes for packages in $(USEPKG) $(RIOTPKG)/%/Makefile.include:: $(Q)"$(MAKE)" -C $(RIOTPKG)/$* Makefile.include .PHONY: $(USEPKG:%=$(RIOTPKG)/%/Makefile.include) -include $(USEPKG:%=$(RIOTPKG)/%/Makefile.include) USEMODULE_INCLUDES_ = $(shell echo $(USEMODULE_INCLUDES) | tr ' ' '\n' | awk '!a[$$0]++' | tr '\n' ' ') INCLUDES += $(USEMODULE_INCLUDES_:%=-I%) .PHONY: pkg-prepare $(USEPKG:%=${BINDIR}/%.a) pkg-prepare: -@for i in $(USEPKG) ; do "$(MAKE)" -C $(RIOTPKG)/$$i prepare ; done $(USEPKG:%=${BINDIR}/%.a): $(RIOTBUILD_CONFIG_HEADER_C) pkg-prepare @mkdir -p ${BINDIR} $(QQ)"$(MAKE)" -C $(RIOTPKG)/$(patsubst ${BINDIR}/%.a,%,$@) clean: -@for i in $(USEPKG) ; do "$(MAKE)" -C $(RIOTPKG)/$$i clean ; done -@rm -rf $(BINDIR) -@rm -rf $(SCANBUILD_OUTPUTDIR) # Remove intermediates, but keep the .elf, .hex and .map etc. clean-intermediates: -@for i in $(USEPKG) ; do "$(MAKE)" -C $(RIOTPKG)/$$i distclean ; done -@rm -rf $(BINDIR)/*.a $(BINDIR)/*/ clean-pkg: -@for i in $(USEPKG) ; do "$(MAKE)" -C $(RIOTPKG)/$$i distclean ; done distclean: -@for i in $(USEPKG) ; do "$(MAKE)" -C $(RIOTPKG)/$$i distclean ; done -@rm -rf $(BINDIRBASE) flash: all $(FLASHDEPS) @command -v $(FLASHER) >/dev/null 2>&1 || \ { $(COLOR_ECHO) \ '${COLOR_RED}Flash program $(FLASHER) not found. Aborting.${COLOR_RESET}'; \ exit 1; } $(FLASHER) $(FFLAGS) preflash: all $(PREFLASHER) $(PREFFLAGS) term: $(filter flash, $(MAKECMDGOALS)) $(TERMDEPS) @command -v $(TERMPROG) >/dev/null 2>&1 || \ { $(COLOR_ECHO) \ '${COLOR_RED}Terminal program $(TERMPROG) not found. Aborting.${COLOR_RESET}'; \ exit 1; } $(TERMPROG) $(TERMFLAGS) list-ttys: $(Q)$(RIOTBASE)/dist/tools/usb-serial/list-ttys.sh doc: make -BC $(RIOTBASE) doc debug: @command -v $(DEBUGGER) >/dev/null 2>&1 || \ { $(COLOR_ECHO) \ '${COLOR_RED}Debug program $(DEBUGGER) not found. Aborting.${COLOR_RESET}'; \ exit 1; } $(DEBUGGER) $(DEBUGGER_FLAGS) debug-server: @command -v $(DEBUGSERVER) >/dev/null 2>&1 || \ { $(COLOR_ECHO) \ '${COLOR_RED}Debug server program $(DEBUGSERVER) not found. Aborting.${COLOR_RESET}'; \ exit 1; } $(DEBUGSERVER) $(DEBUGSERVER_FLAGS) reset: @command -v $(RESET) >/dev/null 2>&1 || \ { $(COLOR_ECHO) \ '${COLOR_RED}Reset program $(RESET) not found. Aborting.${COLOR_RESET}'; \ exit 1; } $(RESET) $(RESET_FLAGS) # Default OBJDUMPFLAGS for platforms which do not specify it: OBJDUMPFLAGS ?= -S -D -h objdump: @command -v $(OBJDUMP) >/dev/null 2>&1 || \ { $(COLOR_ECHO) \ '${COLOR_RED}Objdump program $(OBJDUMP) not found. Aborting.${COLOR_RESET}'; \ exit 1; } $(OBJDUMP) $(OBJDUMPFLAGS) $(ELFFILE) | less # Generate an XML file containing all macro definitions and include paths for # use in Eclipse CDT .PHONY: eclipsesym eclipsesym.xml $(CURDIR)/eclipsesym.xml eclipsesym: $(CURDIR)/eclipsesym.xml eclipsesym.xml: $(CURDIR)/eclipsesym.xml $(CURDIR)/eclipsesym.xml: $(Q)printf "%s\n" $(CC) $(CFLAGS_WITH_MACROS) $(INCLUDES) | \ $(RIOTBASE)/dist/tools/eclipsesym/cmdline2xml.sh > $@ # Export variables used throughout the whole make system: include $(RIOTMAKE)/vars.inc.mk # Include build targets for selected tools after the default RIOT targets have # been defined (-> so the `all` will be always the first target) include $(RIOTMAKE)/tools/targets.inc.mk # Warn if the selected board and drivers don't provide all needed features: ifneq (, $(filter all, $(if $(MAKECMDGOALS), $(MAKECMDGOALS), all))) EXPECT_ERRORS := EXPECT_CONFLICT := # Test if there where dependencies against a module in DISABLE_MODULE. ifneq (, $(filter $(DISABLE_MODULE), $(USEMODULE))) $(shell $(COLOR_ECHO) "$(COLOR_RED)Required modules were disabled using DISABLE_MODULE:$(COLOR_RESET)"\ "$(sort $(filter $(DISABLE_MODULE), $(USEMODULE)))" 1>&2) USEMODULE := $(filter-out $(DISABLE_MODULE), $(USEMODULE)) EXPECT_ERRORS := 1 endif # Test if all feature requirements were met by the selected board. ifneq (, $(filter-out $(FEATURES_PROVIDED) $(FEATURES_OPTIONAL), $(FEATURES_REQUIRED))) $(shell $(COLOR_ECHO) "$(COLOR_RED)There are unsatisfied feature requirements:$(COLOR_RESET)"\ "$(sort $(filter-out $(FEATURES_PROVIDED) $(FEATURES_OPTIONAL), $(FEATURES_REQUIRED)))" 1>&2) EXPECT_ERRORS := 1 endif # Test if any required feature conflict with another one. CONFLICT := $(foreach var,$(FEATURES_CONFLICT),$(if $(filter $(words $(subst :, ,$(var))),$(words $(filter $(FEATURES_REQUIRED),$(subst :, ,$(var))))),$(subst :, ,$(var)))) ifneq (, $(strip $(CONFLICT))) $(shell $(COLOR_ECHO) "$(COLOR_YELLOW)The following features may conflict:$(COLOR_RESET)"\ "$(COLOR_GREEN)$(sort $(filter $(FEATURES_REQUIRED), $(CONFLICT)))$(COLOR_RESET)" 1>&2) ifneq (, $(FEATURES_CONFLICT_MSG)) $(shell $(COLOR_ECHO) "$(COLOR_YELLOW)Rationale: $(COLOR_RESET)$(FEATURES_CONFLICT_MSG)" 1>&2) endif EXPECT_CONFLICT := 1 endif # If there is a whitelist, then test if the board is whitelisted. ifneq (, $(BOARD_WHITELIST)) ifeq (, $(filter $(BOARD_WHITELIST), $(BOARD))) $(shell $(COLOR_ECHO) "$(COLOR_RED)The selected BOARD=${BOARD} is not whitelisted:$(COLOR_RESET) ${BOARD_WHITELIST}" 1>&2) EXPECT_ERRORS := 1 endif endif # If there is a blacklist, then test if the board is blacklisted. ifneq (, $(BOARD_BLACKLIST)) ifneq (, $(filter $(BOARD_BLACKLIST), $(BOARD))) $(shell $(COLOR_ECHO) "$(COLOR_RED)The selected BOARD=${BOARD} is blacklisted:$(COLOR_RESET) ${BOARD_BLACKLIST}" 1>&2) EXPECT_ERRORS := 1 endif endif ifneq (, $(EXPECT_CONFLICT)) $(shell $(COLOR_ECHO) "\n$(COLOR_YELLOW)EXPECT undesired behaviour!$(COLOR_RESET)" 1>&2) endif ifneq (, $(EXPECT_ERRORS)) $(shell $(COLOR_ECHO) "\n\n$(COLOR_RED)EXPECT ERRORS!$(COLOR_RESET)\n\n" 1>&2) endif endif else # RIOT_VERSION export __RIOTBUILD_FLAG := RIOT NUM_RIOT_VERSION := $(shell cd $(RIOTBASE) && git rev-parse --verify --short "$(RIOT_VERSION)" 2>/dev/null) ifeq (, ${NUM_RIOT_VERSION}) $(error The supplied RIOT_VERSION=$(RIOT_VERSION) is invalid!) endif all $(filter-out clean, ${MAKECMDGOALS}): ..delegate ifneq (, $(filter clean, $(MAKECMDGOALS))) all $(filter-out clean, ${MAKECMDGOALS}): clean endif clean: -$(Q)rm -rf $(BINDIR) $(BINDIR)/riot-version/$(NUM_RIOT_VERSION)/Makefile.include: $(Q)rm -rf $(@D) $(Q)mkdir -p $(@D) $(Q)cd $(RIOTBASE) && git archive --format=tar $(NUM_RIOT_VERSION) | ( cd $(@D) && tar x 1>&2 ) ..delegate: $(BINDIR)/riot-version/$(NUM_RIOT_VERSION)/Makefile.include @$(COLOR_ECHO) '$(COLOR_GREEN)Using RIOT_VERSION=${NUM_RIOT_VERSION}$(COLOR_RESET)' 1>&2 @$(COLOR_ECHO) $(MAKE) RIOTBASE=$(