From 77a15e7886c978161fb1bf442cc5a82226571cd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Joakim=20Nohlg=C3=A5rd?= Date: Thu, 17 Mar 2016 13:05:15 +0100 Subject: [PATCH] make: Place most configuration macros in a separate file instead of on the command line --- Makefile.base | 4 +- Makefile.include | 35 +++++--- Makefile.modules | 6 +- dist/tools/genconfigheader/README.md | 14 ++++ dist/tools/genconfigheader/genconfigheader.sh | 84 +++++++++++++++++++ 5 files changed, 128 insertions(+), 15 deletions(-) create mode 100644 dist/tools/genconfigheader/README.md create mode 100755 dist/tools/genconfigheader/genconfigheader.sh diff --git a/Makefile.base b/Makefile.base index fd59c084d1..98f75964a3 100644 --- a/Makefile.base +++ b/Makefile.base @@ -56,13 +56,13 @@ CXXFLAGS = $(filter-out $(CXXUWFLAGS), $(CFLAGS)) $(CXXEXFLAGS) # compile and generate dependency info -$(OBJC): $(BINDIR)$(MODULE)/%.o: %.c +$(OBJC): $(BINDIR)$(MODULE)/%.o: %.c $(RIOTBUILD_CONFIG_HEADER_C) $(AD)$(CCACHE) $(CC) \ -DRIOT_FILE_RELATIVE=\"$(patsubst $(RIOTBASE)/%,%,$(abspath $<))\" \ -DRIOT_FILE_NOPATH=\"$(notdir $<)\" \ $(CFLAGS) $(INCLUDES) -MD -MP -c -o $@ $(abspath $<) -$(OBJCXX): $(BINDIR)$(MODULE)/%.o: %.cpp +$(OBJCXX): $(BINDIR)$(MODULE)/%.o: %.cpp $(RIOTBUILD_CONFIG_HEADER_C) $(AD)$(CCACHE) $(CXX) \ -DRIOT_FILE_RELATIVE=\"$(patsubst $(RIOTBASE)/%,%,$(abspath $<))\" \ -DRIOT_FILE_NOPATH=\"$(notdir $<)\" \ diff --git a/Makefile.include b/Makefile.include index 3ef25e8288..056dc8dea4 100644 --- a/Makefile.include +++ b/Makefile.include @@ -50,6 +50,8 @@ include $(RIOTBASE)/Makefile.docker # Static code analysis tools provided by LLVM include $(RIOTBASE)/Makefile.scan-build +export RIOTBUILD_CONFIG_HEADER_C = $(BINDIR)riotbuild/riotbuild.h + COLOR_GREEN := COLOR_RED := COLOR_PURPLE := @@ -226,12 +228,6 @@ ifeq ($(origin RIOT_VERSION), undefined) endif endif -ifneq (,$(RIOT_VERSION_OVERRIDE)) -export CFLAGS += -DRIOT_VERSION=\"$(RIOT_VERSION_OVERRIDE)\" -else -export CFLAGS += -DRIOT_VERSION=\"$(RIOT_VERSION)\" -endif - # the binaries to link BASELIBS += $(BINDIR)${APPLICATION}.a BASELIBS += $(USEPKG:%=${BINDIR}%.a) @@ -255,7 +251,7 @@ 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) +all: ..compiler-check ..build-message $(RIOTBUILD_CONFIG_HEADER_C) $(USEPKG:%=${BINDIR}%.a) $(APPDEPS) $(AD)DIRS="$(DIRS)" "$(MAKE)" -C $(APPDIR) -f $(RIOTBASE)/Makefile.application ifeq (,$(RIOTNOLINK)) ifeq ($(BUILDOSXNATIVE),1) @@ -286,7 +282,7 @@ include $(RIOTBASE)/drivers/Makefile.include # The `clean` needs to be serialized before everything else. ifneq (, $(filter clean, $(MAKECMDGOALS))) - all $(BASELIBS) $(USEPKG:%=$(RIOTPKG)/%/Makefile.include): clean + all $(BASELIBS) $(USEPKG:%=$(RIOTPKG)/%/Makefile.include) $(RIOTBUILD_CONFIG_HEADER_C): clean endif # include Makefile.includes for packages in $(USEPKG) @@ -301,7 +297,7 @@ USEMODULE_INCLUDES_ = $(shell echo $(USEMODULE_INCLUDES) | tr ' ' '\n' | awk '!a INCLUDES += $(USEMODULE_INCLUDES_:%=-I%) .PHONY: $(USEPKG:%=${BINDIR}%.a) -$(USEPKG:%=${BINDIR}%.a): +$(USEPKG:%=${BINDIR}%.a): $(RIOTBUILD_CONFIG_HEADER_C) @mkdir -p ${BINDIR} "$(MAKE)" -C $(RIOTPKG)/$(patsubst ${BINDIR}%.a,%,$@) @@ -380,7 +376,7 @@ eclipsesym: $(CURDIR)/eclipsesym.xml eclipsesym.xml: $(CURDIR)/eclipsesym.xml $(CURDIR)/eclipsesym.xml: - $(AD)printf "%s\n" $(CC) $(CFLAGS) $(INCLUDES) | \ + $(AD)printf "%s\n" $(CC) $(CFLAGS_WITH_MACROS) $(INCLUDES) | \ $(RIOTBASE)/dist/tools/eclipsesym/cmdline2xml.sh > $@ # Extra make goals for testing and comparing changes. @@ -495,3 +491,22 @@ include $(RIOTBASE)/dist/tools/desvirt/Makefile.desvirt # include bindist target include $(RIOTBASE)/Makefile.bindist + +# 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 $@)' + $(AD)'$(RIOTBASE)/dist/tools/genconfigheader/genconfigheader.sh' '$@' $(CFLAGS_WITH_MACROS) + +CFLAGS_WITH_MACROS := $(CFLAGS) +CFLAGS := $(patsubst -D%,,$(CFLAGS)) +CFLAGS := $(patsubst -U%,,$(CFLAGS)) +CFLAGS += -include '$(RIOTBUILD_CONFIG_HEADER_C)' + +ifneq (,$(RIOT_VERSION_OVERRIDE)) +export CFLAGS += -DRIOT_VERSION=\"$(RIOT_VERSION_OVERRIDE)\" +else +export CFLAGS += -DRIOT_VERSION=\"$(RIOT_VERSION)\" +endif diff --git a/Makefile.modules b/Makefile.modules index 37bef54fde..b6ec9d3428 100644 --- a/Makefile.modules +++ b/Makefile.modules @@ -6,9 +6,9 @@ USEMODULE := $(filter-out $(filter-out $(FEATURES_PROVIDED), $(FEATURES_OPTIONAL INCLUDES += -I$(RIOTBASE)/core/include -I$(RIOTBASE)/drivers/include -I$(RIOTBASE)/sys/include INCLUDES += -I$(RIOTCPU)/$(CPU)/include INCLUDES += -I$(RIOTBOARD)/$(BOARD)/include -ED = $(patsubst %,-DMODULE_%,$(subst -,_,$(USEMODULE) $(USEPKG))) -ED += $(patsubst %,-DFEATURE_%,$(subst -,_,$(filter $(FEATURES_PROVIDED), $(FEATURES_REQUIRED)))) -EXTDEFINES = $(shell echo $(sort $(ED))|tr 'a-z' 'A-Z') +ED = $(addprefix FEATURE_,$(sort $(filter $(FEATURES_PROVIDED), $(FEATURES_REQUIRED)))) +ED += $(addprefix MODULE_,$(sort $(USEMODULE) $(USEPKG))) +EXTDEFINES = $(addprefix -D,$(shell echo '$(ED)' | tr 'a-z-' 'A-Z_')) REALMODULES = $(filter-out $(PSEUDOMODULES), $(sort $(USEMODULE))) export BASELIBS += $(REALMODULES:%=$(BINDIR)%.a) diff --git a/dist/tools/genconfigheader/README.md b/dist/tools/genconfigheader/README.md new file mode 100644 index 0000000000..07321a007d --- /dev/null +++ b/dist/tools/genconfigheader/README.md @@ -0,0 +1,14 @@ +genconfigheader.sh +------------------ + +Usage: `genconfigheader.sh [CFLAGS]` + +Generate a build configuration header from CFLAGS arguments + + - Arguments on the form `-Dmacro_name=macro_value` will be converted to + the form `#define macro_name macro_value` + - Arguments given on the form `-Dmacro_name` will be converted to the form `#define macro_name 1` + - The output file will be overwritten if it already exists _and_ the new output file's contents differs from the old file. + +By not replacing the output file on every run, make can still use the file +modification times for dependency calculations. diff --git a/dist/tools/genconfigheader/genconfigheader.sh b/dist/tools/genconfigheader/genconfigheader.sh new file mode 100755 index 0000000000..901948c6af --- /dev/null +++ b/dist/tools/genconfigheader/genconfigheader.sh @@ -0,0 +1,84 @@ +#!/bin/sh + +# +# Copyright (C) 2016 Eistec AB +# +# This file is subject to the terms and conditions of the GNU Lesser General +# Public License v2.1. See the file LICENSE in the top level directory for more +# details. +# + +DEBUG=0 +if [ "${QUIET}" != "1" ]; then + DEBUG=1 +fi + +if [ $# -lt 1 ]; then + echo "Usage: $0 [CFLAGS]..." + echo "Extract all macros from CFLAGS and generate a header file" + exit 1 +fi +OUTPUTFILE="$1" +shift + +MD5SUM=md5sum +if [ "$(uname -s)" = "Darwin" ]; then + MD5SUM=md5 -r +fi + +# atomically update the file +TMPFILE= +trap '[ -n "${TMPFILE}" ] && rm -f "${TMPFILE}"' EXIT +# Create temporary output file +TMPFILE=$(mktemp ${OUTPUTFILE}.XXXXXX) + +if [ -z "${TMPFILE}" ]; then + echo "Error creating temporary file, aborting" + exit 1 +fi + +# exit on any errors below this line +set -e + +echo "/* DO NOT edit this file, your changes will be overwritten and won't take any effect! */" > "${TMPFILE}" +echo "/* Generated from CFLAGS: $@ */" >> "${TMPFILE}" +for arg in "$@"; do + case ${arg} in + -D*) + # Strip leading -D + d=${arg#-D} + if [ -z "${d##*=*}" ]; then + # key=value pairs + key=${d%%=*} + value=${d#*=} + echo "#define $key $value" >> "${TMPFILE}" + else + # simple #define + echo "#define $d 1" >> "${TMPFILE}" + fi + ;; + -U*) + # Strip leading -U + d=${arg#-U} + echo "#undef $d" >> "${TMPFILE}" + ;; + *) + continue + ;; + esac +done + +# Only replace old file if the new file differs. This allows make to check the +# date of the config header for dependency calculations. +NEWMD5=$(${MD5SUM} ${TMPFILE} | cut -c -32) +OLDMD5=$(${MD5SUM} ${OUTPUTFILE} 2>/dev/null | cut -c -32) +if [ "${NEWMD5}" != "${OLDMD5}" ]; then + if [ "${DEBUG}" -eq 1 ]; then echo "Replacing ${OUTPUTFILE} (${NEWMD5} != ${OLDMD5})"; fi + # Set mode according to umask + chmod +rw "${TMPFILE}" + mv -f "${TMPFILE}" "${OUTPUTFILE}" +else + if [ "${DEBUG}" -eq 1 ]; then echo "Keeping old ${OUTPUTFILE}"; fi +fi + +# $TMPFILE will be deleted by the EXIT trap above if it still exists when we exit