Blame view

RIOT/Makefile.include 18.1 KB
a752c7ab   elopes   add first test an...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
  # 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=$(<D) $(filter-out clean, ${MAKECMDGOALS})
  
  endif
  
  help:
  	@$(MAKE) -qp | sed -ne 's/\(^[a-z][a-z_-]*\):.*/\1/p' | sort | uniq
  
  ifneq (,$(filter iotlab-m3 wsn430-v1_3b wsn430-v1_4,$(BOARD)))
    ifneq (,$(filter iotlab-%,$(MAKECMDGOALS)))
      include $(RIOTBASE)/dist/testbed-support/Makefile.iotlab
    endif
  endif
  
  # Include desvirt Makefile
  include $(RIOTBASE)/dist/tools/desvirt/Makefile.desvirt
  
  # include bindist target
  include $(RIOTMAKE)/bindist.inc.mk
  
  # Add all USEMODULE modules to CFLAGS
  include $(RIOTMAKE)/modules.inc.mk
  
  # Build a header file with all common macro definitions and undefinitions
  # make it phony to force re-run of the script every time even if the file exists
  # The script will only touch the file if anything has changed since last time.
  .PHONY: $(RIOTBUILD_CONFIG_HEADER_C)
  $(RIOTBUILD_CONFIG_HEADER_C):
  	@mkdir -p '$(dir $@)'
  	$(Q)'$(RIOTBASE)/dist/tools/genconfigheader/genconfigheader.sh' '$@' $(CFLAGS_WITH_MACROS)
  
  CFLAGS_WITH_MACROS := $(CFLAGS)
  
  ifneq (,$(RIOT_VERSION_OVERRIDE))
  export CFLAGS_WITH_MACROS += -DRIOT_VERSION=\"$(RIOT_VERSION_OVERRIDE)\"
  else
  export CFLAGS_WITH_MACROS += -DRIOT_VERSION=\"$(RIOT_VERSION)\"
  endif
  
  CFLAGS := $(patsubst -D%,,$(CFLAGS))
  CFLAGS := $(patsubst -U%,,$(CFLAGS))
  CFLAGS += -include '$(RIOTBUILD_CONFIG_HEADER_C)'
  
  # include multislot support
  include $(RIOTMAKE)/multislot.mk
  endif # BOARD=none