From 8db628b17c36129b4f83f23294ae26dae02d0b2f Mon Sep 17 00:00:00 2001 From: Joakim Gebart Date: Thu, 5 Feb 2015 10:03:05 +0100 Subject: [PATCH] Makefile.include: Add docker target. export BUILD_IN_DOCKER=1 to use Docker for building inside a Docker container. GDB debug file paths will be wrong after building inside the container, use the script provided in `dist/gdbinit-docker` to set the correct GDB substitution paths (copy and paste the contents into your `~/.gdbinit`) The environment variable DOCKER_FLAGS can be used to pass extra parameters to the Docker process. --- Makefile.include | 41 +++++++++++++++++++++++++++++++++++++++++ Makefile.vars | 1 + dist/gdbinit-docker | 36 ++++++++++++++++++++++++++++++++++++ 3 files changed, 78 insertions(+) create mode 100644 dist/gdbinit-docker diff --git a/Makefile.include b/Makefile.include index 951b6e96bc..7235312eb3 100644 --- a/Makefile.include +++ b/Makefile.include @@ -10,6 +10,12 @@ RIOTCPU := $(abspath $(RIOTCPU)) RIOTBOARD ?= $(RIOTBASE)/boards RIOTBOARD := $(abspath $(RIOTBOARD)) +RIOTPROJECT ?= $(shell git rev-parse --show-toplevel 2>/dev/null || pwd) +RIOTPROJECT := $(abspath $(RIOTPROJECT)) + +# Path to the current directory relative to the git root +BUILDRELPATH ?= $(shell git rev-parse --show-prefix) + BINDIRBASE ?= $(CURDIR)/bin BINDIRBASE := $(abspath $(BINDIRBASE)) @@ -145,6 +151,7 @@ BASELIBS += $(BINDIR)${APPLICATION}.a BASELIBS += $(USEPKG:%=${BINDIR}%.a) .PHONY: all clean flash term doc debug debug-server reset objdump help +.PHONY: ..in-docker-container ELFFILE ?= $(BINDIR)$(APPLICATION).elf HEXFILE ?= $(ELFFILE:.elf=.hex) @@ -157,6 +164,9 @@ LINKFLAGPREFIX ?= -Wl, DIRS += $(EXTERNAL_MODULE_DIRS) +ifeq ($(BUILD_IN_DOCKER),1) +all: ..in-docker-container +else ## make script for your application. Build RIOT-base here! all: ..compiler-check ..build-message $(USEPKG:%=${BINDIR}%.a) $(APPDEPS) $(AD)DIRS="$(DIRS)" "$(MAKE)" -C $(CURDIR) -f $(RIOTBASE)/Makefile.application @@ -169,6 +179,7 @@ endif $(AD)$(SIZE) $(ELFFILE) $(AD)$(OBJCOPY) $(OFLAGS) $(ELFFILE) $(HEXFILE) endif +endif # BUILD_IN_DOCKER ..compiler-check: $(AD)command -v $(CC) >/dev/null 2>&1 || \ @@ -260,6 +271,36 @@ objdump: exit 1; } $(PREFIX)objdump -S -D -h $(ELFFILE) | less +export DOCKER_IMAGE ?= riot/riotbuild:latest +export DOCKER_BUILD_ROOT ?= /data/riotbuild +export DOCKER_FLAGS ?= --rm +# Default target for building inside a Docker container +export DOCKER_MAKECMDGOALS ?= all +# This will execute `make $(DOCKER_MAKECMDGOALS)` inside a Docker container. +# We do not push the regular $(MAKECMDGOALS) to the container's make command in +# order to only perform building inside the container and defer executing any +# extra commands such as flashing or debugging until after leaving the +# container. +# The `flash`, `term`, `debugserver` etc. targets usually require access to +# hardware which may not be reachable from inside the container. +..in-docker-container: + @$(COLOR_ECHO) '${COLOR_GREEN}Launching build container using image "$(DOCKER_IMAGE)".${COLOR_RESET}' + docker run $(DOCKER_FLAGS) -i -t -u "$$(id -u)" \ + -v '$(RIOTBASE):$(DOCKER_BUILD_ROOT)/riotbase' \ + -v '$(RIOTCPU):$(DOCKER_BUILD_ROOT)/riotcpu' \ + -v '$(RIOTBOARD):$(DOCKER_BUILD_ROOT)/riotboard' \ + -v '$(RIOTPROJECT):$(DOCKER_BUILD_ROOT)/riotproject' \ + -e 'RIOTBASE=$(DOCKER_BUILD_ROOT)/riotbase' \ + -e 'RIOTCPU=$(DOCKER_BUILD_ROOT)/riotcpu' \ + -e 'RIOTBOARD=$(DOCKER_BUILD_ROOT)/riotboard' \ + -e 'RIOTPROJECT=$(DOCKER_BUILD_ROOT)/riotproject' \ + -e 'BOARD=$(BOARD)' \ + -e 'RIOT_VERSION=$(RIOT_VERSION)' \ + -e '__RIOTBUILD_FLAG=$(__RIOTBUILD_FLAG)' \ + -e 'QUIET=$(QUIET)' \ + -w '$(DOCKER_BUILD_ROOT)/riotproject/$(BUILDRELPATH)' \ + '$(DOCKER_IMAGE)' make $(DOCKER_MAKECMDGOALS) + # Extra make goals for testing and comparing changes. include $(RIOTBASE)/Makefile.buildtests diff --git a/Makefile.vars b/Makefile.vars index 7896e67a0a..ab69f06e77 100644 --- a/Makefile.vars +++ b/Makefile.vars @@ -16,6 +16,7 @@ export APPDEPS # Files / Makefile targets that need to be created export RIOTBASE # The root folder of RIOT. The folder where this very file lives in. export RIOTCPU # For third party CPUs this folder is the base of the CPUs. export RIOTBOARD # For third party BOARDs this folder is the base of the BOARDs. +export RIOTPROJECT # Top level git root of the project being built, or PWD if not a git repository export BINDIRBASE # This is the folder where the application should be built in. For each BOARD a different subfolder is used. export BINDIR # This is the folder where the application should be built in. diff --git a/dist/gdbinit-docker b/dist/gdbinit-docker new file mode 100644 index 0000000000..a3e4f1b39c --- /dev/null +++ b/dist/gdbinit-docker @@ -0,0 +1,36 @@ +# Set some path substitution rules to be able to list source code while +# debugging after the build was run inside a Docker container +# These are harmless as they only apply to filenames beginning with /data/riotbuild/ +python +import os +try: + path = os.environ['RIOTBASE'] +except KeyError: + # Environment variable wasn't set. + pass +else: + gdb.execute('set substitute-path /data/riotbuild/riotbase ' + path) +try: + path = os.environ['RIOTCPU'] +except KeyError: + # Environment variable wasn't set. + pass +else: + gdb.execute('set substitute-path /data/riotbuild/riotcpu ' + path) +try: + path = os.environ['RIOTBOARD'] +except KeyError: + # Environment variable wasn't set. + pass +else: + gdb.execute('set substitute-path /data/riotbuild/riotboard ' + path) +try: + path = os.environ['RIOTPROJECT'] +except KeyError: + # Environment variable wasn't set. + pass +else: + gdb.execute('set substitute-path /data/riotbuild/riotproject ' + path) +end + +show substitute-path