[U-Boot] [PATCH v5 06/15] kconfig: switch to Kconfig

Masahiro Yamada yamada.m at jp.panasonic.com
Thu Jul 24 06:00:13 CEST 2014


This commit enables Kconfig.
Going forward, we use Kconfig for the board configuration.
mkconfig will never be used. Nor will include/config.mk be generated.

Kconfig must be adjusted for U-Boot because our situation is
a little more complicated than Linux Kernel.
We have to generate multiple boot images (Normal, SPL, TPL)
from one source tree.
Each image needs its own configuration input.

Usage:

Run "make <board>_defconfig" to do the board configuration.

It will create .config file and additionally spl/.config, tpl/.config
if SPL, TPL is enabled respectively.

You can use "make config", "make menuconfig" etc. to create
a new .config or modify the existing one.

Use "make spl:config", "make spl:menuconfig" etc. for spl/.config
and do likewise for tpl/.config file.

The generic syntax of configuration targets for SPL, TPL is:

  <target_image>:<config_command>

When the configuration is done, run "make".
(Or "make <board>_defconfig all" will do the configuration and build
in one time.)

For futher information of how Kconfig in U-Boot works,
please read the comment block of scripts/multiconfig.py.

By the way, there is another item worth remarking here:
coexistence of Kconfig and board herder files.

Prior to Kconfig, we used C headers to define a set of configs.

We expect a very long term to migrate from C headers to Kconfig.
Two different infractructure must coexist in the interim.

In our former configuration scheme, include/autoconf.mk was generated
for use in makefiles.
It is still generated under include/, spl/include/, tpl/include/ directory
for the Normal, SPL, TPL image, respectively.

Signed-off-by: Masahiro Yamada <yamada.m at jp.panasonic.com>
---

Changes in v5:
  - Rebase on commit fbe79a17fd

Changes in v4:
  - Have one defconfig file for each board by supporting conditional
    definition in defconfig
  - Put adjustment code into scripts/multiconfig.py

Changes in v3:
  - Invoke SPL/TPL configuration only for defconfig and silentoldconfig

Changes in v2:
  - Put dirty build rule into scripts/multiple_config.sh and
    scripts/Makefile.autoconf
  - Fix dependency tracking.
    In v1, any change to Kconfig triggered re-complile of all objects.
    In this version, re-compile is kept at a minimum.
  - Fix a clean-source check
    In v1, clean source tree check did not work correctly for
    out-of-tree build.

 .gitignore                        |   2 -
 Makefile                          | 116 +++++------
 arch/m68k/cpu/mcf52x2/config.mk   |  16 +-
 arch/m68k/cpu/mcf532x/config.mk   |   6 +-
 arch/m68k/cpu/mcf5445x/config.mk  |   4 +-
 arch/powerpc/cpu/ppc4xx/config.mk |   4 +-
 config.mk                         |  10 +
 include/.gitignore                |   1 -
 scripts/Makefile                  |   2 +-
 scripts/Makefile.autoconf         | 100 ++++++++++
 scripts/Makefile.build            |  31 ++-
 scripts/Makefile.spl              |  31 +--
 scripts/basic/fixdep.c            |   6 +-
 scripts/kconfig/confdata.c        |   8 +
 scripts/multiconfig.py            | 406 ++++++++++++++++++++++++++++++++++++++
 tools/Makefile                    |   2 +-
 tools/env/Makefile                |   2 +-
 17 files changed, 615 insertions(+), 132 deletions(-)
 create mode 100644 scripts/Makefile.autoconf
 create mode 100755 scripts/multiconfig.py

diff --git a/.gitignore b/.gitignore
index 0ace33b..5ac2e60 100644
--- a/.gitignore
+++ b/.gitignore
@@ -53,8 +53,6 @@
 #
 /include/config/
 /include/generated/
-/include/spl-autoconf.mk
-/include/tpl-autoconf.mk
 
 # stgit generated dirs
 patches-*
diff --git a/Makefile b/Makefile
index ca212b5..c4d894f 100644
--- a/Makefile
+++ b/Makefile
@@ -166,9 +166,6 @@ VPATH		:= $(srctree)$(if $(KBUILD_EXTMOD),:$(KBUILD_EXTMOD))
 
 export srctree objtree VPATH
 
-MKCONFIG	:= $(srctree)/mkconfig
-export MKCONFIG
-
 # Make sure CDPATH settings don't interfere
 unexport CDPATH
 
@@ -189,9 +186,6 @@ HOSTOS := $(shell uname -s | tr '[:upper:]' '[:lower:]' | \
 
 export	HOSTARCH HOSTOS
 
-# Deal with colliding definitions from tcsh etc.
-VENDOR=
-
 #########################################################################
 
 # set default to nothing for native builds
@@ -199,6 +193,9 @@ ifeq ($(HOSTARCH),$(ARCH))
 CROSS_COMPILE ?=
 endif
 
+KCONFIG_CONFIG	?= .config
+export KCONFIG_CONFIG
+
 # SHELL used by kbuild
 CONFIG_SHELL := $(shell if [ -x "$$BASH" ]; then echo $$BASH; \
 	  else if [ -x /bin/bash ]; then echo /bin/bash; \
@@ -341,6 +338,7 @@ OBJCOPY		= $(CROSS_COMPILE)objcopy
 OBJDUMP		= $(CROSS_COMPILE)objdump
 AWK		= awk
 PERL		= perl
+PYTHON		= python
 DTC		= dtc
 CHECK		= sparse
 
@@ -362,7 +360,7 @@ export VERSION PATCHLEVEL SUBLEVEL UBOOTRELEASE UBOOTVERSION
 export ARCH CPU BOARD VENDOR SOC CPUDIR BOARDDIR
 export CONFIG_SHELL HOSTCC HOSTCFLAGS HOSTLDFLAGS CROSS_COMPILE AS LD CC
 export CPP AR NM LDR STRIP OBJCOPY OBJDUMP
-export MAKE AWK PERL
+export MAKE AWK PERL PYTHON
 export HOSTCXX HOSTCXXFLAGS DTC CHECK CHECKFLAGS
 
 export KBUILD_CPPFLAGS NOSTDINC_FLAGS UBOOTINCLUDE OBJCOPYFLAGS LDFLAGS
@@ -460,31 +458,49 @@ ifeq ($(config-targets),1)
 # *config targets only - make sure prerequisites are updated, and descend
 # in scripts/kconfig to make the *config target
 
-# Read arch specific Makefile to set KBUILD_DEFCONFIG as needed.
-# KBUILD_DEFCONFIG may point out an alternative default configuration
-# used for 'make defconfig'
+KBUILD_DEFCONFIG := sandbox_defconfig
+export KBUILD_DEFCONFIG KBUILD_KCONFIG
 
-%_config:: outputmakefile
-	@$(MKCONFIG) -A $(@:_config=)
+config: scripts_basic outputmakefile FORCE
+	+$(Q)$(PYTHON) $(srctree)/scripts/multiconfig.py $@
+
+%config: scripts_basic outputmakefile FORCE
+	+$(Q)$(PYTHON) $(srctree)/scripts/multiconfig.py $@
 
 else
 # ===========================================================================
 # Build targets only - this includes vmlinux, arch specific targets, clean
 # targets and others. In general all targets except *config targets.
 
-# load ARCH, BOARD, and CPU configuration
--include include/config.mk
-
 ifeq ($(dot-config),1)
 # Read in config
+-include include/config/auto.conf
+
+# Read in dependencies to all Kconfig* files, make sure to run
+# oldconfig if changes are detected.
+-include include/config/auto.conf.cmd
+
+# To avoid any implicit rule to kick in, define an empty command
+$(KCONFIG_CONFIG) include/config/auto.conf.cmd: ;
+
+# If .config is newer than include/config/auto.conf, someone tinkered
+# with it and forgot to run make oldconfig.
+# if auto.conf.cmd is missing then we are probably in a cleaned tree so
+# we execute the config step to be sure to catch updated Kconfig files
+include/config/%.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd
+	$(Q)$(MAKE) -f $(srctree)/Makefile silentoldconfig
+
 -include include/autoconf.mk
 -include include/autoconf.mk.dep
 
-# load other configuration
+# We want to include arch/$(ARCH)/config.mk only when include/config/auto.conf
+# is up-to-date. When we switch to a different board configuration, old CONFIG
+# macros are still remaining in include/config/auto.conf. Without the following
+# gimmick, wrong config.mk would be included leading nasty warnings/errors.
+autoconf_is_update := $(if $(wildcard $(KCONFIG_CONFIG)),$(shell find \
+		-path ./include/config/auto.conf -newer $(KCONFIG_CONFIG)))
+ifneq ($(autoconf_is_update),)
 include $(srctree)/config.mk
-
-ifeq ($(wildcard include/config.mk),)
-$(error "System not configured - see README")
 endif
 
 # If board code explicitly specified LDSCRIPT or CONFIG_SYS_LDSCRIPT, use
@@ -513,8 +529,8 @@ ifndef LDSCRIPT
 endif
 
 else
-
-
+# Dummy target needed, because used as prerequisite
+include/config/auto.conf: ;
 endif # $(dot-config)
 
 KBUILD_CFLAGS += -Os #-fomit-frame-pointer
@@ -563,7 +579,8 @@ KBUILD_CFLAGS += $(KCFLAGS)
 UBOOTINCLUDE    := \
 		-Iinclude \
 		$(if $(KBUILD_SRC), -I$(srctree)/include) \
-		-I$(srctree)/arch/$(ARCH)/include
+		-I$(srctree)/arch/$(ARCH)/include \
+		-include $(srctree)/include/linux/kconfig.h
 
 NOSTDINC_FLAGS += -nostdinc -isystem $(shell $(CC) -print-file-name=include)
 CHECKFLAGS     += $(NOSTDINC_FLAGS)
@@ -1018,7 +1035,7 @@ define filechk_uboot.release
 endef
 
 # Store (new) UBOOTRELEASE string in include/config/uboot.release
-include/config/uboot.release: Makefile FORCE
+include/config/uboot.release: include/config/auto.conf FORCE
 	$(call filechk,uboot.release)
 
 
@@ -1036,8 +1053,8 @@ PHONY += prepare archprepare prepare0 prepare1 prepare2 prepare3
 # 1) Check that make has not been executed in the kernel src $(srctree)
 prepare3: include/config/uboot.release
 ifneq ($(KBUILD_SRC),)
-	@$(kecho) '  Using $(srctree) as source for u-boot'
-	$(Q)if [ -f $(srctree)/include/config.mk ]; then \
+	@$(kecho) '  Using $(srctree) as source for U-Boot'
+	$(Q)if [ -f $(srctree)/.config -o -d $(srctree)/include/config ]; then \
 		echo >&2 "  $(srctree) is not clean, please run 'make mrproper'"; \
 		echo >&2 "  in the '$(srctree)' directory.";\
 		/bin/false; \
@@ -1047,7 +1064,8 @@ endif
 # prepare2 creates a makefile if using a separate output directory
 prepare2: prepare3 outputmakefile
 
-prepare1: prepare2 $(version_h) $(timestamp_h)
+prepare1: prepare2 $(version_h) $(timestamp_h) \
+                   include/config/auto.conf
 ifeq ($(__HAVE_ARCH_GENERIC_BOARD),)
 ifeq ($(CONFIG_SYS_GENERIC_BOARD),y)
 	@echo >&2 "  Your architecture does not support generic board."
@@ -1089,29 +1107,6 @@ $(version_h): include/config/uboot.release FORCE
 $(timestamp_h): $(srctree)/Makefile FORCE
 	$(call filechk,timestamp.h)
 
-#
-# Auto-generate the autoconf.mk file (which is included by all makefiles)
-#
-# This target actually generates 2 files; autoconf.mk and autoconf.mk.dep.
-# the dep file is only include in this top level makefile to determine when
-# to regenerate the autoconf.mk file.
-
-quiet_cmd_autoconf_dep = GEN     $@
-      cmd_autoconf_dep = $(CC) -x c -DDO_DEPS_ONLY -M $(c_flags) \
-	-MQ include/autoconf.mk $(srctree)/include/common.h > $@ || rm $@
-
-include/autoconf.mk.dep: include/config.h include/common.h
-	$(call cmd,autoconf_dep)
-
-quiet_cmd_autoconf = GEN     $@
-      cmd_autoconf = \
-	$(CPP) $(c_flags) -DDO_DEPS_ONLY -dM $(srctree)/include/common.h > $@.tmp && \
-	sed -n -f $(srctree)/tools/scripts/define2mk.sed $@.tmp > $@; \
-	rm $@.tmp
-
-include/autoconf.mk: include/config.h
-	$(call cmd,autoconf)
-
 # ---------------------------------------------------------------------------
 
 PHONY += depend dep
@@ -1135,7 +1130,7 @@ spl/sunxi-spl.bin: spl/u-boot-spl
 	@:
 
 tpl/u-boot-tpl.bin: tools prepare
-	$(Q)$(MAKE) obj=tpl -f $(srctree)/scripts/Makefile.spl all CONFIG_TPL_BUILD=y
+	$(Q)$(MAKE) obj=tpl -f $(srctree)/scripts/Makefile.spl all
 
 TAG_SUBDIRS := $(patsubst %,$(srctree)/%,$(u-boot-dirs) include)
 
@@ -1210,20 +1205,18 @@ include/license.h: tools/bin2header COPYING
 
 # Directories & files removed with 'make clean'
 CLEAN_DIRS  += $(MODVERDIR)
-CLEAN_FILES += u-boot.lds include/bmp_logo.h include/bmp_logo_data.h \
-	       include/autoconf.mk* include/spl-autoconf.mk \
-	       include/tpl-autoconf.mk
+CLEAN_FILES += u-boot.lds include/bmp_logo.h include/bmp_logo_data.h
 
 # Directories & files removed with 'make clobber'
-CLOBBER_DIRS  += spl tpl
+CLOBBER_DIRS  += $(foreach d, spl tpl, $(patsubst %,$d/%, \
+			$(filter-out include, $(shell ls -1 $d 2>/dev/null))))
 CLOBBER_FILES += u-boot* MLO* SPL System.map
 
 # Directories & files removed with 'make mrproper'
-MRPROPER_DIRS  += include/config include/generated          \
+MRPROPER_DIRS  += include/config include/generated spl tpl \
 		  .tmp_objdiff
-MRPROPER_FILES += .config .config.old \
-		  ctags etags cscope* GPATH GTAGS GRTAGS GSYMS \
-		  include/config.h include/config.mk
+MRPROPER_FILES += .config .config.old include/autoconf.mk* include/config.h \
+		  ctags etags TAGS cscope* GPATH GTAGS GRTAGS GSYMS
 
 # clean - Delete most, but leave enough to build external modules
 #
@@ -1300,10 +1293,9 @@ help:
 	@echo  '  mrproper	  - Remove all generated files + config + various backup files'
 	@echo  '  distclean	  - mrproper + remove editor backup and patch files'
 	@echo  ''
-# uncomment after adding Kconfig feature
-#	@echo  'Configuration targets:'
-#	@$(MAKE) -f $(srctree)/scripts/kconfig/Makefile help
-#	@echo  ''
+	@echo  'Configuration targets:'
+	@$(MAKE) -f $(srctree)/scripts/kconfig/Makefile help
+	@echo  ''
 	@echo  'Other generic targets:'
 	@echo  '  all		  - Build all necessary images depending on configuration'
 	@echo  '  u-boot	  - Build the bare u-boot'
diff --git a/arch/m68k/cpu/mcf52x2/config.mk b/arch/m68k/cpu/mcf52x2/config.mk
index 34ad99e..f66000b 100644
--- a/arch/m68k/cpu/mcf52x2/config.mk
+++ b/arch/m68k/cpu/mcf52x2/config.mk
@@ -7,14 +7,14 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-cfg=$(shell grep configs $(objtree)/include/config.h | sed 's/.*<\(configs.*\)>/\1/')
-is5208:=$(shell grep CONFIG_M5208 $(srctree)/include/$(cfg))
-is5249:=$(shell grep CONFIG_M5249 $(srctree)/include/$(cfg))
-is5253:=$(shell grep CONFIG_M5253 $(srctree)/include/$(cfg))
-is5271:=$(shell grep CONFIG_M5271 $(srctree)/include/$(cfg))
-is5272:=$(shell grep CONFIG_M5272 $(srctree)/include/$(cfg))
-is5275:=$(shell grep CONFIG_M5275 $(srctree)/include/$(cfg))
-is5282:=$(shell grep CONFIG_M5282 $(srctree)/include/$(cfg))
+cfg=$(srctree)/include/configs/$(CONFIG_SYS_CONFIG_NAME:"%"=%).h
+is5208:=$(shell grep CONFIG_M5208 $(cfg))
+is5249:=$(shell grep CONFIG_M5249 $(cfg))
+is5253:=$(shell grep CONFIG_M5253 $(cfg))
+is5271:=$(shell grep CONFIG_M5271 $(cfg))
+is5272:=$(shell grep CONFIG_M5272 $(cfg))
+is5275:=$(shell grep CONFIG_M5275 $(cfg))
+is5282:=$(shell grep CONFIG_M5282 $(cfg))
 
 ifneq (,$(findstring CONFIG_M5208,$(is5208)))
 PLATFORM_CPPFLAGS += -mcpu=5208
diff --git a/arch/m68k/cpu/mcf532x/config.mk b/arch/m68k/cpu/mcf532x/config.mk
index af94354..2efb60f 100644
--- a/arch/m68k/cpu/mcf532x/config.mk
+++ b/arch/m68k/cpu/mcf532x/config.mk
@@ -7,9 +7,9 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-cfg=$(shell grep configs $(objtree)/include/config.h | sed 's/.*<\(configs.*\)>/\1/')
-is5301x:=$(shell grep CONFIG_MCF5301x $(srctree)/include/$(cfg))
-is532x:=$(shell grep CONFIG_MCF532x $(srctree)/include/$(cfg))
+cfg=$(srctree)/include/configs/$(CONFIG_SYS_CONFIG_NAME:"%"=%).h
+is5301x:=$(shell grep CONFIG_MCF5301x $(cfg))
+is532x:=$(shell grep CONFIG_MCF532x $(cfg))
 
 ifneq (,$(findstring CONFIG_MCF5301x,$(is5301x)))
 PLATFORM_CPPFLAGS += -mcpu=53015 -fPIC
diff --git a/arch/m68k/cpu/mcf5445x/config.mk b/arch/m68k/cpu/mcf5445x/config.mk
index 5fd0d4d..13f8a9f 100644
--- a/arch/m68k/cpu/mcf5445x/config.mk
+++ b/arch/m68k/cpu/mcf5445x/config.mk
@@ -9,8 +9,8 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-cfg=$(shell grep configs $(objtree)/include/config.h | sed 's/.*<\(configs.*\)>/\1/')
-is5441x:=$(shell grep CONFIG_MCF5441x $(srctree)/include/$(cfg))
+cfg=$(srctree)/include/configs/$(CONFIG_SYS_CONFIG_NAME:"%"=%).h
+is5441x:=$(shell grep CONFIG_MCF5441x $(cfg))
 
 ifneq (,$(findstring CONFIG_MCF5441x,$(is5441x)))
 PLATFORM_CPPFLAGS += -mcpu=54418 -fPIC
diff --git a/arch/powerpc/cpu/ppc4xx/config.mk b/arch/powerpc/cpu/ppc4xx/config.mk
index 102f069..a7253b2 100644
--- a/arch/powerpc/cpu/ppc4xx/config.mk
+++ b/arch/powerpc/cpu/ppc4xx/config.mk
@@ -7,8 +7,8 @@
 
 PLATFORM_CPPFLAGS += -DCONFIG_4xx -mstring -msoft-float
 
-cfg=$(shell grep configs $(objtree)/include/config.h | sed 's/.*<\(configs.*\)>/\1/')
-is440:=$(shell grep CONFIG_440 $(srctree)/include/$(cfg))
+cfg=$(srctree)/include/configs/$(CONFIG_SYS_CONFIG_NAME:"%"=%).h
+is440:=$(shell grep CONFIG_440 $(cfg))
 
 ifneq (,$(findstring CONFIG_440,$(is440)))
 PLATFORM_CPPFLAGS += -Wa,-m440 -mcpu=440
diff --git a/config.mk b/config.mk
index bd74732..b4bf6f9 100644
--- a/config.mk
+++ b/config.mk
@@ -20,6 +20,16 @@ LDFLAGS_FINAL :=
 OBJCOPYFLAGS :=
 #########################################################################
 
+ARCH := $(CONFIG_SYS_ARCH:"%"=%)
+CPU := $(CONFIG_SYS_CPU:"%"=%)
+BOARD := $(CONFIG_SYS_BOARD:"%"=%)
+ifneq ($(CONFIG_SYS_VENDOR),)
+VENDOR := $(CONFIG_SYS_VENDOR:"%"=%)
+endif
+ifneq ($(CONFIG_SYS_SOC),)
+SOC := $(CONFIG_SYS_SOC:"%"=%)
+endif
+
 # Some architecture config.mk files need to know what CPUDIR is set to,
 # so calculate CPUDIR before including ARCH/SOC/CPU config.mk files.
 # Check if arch/$ARCH/cpu/$CPU exists, otherwise assume arch/$ARCH/cpu contains
diff --git a/include/.gitignore b/include/.gitignore
index bf142fc..8e41a95 100644
--- a/include/.gitignore
+++ b/include/.gitignore
@@ -2,4 +2,3 @@
 /bmp_logo.h
 /bmp_logo_data.h
 /config.h
-/config.mk
diff --git a/scripts/Makefile b/scripts/Makefile
index 68c998e..efe25bf 100644
--- a/scripts/Makefile
+++ b/scripts/Makefile
@@ -13,4 +13,4 @@ build_docproc: $(obj)/docproc
 	@:
 
 # Let clean descend into subdirs
-subdir-	+= basic
+subdir-	+= basic kconfig
diff --git a/scripts/Makefile.autoconf b/scripts/Makefile.autoconf
new file mode 100644
index 0000000..44c3997
--- /dev/null
+++ b/scripts/Makefile.autoconf
@@ -0,0 +1,100 @@
+# This helper makefile is used for creating
+#  - symbolic links (arch/$ARCH/include/asm/arch
+#  - include/autoconf.mk, {spl,tpl}/include/autoconf.mk
+#  - include/config.h
+#
+# When our migration to Kconfig is done
+# (= When we move all CONFIGs from header files to Kconfig)
+# this makefile can be deleted.
+
+# obj is "include" or "spl/include" or "tpl/include"
+# for non-SPL, SPL, TPL, respectively
+include $(obj)/config/auto.conf
+
+include scripts/Kbuild.include
+
+# Need to define CC and CPP again here in case the top Makefile did not
+# include config.mk.  Some architectures expect CROSS_COMPILE to be defined
+# in arch/$(ARCH)/config.mk
+CC		= $(CROSS_COMPILE)gcc
+CPP		= $(CC) -E
+
+include config.mk
+
+UBOOTINCLUDE    := \
+		-I$(obj) \
+		-Iinclude \
+		$(if $(KBUILD_SRC), -I$(srctree)/include) \
+		-I$(srctree)/arch/$(ARCH)/include \
+		-include $(srctree)/include/linux/kconfig.h
+
+c_flags := $(KBUILD_CFLAGS) $(KBUILD_CPPFLAGS) $(PLATFORM_CPPFLAGS) \
+					$(UBOOTINCLUDE) $(NOSTDINC_FLAGS)
+
+quiet_cmd_autoconf_dep = GEN     $@
+      cmd_autoconf_dep = $(CC) -x c -DDO_DEPS_ONLY -M -MP $(c_flags) \
+	-MQ include/config/auto.conf $(srctree)/include/common.h > $@ || {	\
+		rm $@; false;							\
+	}
+include/autoconf.mk.dep: FORCE
+	$(call cmd,autoconf_dep)
+
+# We are migrating from board headers to Kconfig little by little.
+# In the interim, we use both of
+#  - include/config/auto.conf (generated by Kconfig)
+#  - include/autoconf.mk      (used in the U-Boot conventional configuration)
+# The following rule creates autoconf.mk
+# include/config/auto.conf is grepped in order to avoid duplication of the
+# same CONFIG macros
+quiet_cmd_autoconf = GEN     $@
+      cmd_autoconf = \
+	$(CPP) $(c_flags) -DDO_DEPS_ONLY -dM $(srctree)/include/common.h > $@.tmp && {	\
+		sed -n -f $(srctree)/tools/scripts/define2mk.sed $@.tmp |		\
+		while read line; do							\
+			if ! grep -q "$${line%=*}=" $(obj)/config/auto.conf; then	\
+				echo "$$line";						\
+			fi								\
+		done > $@;								\
+		rm $@.tmp;								\
+	} || {										\
+		rm $@.tmp; false;							\
+	}
+
+$(obj)/autoconf.mk: FORCE
+	$(call cmd,autoconf)
+
+include/autoconf.mk include/autoconf.mk.dep: include/config.h
+
+# include/config.h
+# Prior to Kconfig, it was generated by mkconfig. Now it is created here.
+define filechk_config_h
+	(echo "/* Automatically generated - do not edit */";		\
+	for i in $$(echo $(CONFIG_SYS_EXTRA_OPTIONS) | sed 's/,/ /g'); do \
+		echo \#define CONFIG_$$i				\
+		| sed '/=/ {s/=/	/;q; } ; { s/$$/	1/; }'; \
+	done;								\
+	echo \#define CONFIG_BOARDDIR board/$(if $(VENDOR),$(VENDOR)/)$(BOARD);\
+	echo \#include \<config_cmd_defaults.h\>;			\
+	echo \#include \<config_defaults.h\>;				\
+	echo \#include \<configs/$(CONFIG_SYS_CONFIG_NAME).h\>;		\
+	echo \#include \<asm/config.h\>;				\
+	echo \#include \<config_fallbacks.h\>;				\
+	echo \#include \<config_uncmd_spl.h\>; )
+endef
+
+include/config.h: scripts/Makefile.autoconf create_symlink FORCE
+	$(call filechk,config_h)
+
+# symbolic links
+PHONY += create_symlink
+create_symlink:
+ifneq ($(KBUILD_SRC),)
+	$(Q)mkdir -p include/asm
+endif
+	$(Q)ln -fsn $(srctree)/arch/$(ARCH)/include/asm/arch-$(if $(SOC),$(SOC),$(CPU)) \
+		$(if $(KBUILD_SRC),,arch/$(ARCH)/)include/asm/arch
+
+PHONY += FORCE
+FORCE:
+
+.PHONY: $(PHONY)
diff --git a/scripts/Makefile.build b/scripts/Makefile.build
index 04c6f7d..baeaabe 100644
--- a/scripts/Makefile.build
+++ b/scripts/Makefile.build
@@ -3,14 +3,14 @@
 # ==========================================================================
 
 # Modified for U-Boot
-ifeq ($(CONFIG_TPL_BUILD),y)
-  src := $(patsubst tpl/%,%,$(obj))
-else
-  ifeq ($(CONFIG_SPL_BUILD),y)
-    src := $(patsubst spl/%,%,$(obj))
-  else
-    src := $(obj)
-  endif
+prefix := tpl
+src := $(patsubst $(prefix)/%,%,$(obj))
+ifeq ($(obj),$(src))
+prefix := spl
+src := $(patsubst $(prefix)/%,%,$(obj))
+ifeq ($(obj),$(src))
+prefix := .
+endif
 endif
 
 PHONY := __build
@@ -40,18 +40,9 @@ subdir-asflags-y :=
 subdir-ccflags-y :=
 
 # Read auto.conf if it exists, otherwise ignore
--include include/config/auto.conf
-
-# Added for U-Boot: Load U-Boot configuration
-ifeq ($(CONFIG_TPL_BUILD),y)
-  -include include/tpl-autoconf.mk
-else
-  ifeq ($(CONFIG_SPL_BUILD),y)
-    -include include/spl-autoconf.mk
-  else
-    -include include/autoconf.mk
-  endif
-endif
+# Modified for U-Boot
+-include $(prefix)/include/config/auto.conf
+-include $(prefix)/include/autoconf.mk
 
 include scripts/Kbuild.include
 
diff --git a/scripts/Makefile.spl b/scripts/Makefile.spl
index bf677aa..88c01d1 100644
--- a/scripts/Makefile.spl
+++ b/scripts/Makefile.spl
@@ -21,13 +21,10 @@ _dummy := $(shell [ -d $(obj) ] || mkdir -p $(obj))
 
 include $(srctree)/scripts/Kbuild.include
 
-CONFIG_SPL_BUILD := y
-export CONFIG_SPL_BUILD
+UBOOTINCLUDE := -I$(obj)/include $(UBOOTINCLUDE)
 
-KBUILD_CPPFLAGS += -DCONFIG_SPL_BUILD
-ifeq ($(CONFIG_TPL_BUILD),y)
-KBUILD_CPPFLAGS += -DCONFIG_TPL_BUILD
-endif
+-include $(obj)/include/config/auto.conf
+-include $(obj)/include/autoconf.mk
 
 ifeq ($(CONFIG_TPL_BUILD),y)
 export CONFIG_TPL_BUILD
@@ -36,14 +33,6 @@ else
 SPL_BIN := u-boot-spl
 endif
 
-include include/config.mk
-
-ifeq ($(CONFIG_TPL_BUILD),y)
-  -include include/tpl-autoconf.mk
-else
-  -include include/spl-autoconf.mk
-endif
-
 include $(srctree)/config.mk
 
 # Enable garbage collection of un-used sections for SPL
@@ -53,20 +42,6 @@ LDFLAGS_FINAL += --gc-sections
 # FIX ME
 cpp_flags := $(KBUILD_CPPFLAGS) $(PLATFORM_CPPFLAGS) $(UBOOTINCLUDE) \
 							$(NOSTDINC_FLAGS)
-c_flags := $(KBUILD_CFLAGS) $(cpp_flags)
-
-# Auto-generate the spl-autoconf.mk file (which is included by all makefiles for SPL)
-quiet_cmd_autoconf = GEN     $@
-      cmd_autoconf = \
-	$(CPP) $(c_flags) -DDO_DEPS_ONLY -dM $(srctree)/include/common.h > $@.tmp && \
-		sed -n -f $(srctree)/tools/scripts/define2mk.sed $@.tmp > $@; \
-	rm $@.tmp
-
-include/tpl-autoconf.mk: include/config.h
-	$(call cmd,autoconf)
-
-include/spl-autoconf.mk: include/config.h
-	$(call cmd,autoconf)
 
 HAVE_VENDOR_COMMON_LIB = $(if $(wildcard $(srctree)/board/$(VENDOR)/common/Makefile),y,n)
 
diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c
index b304068..1a41723 100644
--- a/scripts/basic/fixdep.c
+++ b/scripts/basic/fixdep.c
@@ -221,7 +221,11 @@ static void use_config(const char *m, int slen)
 
 	define_config(m, slen, hash);
 
-	printf("    $(wildcard include/config/");
+	/* printf("    $(wildcard include/config/"); */
+	/* modified for U-Boot */
+	printf("    $(wildcard %sinclude/config/",
+	       strncmp(depfile, "spl/", 4) ?
+	       (strncmp(depfile, "tpl/", 4) ? "" : "tpl/") : "spl/");
 	for (i = 0; i < slen; i++) {
 		c = m[i];
 		if (c == '_')
diff --git a/scripts/kconfig/confdata.c b/scripts/kconfig/confdata.c
index f88d90f..ae6ce66 100644
--- a/scripts/kconfig/confdata.c
+++ b/scripts/kconfig/confdata.c
@@ -951,6 +951,14 @@ int conf_write_autoconf(void)
 	FILE *out, *tristate, *out_h;
 	int i;
 
+	/*
+	 * Added for U-Boot SPL/TPL
+	 */
+	name = getenv("KCONFIG_OBJDIR");
+	if (name && name[0])
+		if (chdir(name))
+			return 1;
+
 	sym_clear_all_valid();
 
 	file_write_dep("include/config/auto.conf.cmd");
diff --git a/scripts/multiconfig.py b/scripts/multiconfig.py
new file mode 100755
index 0000000..544b44a
--- /dev/null
+++ b/scripts/multiconfig.py
@@ -0,0 +1,406 @@
+#!/usr/bin/env python
+#
+# Copyright (C) 2014, Masahiro Yamada <yamada.m at jp.panasonic.com>
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+'''
+A wrapper script to adjust Kconfig for U-Boot
+
+The biggest difference between Linux Kernel and U-Boot in terms of the
+board configuration is that U-Boot has to configure multiple boot images
+per board: Normal, SPL, TPL.
+We need to expand the functions of Kconfig to handle multiple boot images.
+
+Instead of touching various parts under scripts/kconfig/ directory,
+pushing necessary adjustments into this single script would be better
+for code maintainance. All the make targets related to the configuration
+(make %config) should be invoked through this script.
+
+Let's see what is different from the original Kconfig.
+
+- config, menuconfig, etc.
+
+The commands "make config", "make menuconfig", etc. are used to create
+or modify .config file, which stores configs for Normal boot image.
+
+The location of that file for SPL, TPL image is spl/.config, tpl/.config,
+respectively. Use "make spl:config", "make spl:menuconfig", etc. to create
+or modify spl/.config file, which contains configs for SPL image.
+Do likewise for tpl/.config file.
+The generic syntax for SPL, TPL configuration is
+"make <target_image>:<config_command>".
+
+- silentoldconfig
+
+The command "make silentoldconfig" updates .config, if necessary, and
+additionally updates include/generated/autoconf.h and files under
+include/configs/ directory. In U-Boot, it should do the same things for
+SPL, TPL images for boards supporting them.
+Depending on whether CONFIG_SPL, CONFIG_TPL is defined or not,
+"make silentoldconfig" iterates three times at most changing the target
+directory.
+
+To sum up, "make silentoldconfig" possibly updates
+  - .config, include/generated/autoconf.h, include/config/*
+  - spl/.config, spl/include/generated/autoconf.h, spl/include/config/*
+    (in case CONFIG_SPL=y)
+  - tpl/.config, tpl/include/generated/autoconf.h, tpl/include/config/*
+    (in case CONFIG_TPL=y)
+
+- defconfig, <board>_defconfig
+
+The command "make <board>_defconfig" creates a new .config based on the
+file configs/<board>_defconfig. The command "make defconfig" is the same
+but the difference is it uses the file specified with KBUILD_DEFCONFIG
+environment.
+
+We need to create .spl, spl/.config, tpl/.config for boards where SPL/TPL
+is supported. One possible solution for that is to have multiple defconfig
+files per board, but it would produce duplication among defconfigs.
+The approach chosen here is to expand the feature and support conditional
+definition in defconfig: The each line in defconfig has the form of:
+<condition>:<macro definition>
+
+The "<condition>:" prefix specifies which image the line is valid for.
+The "<condition>:" is one of:
+  None  - the line is valid only for Normal image
+  S:    - the line is valid only for SPL image
+  T:    - the line is valid only for TPL image
+  ST:   - the line is valid for SPL and TPL images
+  +S:   - the line is valid for Normal and SPL images
+  +T:   - the line is valid for Normal and TPL images
+  +ST:  - the line is valid for Normal, SPL and SPL images
+
+So, if neither CONFIG_SPL nor CONFIG_TPL is defined, the defconfig file
+has no "<condition>:" part and has the same form of that of Linux Kernel.
+
+In U-Boot, for example, defconfig can be written like this:
+
+  CONFIG_FOO=100
+  S:CONFIG_FOO=200
+  T:CONFIG_FOO=300
+  ST:CONFIG_BAR=y
+  +S:CONFIG_BAZ=y
+  +T:CONFIG_QUX=y
+  +ST:CONFIG_QUUX=y
+
+The defconfig above is parsed by this script and internally divided into
+three temporary defconfig files.
+
+  - Temporary defconfig for Normal image
+     CONFIG_FOO=100
+     CONFIG_BAZ=y
+     CONFIG_QUX=y
+     CONFIG_QUUX=y
+
+  - Temporary defconfig for SPL image
+     CONFIG_FOO=200
+     CONFIG_BAR=y
+     CONFIG_BAZ=y
+     CONFIG_QUUX=y
+
+  - Temporary defconfig for TPL image
+     CONFIG_FOO=300
+     CONFIG_BAR=y
+     CONFIG_QUX=y
+     CONFIG_QUUX=y
+
+They are passed to scripts/kconfig/conf, each is used for generating
+.config, spl/.config, tpl/.config, respectively.
+
+- savedefconfig
+
+This is the reverse operation of "make defconfig".
+If neither CONFIG_SPL nor CONFIG_TPL is defined in the .config file,
+it works as "make savedefconfig" in Linux Kernel: create the minimal set
+of config based on the .config and save it into "defconfig" file.
+
+If CONFIG_SPL or CONFIG_TPL is defined, the common lines among .config,
+spl/.config, tpl/.config are coalesced together and output "defconfig"
+in the form like:
+
+  CONFIG_FOO=100
+  S:CONFIG_FOO=200
+  T:CONFIG_FOO=300
+  ST:CONFIG_BAR=y
+  +S:CONFIG_BAZ=y
+  +T:CONFIG_QUX=y
+  +ST:CONFIG_QUUX=y
+
+This can be used as an input of "make <board>_defconfig" command.
+'''
+
+import os
+import sys
+import re
+import errno
+import subprocess
+
+# Constant variables
+SUB_IMAGES = ('spl', 'tpl')
+IMAGES = ('',) + SUB_IMAGES
+SYMBOL_MAP = {'': '+', 'spl': 'S', 'tpl': 'T'}
+PATTERN_SYMBOL = re.compile(r"(\+?)(S?)(T?):(.*)")
+
+# Environment variables (should be defined in the top Makefile)
+# .get('key', 'default_value') method is used for standalone testing.
+MAKE = os.environ.get('MAKE', 'make')
+srctree = os.environ.get('srctree', '.')
+KCONFIG_CONFIG = os.environ.get('KCONFIG_CONFIG', '.config')
+
+# Useful shorthand
+build = '%s -f %s/scripts/Makefile.build obj=scripts/kconfig %%s' % (MAKE, srctree)
+autoconf = '%s -f %s/scripts/Makefile.autoconf obj=%%s %%s' % (MAKE, srctree)
+
+### helper functions
+def mkdirs(*dirs):
+    '''
+    Make directories ignoring 'File exists' error
+    '''
+    for d in dirs:
+        try:
+            os.makedirs(d)
+        except OSError as exception:
+            # Ignore 'File exists' error
+            if exception.errno != errno.EEXIST:
+                raise
+
+def rmfiles(*files):
+    '''
+    Remove files ignoring 'No such file or directory' error
+    '''
+    for f in files:
+        try:
+            os.remove(f)
+        except OSError as exception:
+            # Ignore 'No such file or directory' error
+            if exception.errno != errno.ENOENT:
+                raise
+
+def error(msg):
+    '''
+    Output the given argument to stderr and exit with return code 1
+    '''
+    print >> sys.stderr, msg
+    sys.exit(1)
+
+def run_command(command, callback_on_error=None):
+    '''
+    Run the given command in a sub-shell (and exit with return code 1
+    if the command fails)
+
+    Arguments:
+      command - A string of the command
+      callback_on_error - Callback handler invoked just before exit
+                          when the command fails (Default=None)
+    '''
+    retcode = subprocess.call(command, shell=True)
+    if retcode:
+        if callback_on_error:
+            callback_on_error()
+        error('"%s" Failed' % command)
+
+def run_make_config(cmd, objdir, callback_on_error=None):
+    '''
+    Run the make command in a sub-shell (and exit with return code 1
+    if the command fails)
+
+    Arguments:
+      cmd - Make target such as 'config', 'menuconfig', 'defconfig', etc.
+      objdir - Target directory where the make command is run.
+               Typically '', 'spl', 'tpl' for Normal, SPL, TPL image,
+               respectively.
+      callback_on_error - Callback handler invoked just before exit
+                          when the command fails (Default=None)
+    '''
+    # Linux expects defconfig files in arch/$(SRCARCH)/configs/ directory,
+    # but U-Boot puts them in configs/ directory.
+    # Give SRCARCH=.. to fake scripts/kconfig/Makefile.
+    options = 'SRCARCH=.. KCONFIG_OBJDIR=%s' % objdir
+    if objdir:
+        options += ' KCONFIG_CONFIG=%s/%s' % (objdir, KCONFIG_CONFIG)
+        mkdirs(objdir)
+    run_command(build % cmd + ' ' + options, callback_on_error)
+
+def get_enabled_subimages(ignore_error=False):
+    '''
+    Parse .config file to detect if CONFIG_SPL, CONFIG_TPL is enabled
+    and return a tuple of enabled subimages
+
+    Arguments:
+      ignore_error - Specify the behavior when .config file is not found.
+                     Raise an exception if this flag is False.
+                     Return a null tuple if this flag is True.
+    Returns:
+      A tuple of enabled subimages as follows:
+        ()             if neither CONFIG_SPL nor CONFIG_TPL is defined
+        ('spl',)       if CONFIG_SPL is defined but CONFIG_TPL is not
+        ('spl', 'tpl') if both CONFIG_SPL and CONFIG_TPL are defined
+    '''
+    enabled = ()
+    match_pattern = [ (img, 'CONFIG_' + img.upper() + '=y\n')
+                                                        for img in SUB_IMAGES ]
+    try:
+        f = open(KCONFIG_CONFIG)
+    except IOError as exception:
+        if not ignore_error or exception.errno != errno.ENOENT:
+            raise
+        return enabled
+    with f:
+        for line in f:
+            for img, pattern in match_pattern:
+                if line == pattern:
+                    enabled += (img,)
+    return enabled
+
+def do_silentoldconfig(cmd):
+    '''
+    Run "make silentoldconfig" for all the enabled images
+
+    Arguments:
+      cmd - should always be a string 'silentoldconfig'
+    '''
+    run_make_config(cmd, '')
+    subimages = get_enabled_subimages()
+    for obj in subimages:
+        mkdirs(os.path.join(obj, 'include', 'config'),
+               os.path.join(obj, 'include', 'generated'))
+        run_make_config(cmd, obj)
+    remove_auto_conf = lambda : rmfiles('include/config/auto.conf')
+    # If the following part failed, include/config/auto.conf should be deleted
+    # so 'make silentoldconfig' will be re-run on the next build.
+    run_command(autoconf %
+                ('include', 'include/autoconf.mk include/autoconf.mk.dep'),
+                remove_auto_conf)
+    # include/config.h has been updated after "make silentoldconfig".
+    # We need to touch include/config/auto.conf so it gets newer
+    # than include/config.h.
+    # Otherwise, "make silentoldconfig" would be invoked twice.
+    os.utime('include/config/auto.conf', None)
+    for obj in subimages:
+        run_command(autoconf %
+                    (obj + '/include', obj + '/include/autoconf.mk'),
+                    remove_auto_conf)
+
+def do_tmp_defconfig(output_lines, img):
+    '''
+    Helper function for do_board_defconfig.
+    Write the defconfig contents into a file ".tmp_defconfig" and
+    invoke "make .tmp_defconfig".
+
+    Arguments:
+      output_lines - A sequence of defconfig lines of each image
+      img - Target image. Typically '', 'spl', 'tpl' for
+            Normal, SPL, TPL images, respectively.
+    '''
+    TMP_DEFCONFIG = '.tmp_defconfig'
+    defconfig_path = os.path.join('configs', TMP_DEFCONFIG)
+    mkdirs('arch', 'configs')
+    with open(defconfig_path, 'w') as f:
+        f.write(''.join(output_lines[img]))
+    run_make_config(TMP_DEFCONFIG, img, lambda: rmfiles(defconfig_path))
+    rmfiles(defconfig_path)
+
+def do_board_defconfig(cmd):
+    '''
+    Run "make <board>_defconfig"
+
+    Arguments:
+      cmd - should be a string '<board>_defconfig'
+    '''
+    defconfig = cmd
+    defconfig_path = os.path.join(srctree, 'configs', defconfig)
+    output_lines = dict([ (img, []) for img in IMAGES ])
+    with open(defconfig_path) as f:
+        for line in f:
+            m = PATTERN_SYMBOL.match(line)
+            if m:
+                for idx, img in enumerate(IMAGES):
+                    if m.group(idx + 1):
+                        output_lines[img].append(m.group(4) + '\n')
+                continue
+            output_lines[''].append(line)
+    do_tmp_defconfig(output_lines, '')
+    for img in get_enabled_subimages():
+        do_tmp_defconfig(output_lines, img)
+
+def do_defconfig(cmd):
+    '''
+    Run "make defconfig"
+
+    Arguments:
+      cmd - should always be a string 'defconfig'
+    '''
+    KBUILD_DEFCONFIG = os.environ['KBUILD_DEFCONFIG']
+    print "*** Default configuration is based on '%s'" % KBUILD_DEFCONFIG
+    do_board_defconfig(KBUILD_DEFCONFIG)
+
+def do_savedefconfig(cmd):
+    '''
+    Run "make savedefconfig"
+
+    Arguments:
+      cmd - should always be a string 'savedefconfig'
+    '''
+    defconfig = 'defconfig'
+    # Continue even if '.config' does not exist
+    subimages = get_enabled_subimages(True)
+    run_make_config(cmd, '')
+    output_lines = []
+    prefix = {}
+    with open(defconfig) as f:
+        for line in f:
+            output_lines.append(line)
+            prefix[line] = '+'
+    for img in subimages:
+        run_make_config(cmd, img)
+        unmatched_lines = []
+        with open(defconfig) as f:
+            for line in f:
+                if line in output_lines:
+                    index = output_lines.index(line)
+                    output_lines[index:index] = unmatched_lines
+                    unmatched_lines = []
+                    prefix[line] += SYMBOL_MAP[img]
+                else:
+                    ummatched_lines.append(line)
+                    prefix[line] = SYMBOL_MAP[img]
+    with open(defconfig, 'w') as f:
+        for line in output_lines:
+            if prefix[line] == '+':
+                f.write(line)
+            else:
+                f.write(prefix[line] + ':' + line)
+
+def do_others(cmd):
+    '''
+    Run the make command other than 'silentoldconfig', 'defconfig',
+    '<board>_defconfig' and 'savedefconfig'
+
+    Arguments:
+      cmd - Make target in the form of '<target_image>:<config_command>'
+            The field '<target_image>:' is typically empty, 'spl:', 'tpl:'
+            for Normal, SPL, TPL images, respectively.
+            The field '<config_command>' is make target such as 'config',
+            'menuconfig', etc.
+    '''
+
+    cmd, _, objdir = cmd.partition(':')
+    run_make_config(cmd, objdir)
+
+cmd_list = {'silentoldconfig': do_silentoldconfig,
+            'defconfig': do_defconfig,
+            'savedefconfig': do_savedefconfig}
+
+def main():
+    cmd = sys.argv[1]
+    if cmd.endswith('_defconfig'):
+        do_board_defconfig(cmd)
+    else:
+        func = cmd_list.get(cmd, do_others)
+        func(cmd)
+
+if __name__ == '__main__':
+    main()
diff --git a/tools/Makefile b/tools/Makefile
index 61b2048..90e966d 100644
--- a/tools/Makefile
+++ b/tools/Makefile
@@ -193,7 +193,7 @@ endif # !LOGO_BMP
 # Define _GNU_SOURCE to obtain the getline prototype from stdio.h
 #
 HOST_EXTRACFLAGS += -include $(srctree)/include/libfdt_env.h \
-		$(patsubst -I%,-idirafter%, $(UBOOTINCLUDE)) \
+		$(patsubst -I%,-idirafter%, $(filter -I%, $(UBOOTINCLUDE))) \
 		-I$(srctree)/lib/libfdt \
 		-I$(srctree)/tools \
 		-DCONFIG_SYS_TEXT_BASE=$(CONFIG_SYS_TEXT_BASE) \
diff --git a/tools/env/Makefile b/tools/env/Makefile
index f5368bc..4927489 100644
--- a/tools/env/Makefile
+++ b/tools/env/Makefile
@@ -11,7 +11,7 @@
 HOSTCC = $(CC)
 
 # Compile for a hosted environment on the target
-HOST_EXTRACFLAGS  = $(patsubst -I%,-idirafter%, $(UBOOTINCLUDE)) \
+HOST_EXTRACFLAGS  = $(patsubst -I%,-idirafter%, $(filter -I%, $(UBOOTINCLUDE))) \
 		-idirafter $(srctree)/tools/env \
 		-DUSE_HOSTCC \
 		-DTEXT_BASE=$(TEXT_BASE)
-- 
1.9.1



More information about the U-Boot mailing list