浏览代码

Merge tag 'kconfig-v4.19' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild

Pull Kconfig updates from Masahiro Yamada:

 - show clearer error messages where pkg-config is needed, but not
   installed

 - rename SYMBOL_AUTO to SYMBOL_NO_WRITE to reflect its semantics

 - create all necessary directories by Kconfig tool itself instead of
   Makefile

 - update the .config unconditionally when syncconfig is invoked

 - use 'include' directive instead of '-include' where
   include/config/{auto,tristate}.conf is mandatory

 - do not try to update the .config when running install targets

 - add .DELETE_ON_ERROR to delete partially updated files

 - misc cleanups and fixes

* tag 'kconfig-v4.19' of git://git.kernel.org/pub/scm/linux/kernel/git/masahiroy/linux-kbuild:
  kconfig: remove P_ENV property type
  kconfig: remove unused sym_get_env_prop() function
  kconfig: fix the rule of mainmenu_stmt symbol
  init/Kconfig: Use short unix-style option instead of --longname
  Kbuild: Makefile.modbuiltin: include auto.conf and tristate.conf mandatory
  kbuild: remove auto.conf from prerequisite of phony targets
  kbuild: do not update config for 'make kernelrelease'
  kbuild: do not update config when running install targets
  kbuild: add .DELETE_ON_ERROR special target
  kbuild: use 'include' directive to load auto.conf from top Makefile
  kconfig: allow all config targets to write auto.conf if missing
  kconfig: make syncconfig update .config regardless of sym_change_count
  kconfig: create directories needed for syncconfig by itself
  kconfig: remove unneeded directory generation from local*config
  kconfig: split out useful helpers in confdata.c
  kconfig: rename file_write_dep and move it to confdata.c
  kconfig: fix typos in description of "choice" in kconfig-language.txt
  kconfig: handle format string before calling conf_message_callback()
  kconfig: rename SYMBOL_AUTO to SYMBOL_NO_WRITE
  kconfig: check for pkg-config on make {menu,n,g,x}config
Linus Torvalds 7 年之前
父节点
当前提交
01f0e5cded

+ 2 - 2
Documentation/kbuild/kconfig-language.txt

@@ -370,7 +370,7 @@ choices:
 
 
 This defines a choice group and accepts any of the above attributes as
 This defines a choice group and accepts any of the above attributes as
 options. A choice can only be of type bool or tristate.  If no type is
 options. A choice can only be of type bool or tristate.  If no type is
-specified for a choice, it's type will be determined by the type of
+specified for a choice, its type will be determined by the type of
 the first choice element in the group or remain unknown if none of the
 the first choice element in the group or remain unknown if none of the
 choice elements have a type specified, as well.
 choice elements have a type specified, as well.
 
 
@@ -384,7 +384,7 @@ A choice accepts another option "optional", which allows to set the
 choice to 'n' and no entry needs to be selected.
 choice to 'n' and no entry needs to be selected.
 If no [symbol] is associated with a choice, then you can not have multiple
 If no [symbol] is associated with a choice, then you can not have multiple
 definitions of that choice. If a [symbol] is associated to the choice,
 definitions of that choice. If a [symbol] is associated to the choice,
-then you may define the same choice (ie. with the same entries) in another
+then you may define the same choice (i.e. with the same entries) in another
 place.
 place.
 
 
 comment:
 comment:

+ 8 - 0
Documentation/process/changes.rst

@@ -81,6 +81,14 @@ The build system has, as of 4.13, switched to using thin archives (`ar T`)
 rather than incremental linking (`ld -r`) for built-in.a intermediate steps.
 rather than incremental linking (`ld -r`) for built-in.a intermediate steps.
 This requires binutils 2.20 or newer.
 This requires binutils 2.20 or newer.
 
 
+pkg-config
+----------
+
+The build system, as of 4.18, requires pkg-config to check for installed
+kconfig tools and to determine flags settings for use in
+'make {menu,n,g,x}config'.  Previously pkg-config was being used but not
+verified or documented.
+
 Flex
 Flex
 ----
 ----
 
 

+ 26 - 18
Makefile

@@ -225,10 +225,13 @@ no-dot-config-targets := $(clean-targets) \
 			 cscope gtags TAGS tags help% %docs check% coccicheck \
 			 cscope gtags TAGS tags help% %docs check% coccicheck \
 			 $(version_h) headers_% archheaders archscripts \
 			 $(version_h) headers_% archheaders archscripts \
 			 %asm-generic kernelversion %src-pkg
 			 %asm-generic kernelversion %src-pkg
+no-sync-config-targets := $(no-dot-config-targets) install %install \
+			   kernelrelease
 
 
-config-targets := 0
-mixed-targets  := 0
-dot-config     := 1
+config-targets  := 0
+mixed-targets   := 0
+dot-config      := 1
+may-sync-config := 1
 
 
 ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),)
 ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),)
 	ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),)
 	ifeq ($(filter-out $(no-dot-config-targets), $(MAKECMDGOALS)),)
@@ -236,6 +239,16 @@ ifneq ($(filter $(no-dot-config-targets), $(MAKECMDGOALS)),)
 	endif
 	endif
 endif
 endif
 
 
+ifneq ($(filter $(no-sync-config-targets), $(MAKECMDGOALS)),)
+	ifeq ($(filter-out $(no-sync-config-targets), $(MAKECMDGOALS)),)
+		may-sync-config := 0
+	endif
+endif
+
+ifneq ($(KBUILD_EXTMOD),)
+	may-sync-config := 0
+endif
+
 ifeq ($(KBUILD_EXTMOD),)
 ifeq ($(KBUILD_EXTMOD),)
         ifneq ($(filter config %config,$(MAKECMDGOALS)),)
         ifneq ($(filter config %config,$(MAKECMDGOALS)),)
                 config-targets := 1
                 config-targets := 1
@@ -585,7 +598,7 @@ virt-y		:= virt/
 endif # KBUILD_EXTMOD
 endif # KBUILD_EXTMOD
 
 
 ifeq ($(dot-config),1)
 ifeq ($(dot-config),1)
--include include/config/auto.conf
+include include/config/auto.conf
 endif
 endif
 
 
 # The all: target is the default when no target is given on the
 # The all: target is the default when no target is given on the
@@ -607,7 +620,7 @@ ARCH_CFLAGS :=
 include arch/$(SRCARCH)/Makefile
 include arch/$(SRCARCH)/Makefile
 
 
 ifeq ($(dot-config),1)
 ifeq ($(dot-config),1)
-ifeq ($(KBUILD_EXTMOD),)
+ifeq ($(may-sync-config),1)
 # Read in dependencies to all Kconfig* files, make sure to run syncconfig if
 # Read in dependencies to all Kconfig* files, make sure to run syncconfig if
 # changes are detected. This should be included after arch/$(SRCARCH)/Makefile
 # changes are detected. This should be included after arch/$(SRCARCH)/Makefile
 # because some architectures define CROSS_COMPILE there.
 # because some architectures define CROSS_COMPILE there.
@@ -622,8 +635,9 @@ $(KCONFIG_CONFIG) include/config/auto.conf.cmd: ;
 include/config/%.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd
 include/config/%.conf: $(KCONFIG_CONFIG) include/config/auto.conf.cmd
 	$(Q)$(MAKE) -f $(srctree)/Makefile syncconfig
 	$(Q)$(MAKE) -f $(srctree)/Makefile syncconfig
 else
 else
-# external modules needs include/generated/autoconf.h and include/config/auto.conf
-# but do not care if they are up-to-date. Use auto.conf to trigger the test
+# External modules and some install targets need include/generated/autoconf.h
+# and include/config/auto.conf but do not care if they are up-to-date.
+# Use auto.conf to trigger the test
 PHONY += include/config/auto.conf
 PHONY += include/config/auto.conf
 
 
 include/config/auto.conf:
 include/config/auto.conf:
@@ -635,11 +649,7 @@ include/config/auto.conf:
 	echo >&2 ;							\
 	echo >&2 ;							\
 	/bin/false)
 	/bin/false)
 
 
-endif # KBUILD_EXTMOD
-
-else
-# Dummy target needed, because used as prerequisite
-include/config/auto.conf: ;
+endif # may-sync-config
 endif # $(dot-config)
 endif # $(dot-config)
 
 
 KBUILD_CFLAGS	+= $(call cc-option,-fno-delete-null-pointer-checks,)
 KBUILD_CFLAGS	+= $(call cc-option,-fno-delete-null-pointer-checks,)
@@ -1035,15 +1045,14 @@ define filechk_kernel.release
 endef
 endef
 
 
 # Store (new) KERNELRELEASE string in include/config/kernel.release
 # Store (new) KERNELRELEASE string in include/config/kernel.release
-include/config/kernel.release: include/config/auto.conf FORCE
+include/config/kernel.release: $(srctree)/Makefile FORCE
 	$(call filechk,kernel.release)
 	$(call filechk,kernel.release)
 
 
 # Additional helpers built in scripts/
 # Additional helpers built in scripts/
 # Carefully list dependencies so we do not try to build scripts twice
 # Carefully list dependencies so we do not try to build scripts twice
 # in parallel
 # in parallel
 PHONY += scripts
 PHONY += scripts
-scripts: scripts_basic include/config/auto.conf include/config/tristate.conf \
-	 asm-generic gcc-plugins $(autoksyms_h)
+scripts: scripts_basic asm-generic gcc-plugins $(autoksyms_h)
 	$(Q)$(MAKE) $(build)=$(@)
 	$(Q)$(MAKE) $(build)=$(@)
 
 
 # Things we need to do before we recursively start building the kernel
 # Things we need to do before we recursively start building the kernel
@@ -1073,8 +1082,7 @@ endif
 # that need to depend on updated CONFIG_* values can be checked here.
 # that need to depend on updated CONFIG_* values can be checked here.
 prepare2: prepare3 outputmakefile asm-generic
 prepare2: prepare3 outputmakefile asm-generic
 
 
-prepare1: prepare2 $(version_h) $(autoksyms_h) include/generated/utsrelease.h \
-                   include/config/auto.conf
+prepare1: prepare2 $(version_h) $(autoksyms_h) include/generated/utsrelease.h
 	$(cmd_crmodverdir)
 	$(cmd_crmodverdir)
 
 
 archprepare: archheaders archscripts prepare1 scripts_basic
 archprepare: archheaders archscripts prepare1 scripts_basic
@@ -1212,7 +1220,7 @@ modules: $(vmlinux-dirs) $(if $(KBUILD_BUILTIN),vmlinux) modules.builtin
 modules.builtin: $(vmlinux-dirs:%=%/modules.builtin)
 modules.builtin: $(vmlinux-dirs:%=%/modules.builtin)
 	$(Q)$(AWK) '!x[$$0]++' $^ > $(objtree)/modules.builtin
 	$(Q)$(AWK) '!x[$$0]++' $^ > $(objtree)/modules.builtin
 
 
-%/modules.builtin: include/config/auto.conf
+%/modules.builtin: include/config/auto.conf include/config/tristate.conf
 	$(Q)$(MAKE) $(modbuiltin)=$*
 	$(Q)$(MAKE) $(modbuiltin)=$*
 
 
 
 

+ 2 - 2
init/Kconfig

@@ -2,9 +2,9 @@ config DEFCONFIG_LIST
 	string
 	string
 	depends on !UML
 	depends on !UML
 	option defconfig_list
 	option defconfig_list
-	default "/lib/modules/$(shell,uname --release)/.config"
+	default "/lib/modules/$(shell,uname -r)/.config"
 	default "/etc/kernel-config"
 	default "/etc/kernel-config"
-	default "/boot/config-$(shell,uname --release)"
+	default "/boot/config-$(shell,uname -r)"
 	default ARCH_DEFCONFIG
 	default ARCH_DEFCONFIG
 	default "arch/$(ARCH)/defconfig"
 	default "arch/$(ARCH)/defconfig"
 
 

+ 3 - 0
scripts/Kbuild.include

@@ -400,3 +400,6 @@ endif
 endef
 endef
 #
 #
 ###############################################################################
 ###############################################################################
+
+# delete partially updated (i.e. corrupted) files on error
+.DELETE_ON_ERROR:

+ 2 - 2
scripts/Makefile.modbuiltin

@@ -8,10 +8,10 @@ src := $(obj)
 PHONY := __modbuiltin
 PHONY := __modbuiltin
 __modbuiltin:
 __modbuiltin:
 
 
--include include/config/auto.conf
+include include/config/auto.conf
 # tristate.conf sets tristate variables to uppercase 'Y' or 'M'
 # tristate.conf sets tristate variables to uppercase 'Y' or 'M'
 # That way, we get the list of built-in modules in obj-Y
 # That way, we get the list of built-in modules in obj-Y
--include include/config/tristate.conf
+include include/config/tristate.conf
 
 
 include scripts/Kbuild.include
 include scripts/Kbuild.include
 
 

+ 7 - 10
scripts/kconfig/Makefile

@@ -3,8 +3,7 @@
 # Kernel configuration targets
 # Kernel configuration targets
 # These targets are used from top-level makefile
 # These targets are used from top-level makefile
 
 
-PHONY += xconfig gconfig menuconfig config syncconfig \
-	localmodconfig localyesconfig
+PHONY += xconfig gconfig menuconfig config localmodconfig localyesconfig
 
 
 ifdef KBUILD_KCONFIG
 ifdef KBUILD_KCONFIG
 Kconfig := $(KBUILD_KCONFIG)
 Kconfig := $(KBUILD_KCONFIG)
@@ -34,14 +33,7 @@ config: $(obj)/conf
 nconfig: $(obj)/nconf
 nconfig: $(obj)/nconf
 	$< $(silent) $(Kconfig)
 	$< $(silent) $(Kconfig)
 
 
-# This has become an internal implementation detail and is now deprecated
-# for external use.
-syncconfig: $(obj)/conf
-	$(Q)mkdir -p include/config include/generated
-	$< $(silent) --$@ $(Kconfig)
-
 localyesconfig localmodconfig: $(obj)/conf
 localyesconfig localmodconfig: $(obj)/conf
-	$(Q)mkdir -p include/config include/generated
 	$(Q)perl $(srctree)/$(src)/streamline_config.pl --$@ $(srctree) $(Kconfig) > .tmp.config
 	$(Q)perl $(srctree)/$(src)/streamline_config.pl --$@ $(srctree) $(Kconfig) > .tmp.config
 	$(Q)if [ -f .config ]; then 					\
 	$(Q)if [ -f .config ]; then 					\
 			cmp -s .tmp.config .config ||			\
 			cmp -s .tmp.config .config ||			\
@@ -56,8 +48,12 @@ localyesconfig localmodconfig: $(obj)/conf
 	$(Q)rm -f .tmp.config
 	$(Q)rm -f .tmp.config
 
 
 # These targets map 1:1 to the commandline options of 'conf'
 # These targets map 1:1 to the commandline options of 'conf'
+#
+# Note:
+#  syncconfig has become an internal implementation detail and is now
+#  deprecated for external use
 simple-targets := oldconfig allnoconfig allyesconfig allmodconfig \
 simple-targets := oldconfig allnoconfig allyesconfig allmodconfig \
-	alldefconfig randconfig listnewconfig olddefconfig
+	alldefconfig randconfig listnewconfig olddefconfig syncconfig
 PHONY += $(simple-targets)
 PHONY += $(simple-targets)
 
 
 $(simple-targets): $(obj)/conf
 $(simple-targets): $(obj)/conf
@@ -215,6 +211,7 @@ $(obj)/zconf.tab.o: $(obj)/zconf.lex.c
 
 
 # check if necessary packages are available, and configure build flags
 # check if necessary packages are available, and configure build flags
 define filechk_conf_cfg
 define filechk_conf_cfg
+	$(CONFIG_SHELL) $(srctree)/scripts/kconfig/check-pkgconfig.sh; \
 	$(CONFIG_SHELL) $<
 	$(CONFIG_SHELL) $<
 endef
 endef
 
 

+ 8 - 0
scripts/kconfig/check-pkgconfig.sh

@@ -0,0 +1,8 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+# Check for pkg-config presence
+
+if [ -z $(command -v pkg-config) ]; then
+	echo "'make *config' requires 'pkg-config'. Please install it." 1>&2
+	exit 1
+fi

+ 22 - 17
scripts/kconfig/conf.c

@@ -496,6 +496,7 @@ int main(int ac, char **av)
 	int opt;
 	int opt;
 	const char *name, *defconfig_file = NULL /* gcc uninit */;
 	const char *name, *defconfig_file = NULL /* gcc uninit */;
 	struct stat tmpstat;
 	struct stat tmpstat;
+	int no_conf_write = 0;
 
 
 	tty_stdio = isatty(0) && isatty(1);
 	tty_stdio = isatty(0) && isatty(1);
 
 
@@ -633,13 +634,14 @@ int main(int ac, char **av)
 	}
 	}
 
 
 	if (sync_kconfig) {
 	if (sync_kconfig) {
-		if (conf_get_changed()) {
-			name = getenv("KCONFIG_NOSILENTUPDATE");
-			if (name && *name) {
+		name = getenv("KCONFIG_NOSILENTUPDATE");
+		if (name && *name) {
+			if (conf_get_changed()) {
 				fprintf(stderr,
 				fprintf(stderr,
 					"\n*** The configuration requires explicit update.\n\n");
 					"\n*** The configuration requires explicit update.\n\n");
 				return 1;
 				return 1;
 			}
 			}
+			no_conf_write = 1;
 		}
 		}
 	}
 	}
 
 
@@ -684,29 +686,32 @@ int main(int ac, char **av)
 		break;
 		break;
 	}
 	}
 
 
-	if (sync_kconfig) {
-		/* syncconfig is used during the build so we shall update autoconf.
-		 * All other commands are only used to generate a config.
-		 */
-		if (conf_get_changed() && conf_write(NULL)) {
-			fprintf(stderr, "\n*** Error during writing of the configuration.\n\n");
-			exit(1);
-		}
-		if (conf_write_autoconf()) {
-			fprintf(stderr, "\n*** Error during update of the configuration.\n\n");
-			return 1;
-		}
-	} else if (input_mode == savedefconfig) {
+	if (input_mode == savedefconfig) {
 		if (conf_write_defconfig(defconfig_file)) {
 		if (conf_write_defconfig(defconfig_file)) {
 			fprintf(stderr, "n*** Error while saving defconfig to: %s\n\n",
 			fprintf(stderr, "n*** Error while saving defconfig to: %s\n\n",
 				defconfig_file);
 				defconfig_file);
 			return 1;
 			return 1;
 		}
 		}
 	} else if (input_mode != listnewconfig) {
 	} else if (input_mode != listnewconfig) {
-		if (conf_write(NULL)) {
+		if (!no_conf_write && conf_write(NULL)) {
 			fprintf(stderr, "\n*** Error during writing of the configuration.\n\n");
 			fprintf(stderr, "\n*** Error during writing of the configuration.\n\n");
 			exit(1);
 			exit(1);
 		}
 		}
+
+		/*
+		 * Create auto.conf if it does not exist.
+		 * This prevents GNU Make 4.1 or older from emitting
+		 * "include/config/auto.conf: No such file or directory"
+		 * in the top-level Makefile
+		 *
+		 * syncconfig always creates or updates auto.conf because it is
+		 * used during the build.
+		 */
+		if (conf_write_autoconf(sync_kconfig) && sync_kconfig) {
+			fprintf(stderr,
+				"\n*** Error during sync of the configuration.\n\n");
+			return 1;
+		}
 	}
 	}
 	return 0;
 	return 0;
 }
 }

+ 127 - 29
scripts/kconfig/confdata.c

@@ -16,6 +16,64 @@
 
 
 #include "lkc.h"
 #include "lkc.h"
 
 
+/* return true if 'path' exists, false otherwise */
+static bool is_present(const char *path)
+{
+	struct stat st;
+
+	return !stat(path, &st);
+}
+
+/* return true if 'path' exists and it is a directory, false otherwise */
+static bool is_dir(const char *path)
+{
+	struct stat st;
+
+	if (stat(path, &st))
+		return 0;
+
+	return S_ISDIR(st.st_mode);
+}
+
+/*
+ * Create the parent directory of the given path.
+ *
+ * For example, if 'include/config/auto.conf' is given, create 'include/config'.
+ */
+static int make_parent_dir(const char *path)
+{
+	char tmp[PATH_MAX + 1];
+	char *p;
+
+	strncpy(tmp, path, sizeof(tmp));
+	tmp[sizeof(tmp) - 1] = 0;
+
+	/* Remove the base name. Just return if nothing is left */
+	p = strrchr(tmp, '/');
+	if (!p)
+		return 0;
+	*(p + 1) = 0;
+
+	/* Just in case it is an absolute path */
+	p = tmp;
+	while (*p == '/')
+		p++;
+
+	while ((p = strchr(p, '/'))) {
+		*p = 0;
+
+		/* skip if the directory exists */
+		if (!is_dir(tmp) && mkdir(tmp, 0755))
+			return -1;
+
+		*p = '/';
+		while (*p == '/')
+			p++;
+	}
+
+	return 0;
+}
+
 struct conf_printer {
 struct conf_printer {
 	void (*print_symbol)(FILE *, struct symbol *, const char *, void *);
 	void (*print_symbol)(FILE *, struct symbol *, const char *, void *);
 	void (*print_comment)(FILE *, const char *, void *);
 	void (*print_comment)(FILE *, const char *, void *);
@@ -43,16 +101,16 @@ static void conf_warning(const char *fmt, ...)
 	conf_warnings++;
 	conf_warnings++;
 }
 }
 
 
-static void conf_default_message_callback(const char *fmt, va_list ap)
+static void conf_default_message_callback(const char *s)
 {
 {
 	printf("#\n# ");
 	printf("#\n# ");
-	vprintf(fmt, ap);
+	printf("%s", s);
 	printf("\n#\n");
 	printf("\n#\n");
 }
 }
 
 
-static void (*conf_message_callback) (const char *fmt, va_list ap) =
+static void (*conf_message_callback)(const char *s) =
 	conf_default_message_callback;
 	conf_default_message_callback;
-void conf_set_message_callback(void (*fn) (const char *fmt, va_list ap))
+void conf_set_message_callback(void (*fn)(const char *s))
 {
 {
 	conf_message_callback = fn;
 	conf_message_callback = fn;
 }
 }
@@ -60,10 +118,15 @@ void conf_set_message_callback(void (*fn) (const char *fmt, va_list ap))
 static void conf_message(const char *fmt, ...)
 static void conf_message(const char *fmt, ...)
 {
 {
 	va_list ap;
 	va_list ap;
+	char buf[4096];
+
+	if (!conf_message_callback)
+		return;
 
 
 	va_start(ap, fmt);
 	va_start(ap, fmt);
-	if (conf_message_callback)
-		conf_message_callback(fmt, ap);
+
+	vsnprintf(buf, sizeof(buf), fmt, ap);
+	conf_message_callback(buf);
 	va_end(ap);
 	va_end(ap);
 }
 }
 
 
@@ -83,7 +146,6 @@ const char *conf_get_autoconfig_name(void)
 
 
 char *conf_get_default_confname(void)
 char *conf_get_default_confname(void)
 {
 {
-	struct stat buf;
 	static char fullname[PATH_MAX+1];
 	static char fullname[PATH_MAX+1];
 	char *env, *name;
 	char *env, *name;
 
 
@@ -91,7 +153,7 @@ char *conf_get_default_confname(void)
 	env = getenv(SRCTREE);
 	env = getenv(SRCTREE);
 	if (env) {
 	if (env) {
 		sprintf(fullname, "%s/%s", env, name);
 		sprintf(fullname, "%s/%s", env, name);
-		if (!stat(fullname, &buf))
+		if (is_present(fullname))
 			return fullname;
 			return fullname;
 	}
 	}
 	return name;
 	return name;
@@ -397,7 +459,7 @@ int conf_read(const char *name)
 
 
 	for_all_symbols(i, sym) {
 	for_all_symbols(i, sym) {
 		sym_calc_value(sym);
 		sym_calc_value(sym);
-		if (sym_is_choice(sym) || (sym->flags & SYMBOL_AUTO))
+		if (sym_is_choice(sym) || (sym->flags & SYMBOL_NO_WRITE))
 			continue;
 			continue;
 		if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) {
 		if (sym_has_value(sym) && (sym->flags & SYMBOL_WRITE)) {
 			/* check that calculated value agrees with saved value */
 			/* check that calculated value agrees with saved value */
@@ -725,10 +787,9 @@ int conf_write(const char *name)
 
 
 	dirname[0] = 0;
 	dirname[0] = 0;
 	if (name && name[0]) {
 	if (name && name[0]) {
-		struct stat st;
 		char *slash;
 		char *slash;
 
 
-		if (!stat(name, &st) && S_ISDIR(st.st_mode)) {
+		if (is_dir(name)) {
 			strcpy(dirname, name);
 			strcpy(dirname, name);
 			strcat(dirname, "/");
 			strcat(dirname, "/");
 			basename = conf_get_configname();
 			basename = conf_get_configname();
@@ -813,26 +874,59 @@ next:
 	return 0;
 	return 0;
 }
 }
 
 
+/* write a dependency file as used by kbuild to track dependencies */
+static int conf_write_dep(const char *name)
+{
+	struct file *file;
+	FILE *out;
+
+	if (!name)
+		name = ".kconfig.d";
+	out = fopen("..config.tmp", "w");
+	if (!out)
+		return 1;
+	fprintf(out, "deps_config := \\\n");
+	for (file = file_list; file; file = file->next) {
+		if (file->next)
+			fprintf(out, "\t%s \\\n", file->name);
+		else
+			fprintf(out, "\t%s\n", file->name);
+	}
+	fprintf(out, "\n%s: \\\n"
+		     "\t$(deps_config)\n\n", conf_get_autoconfig_name());
+
+	env_write_dep(out, conf_get_autoconfig_name());
+
+	fprintf(out, "\n$(deps_config): ;\n");
+	fclose(out);
+
+	if (make_parent_dir(name))
+		return 1;
+	rename("..config.tmp", name);
+	return 0;
+}
+
 static int conf_split_config(void)
 static int conf_split_config(void)
 {
 {
 	const char *name;
 	const char *name;
 	char path[PATH_MAX+1];
 	char path[PATH_MAX+1];
 	char *s, *d, c;
 	char *s, *d, c;
 	struct symbol *sym;
 	struct symbol *sym;
-	struct stat sb;
 	int res, i, fd;
 	int res, i, fd;
 
 
 	name = conf_get_autoconfig_name();
 	name = conf_get_autoconfig_name();
 	conf_read_simple(name, S_DEF_AUTO);
 	conf_read_simple(name, S_DEF_AUTO);
 	sym_calc_value(modules_sym);
 	sym_calc_value(modules_sym);
 
 
+	if (make_parent_dir("include/config/foo.h"))
+		return 1;
 	if (chdir("include/config"))
 	if (chdir("include/config"))
 		return 1;
 		return 1;
 
 
 	res = 0;
 	res = 0;
 	for_all_symbols(i, sym) {
 	for_all_symbols(i, sym) {
 		sym_calc_value(sym);
 		sym_calc_value(sym);
-		if ((sym->flags & SYMBOL_AUTO) || !sym->name)
+		if ((sym->flags & SYMBOL_NO_WRITE) || !sym->name)
 			continue;
 			continue;
 		if (sym->flags & SYMBOL_WRITE) {
 		if (sym->flags & SYMBOL_WRITE) {
 			if (sym->flags & SYMBOL_DEF_AUTO) {
 			if (sym->flags & SYMBOL_DEF_AUTO) {
@@ -897,19 +991,12 @@ static int conf_split_config(void)
 				res = 1;
 				res = 1;
 				break;
 				break;
 			}
 			}
-			/*
-			 * Create directory components,
-			 * unless they exist already.
-			 */
-			d = path;
-			while ((d = strchr(d, '/'))) {
-				*d = 0;
-				if (stat(path, &sb) && mkdir(path, 0755)) {
-					res = 1;
-					goto out;
-				}
-				*d++ = '/';
+
+			if (make_parent_dir(path)) {
+				res = 1;
+				goto out;
 			}
 			}
+
 			/* Try it again. */
 			/* Try it again. */
 			fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
 			fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
 			if (fd == -1) {
 			if (fd == -1) {
@@ -926,16 +1013,20 @@ out:
 	return res;
 	return res;
 }
 }
 
 
-int conf_write_autoconf(void)
+int conf_write_autoconf(int overwrite)
 {
 {
 	struct symbol *sym;
 	struct symbol *sym;
 	const char *name;
 	const char *name;
+	const char *autoconf_name = conf_get_autoconfig_name();
 	FILE *out, *tristate, *out_h;
 	FILE *out, *tristate, *out_h;
 	int i;
 	int i;
 
 
+	if (!overwrite && is_present(autoconf_name))
+		return 0;
+
 	sym_clear_all_valid();
 	sym_clear_all_valid();
 
 
-	file_write_dep("include/config/auto.conf.cmd");
+	conf_write_dep("include/config/auto.conf.cmd");
 
 
 	if (conf_split_config())
 	if (conf_split_config())
 		return 1;
 		return 1;
@@ -982,19 +1073,26 @@ int conf_write_autoconf(void)
 	name = getenv("KCONFIG_AUTOHEADER");
 	name = getenv("KCONFIG_AUTOHEADER");
 	if (!name)
 	if (!name)
 		name = "include/generated/autoconf.h";
 		name = "include/generated/autoconf.h";
+	if (make_parent_dir(name))
+		return 1;
 	if (rename(".tmpconfig.h", name))
 	if (rename(".tmpconfig.h", name))
 		return 1;
 		return 1;
+
 	name = getenv("KCONFIG_TRISTATE");
 	name = getenv("KCONFIG_TRISTATE");
 	if (!name)
 	if (!name)
 		name = "include/config/tristate.conf";
 		name = "include/config/tristate.conf";
+	if (make_parent_dir(name))
+		return 1;
 	if (rename(".tmpconfig_tristate", name))
 	if (rename(".tmpconfig_tristate", name))
 		return 1;
 		return 1;
-	name = conf_get_autoconfig_name();
+
+	if (make_parent_dir(autoconf_name))
+		return 1;
 	/*
 	/*
 	 * This must be the last step, kbuild has a dependency on auto.conf
 	 * This must be the last step, kbuild has a dependency on auto.conf
 	 * and this marks the successful completion of the previous steps.
 	 * and this marks the successful completion of the previous steps.
 	 */
 	 */
-	if (rename(".tmpconfig", name))
+	if (rename(".tmpconfig", autoconf_name))
 		return 1;
 		return 1;
 
 
 	return 0;
 	return 0;

+ 1 - 2
scripts/kconfig/expr.h

@@ -141,7 +141,7 @@ struct symbol {
 #define SYMBOL_OPTIONAL   0x0100  /* choice is optional - values can be 'n' */
 #define SYMBOL_OPTIONAL   0x0100  /* choice is optional - values can be 'n' */
 #define SYMBOL_WRITE      0x0200  /* write symbol to file (KCONFIG_CONFIG) */
 #define SYMBOL_WRITE      0x0200  /* write symbol to file (KCONFIG_CONFIG) */
 #define SYMBOL_CHANGED    0x0400  /* ? */
 #define SYMBOL_CHANGED    0x0400  /* ? */
-#define SYMBOL_AUTO       0x1000  /* value from environment variable */
+#define SYMBOL_NO_WRITE   0x1000  /* Symbol for internal use only; it will not be written */
 #define SYMBOL_CHECKED    0x2000  /* used during dependency checking */
 #define SYMBOL_CHECKED    0x2000  /* used during dependency checking */
 #define SYMBOL_WARNED     0x8000  /* warning has been issued */
 #define SYMBOL_WARNED     0x8000  /* warning has been issued */
 
 
@@ -185,7 +185,6 @@ enum prop_type {
 	P_SELECT,   /* select BAR */
 	P_SELECT,   /* select BAR */
 	P_IMPLY,    /* imply BAR */
 	P_IMPLY,    /* imply BAR */
 	P_RANGE,    /* range 7..100 (for a symbol) */
 	P_RANGE,    /* range 7..100 (for a symbol) */
-	P_ENV,      /* value from environment variable */
 	P_SYMBOL,   /* where a symbol is defined */
 	P_SYMBOL,   /* where a symbol is defined */
 };
 };
 
 

+ 3 - 2
scripts/kconfig/gconf.c

@@ -101,8 +101,8 @@ const char *dbg_sym_flags(int val)
 		strcat(buf, "write/");
 		strcat(buf, "write/");
 	if (val & SYMBOL_CHANGED)
 	if (val & SYMBOL_CHANGED)
 		strcat(buf, "changed/");
 		strcat(buf, "changed/");
-	if (val & SYMBOL_AUTO)
-		strcat(buf, "auto/");
+	if (val & SYMBOL_NO_WRITE)
+		strcat(buf, "no_write/");
 
 
 	buf[strlen(buf) - 1] = '\0';
 	buf[strlen(buf) - 1] = '\0';
 
 
@@ -525,6 +525,7 @@ void on_save_activate(GtkMenuItem * menuitem, gpointer user_data)
 {
 {
 	if (conf_write(NULL))
 	if (conf_write(NULL))
 		text_insert_msg("Error", "Unable to save configuration !");
 		text_insert_msg("Error", "Unable to save configuration !");
+	conf_write_autoconf(0);
 }
 }
 
 
 
 

+ 0 - 2
scripts/kconfig/lkc.h

@@ -97,7 +97,6 @@ void menu_set_type(int type);
 
 
 /* util.c */
 /* util.c */
 struct file *file_lookup(const char *name);
 struct file *file_lookup(const char *name);
-int file_write_dep(const char *name);
 void *xmalloc(size_t size);
 void *xmalloc(size_t size);
 void *xcalloc(size_t nmemb, size_t size);
 void *xcalloc(size_t nmemb, size_t size);
 void *xrealloc(void *p, size_t size);
 void *xrealloc(void *p, size_t size);
@@ -126,7 +125,6 @@ const char *sym_get_string_default(struct symbol *sym);
 struct symbol *sym_check_deps(struct symbol *sym);
 struct symbol *sym_check_deps(struct symbol *sym);
 struct property *prop_alloc(enum prop_type type, struct symbol *sym);
 struct property *prop_alloc(enum prop_type type, struct symbol *sym);
 struct symbol *prop_get_symbol(struct property *prop);
 struct symbol *prop_get_symbol(struct property *prop);
-struct property *sym_get_env_prop(struct symbol *sym);
 
 
 static inline tristate sym_get_tristate_value(struct symbol *sym)
 static inline tristate sym_get_tristate_value(struct symbol *sym)
 {
 {

+ 2 - 2
scripts/kconfig/lkc_proto.h

@@ -7,10 +7,10 @@ int conf_read(const char *name);
 int conf_read_simple(const char *name, int);
 int conf_read_simple(const char *name, int);
 int conf_write_defconfig(const char *name);
 int conf_write_defconfig(const char *name);
 int conf_write(const char *name);
 int conf_write(const char *name);
-int conf_write_autoconf(void);
+int conf_write_autoconf(int overwrite);
 bool conf_get_changed(void);
 bool conf_get_changed(void);
 void conf_set_changed_callback(void (*fn)(void));
 void conf_set_changed_callback(void (*fn)(void));
-void conf_set_message_callback(void (*fn)(const char *fmt, va_list ap));
+void conf_set_message_callback(void (*fn)(const char *s));
 
 
 /* menu.c */
 /* menu.c */
 extern struct menu rootmenu;
 extern struct menu rootmenu;

+ 4 - 6
scripts/kconfig/mconf.c

@@ -772,16 +772,13 @@ static void show_helptext(const char *title, const char *text)
 	show_textbox(title, text, 0, 0);
 	show_textbox(title, text, 0, 0);
 }
 }
 
 
-static void conf_message_callback(const char *fmt, va_list ap)
+static void conf_message_callback(const char *s)
 {
 {
-	char buf[PATH_MAX+1];
-
-	vsnprintf(buf, sizeof(buf), fmt, ap);
 	if (save_and_exit) {
 	if (save_and_exit) {
 		if (!silent)
 		if (!silent)
-			printf("%s", buf);
+			printf("%s", s);
 	} else {
 	} else {
-		show_textbox(NULL, buf, 6, 60);
+		show_textbox(NULL, s, 6, 60);
 	}
 	}
 }
 }
 
 
@@ -977,6 +974,7 @@ static int handle_exit(void)
 					  "\n\n");
 					  "\n\n");
 			return 1;
 			return 1;
 		}
 		}
+		conf_write_autoconf(0);
 		/* fall through */
 		/* fall through */
 	case -1:
 	case -1:
 		if (!silent)
 		if (!silent)

+ 1 - 1
scripts/kconfig/menu.c

@@ -212,7 +212,7 @@ void menu_add_option(int token, char *arg)
 			sym_defconfig_list = current_entry->sym;
 			sym_defconfig_list = current_entry->sym;
 		else if (sym_defconfig_list != current_entry->sym)
 		else if (sym_defconfig_list != current_entry->sym)
 			zconf_error("trying to redefine defconfig symbol");
 			zconf_error("trying to redefine defconfig symbol");
-		sym_defconfig_list->flags |= SYMBOL_AUTO;
+		sym_defconfig_list->flags |= SYMBOL_NO_WRITE;
 		break;
 		break;
 	case T_OPT_ALLNOCONFIG_Y:
 	case T_OPT_ALLNOCONFIG_Y:
 		current_entry->sym->flags |= SYMBOL_ALLNOCONFIG_Y;
 		current_entry->sym->flags |= SYMBOL_ALLNOCONFIG_Y;

+ 3 - 5
scripts/kconfig/nconf.c

@@ -674,6 +674,7 @@ static int do_exit(void)
 				  "Your configuration changes were NOT saved.",
 				  "Your configuration changes were NOT saved.",
 				  1,
 				  1,
 				  "<OK>");
 				  "<OK>");
+		conf_write_autoconf(0);
 		break;
 		break;
 	default:
 	default:
 		btn_dialog(
 		btn_dialog(
@@ -1210,12 +1211,9 @@ static void conf(struct menu *menu)
 	}
 	}
 }
 }
 
 
-static void conf_message_callback(const char *fmt, va_list ap)
+static void conf_message_callback(const char *s)
 {
 {
-	char buf[1024];
-
-	vsnprintf(buf, sizeof(buf), fmt, ap);
-	btn_dialog(main_window, buf, 1, "<OK>");
+	btn_dialog(main_window, s, 1, "<OK>");
 }
 }
 
 
 static void show_help(struct menu *menu)
 static void show_help(struct menu *menu)

+ 2 - 1
scripts/kconfig/qconf.cc

@@ -1149,7 +1149,6 @@ QString ConfigInfoView::debug_info(struct symbol *sym)
 		case P_DEFAULT:
 		case P_DEFAULT:
 		case P_SELECT:
 		case P_SELECT:
 		case P_RANGE:
 		case P_RANGE:
-		case P_ENV:
 			debug += prop_get_type_name(prop->type);
 			debug += prop_get_type_name(prop->type);
 			debug += ": ";
 			debug += ": ";
 			expr_print(prop->expr, expr_print_help, &debug, E_NONE);
 			expr_print(prop->expr, expr_print_help, &debug, E_NONE);
@@ -1535,6 +1534,8 @@ bool ConfigMainWindow::saveConfig(void)
 		QMessageBox::information(this, "qconf", "Unable to save configuration!");
 		QMessageBox::information(this, "qconf", "Unable to save configuration!");
 		return false;
 		return false;
 	}
 	}
+	conf_write_autoconf(0);
+
 	return true;
 	return true;
 }
 }
 
 

+ 1 - 12
scripts/kconfig/symbol.c

@@ -76,15 +76,6 @@ struct property *sym_get_choice_prop(struct symbol *sym)
 	return NULL;
 	return NULL;
 }
 }
 
 
-struct property *sym_get_env_prop(struct symbol *sym)
-{
-	struct property *prop;
-
-	for_all_properties(sym, prop, P_ENV)
-		return prop;
-	return NULL;
-}
-
 static struct property *sym_get_default_prop(struct symbol *sym)
 static struct property *sym_get_default_prop(struct symbol *sym)
 {
 {
 	struct property *prop;
 	struct property *prop;
@@ -463,7 +454,7 @@ void sym_calc_value(struct symbol *sym)
 		}
 		}
 	}
 	}
 
 
-	if (sym->flags & SYMBOL_AUTO)
+	if (sym->flags & SYMBOL_NO_WRITE)
 		sym->flags &= ~SYMBOL_WRITE;
 		sym->flags &= ~SYMBOL_WRITE;
 
 
 	if (sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES)
 	if (sym->flags & SYMBOL_NEED_SET_CHOICE_VALUES)
@@ -1298,8 +1289,6 @@ const char *prop_get_type_name(enum prop_type type)
 	switch (type) {
 	switch (type) {
 	case P_PROMPT:
 	case P_PROMPT:
 		return "prompt";
 		return "prompt";
-	case P_ENV:
-		return "env";
 	case P_COMMENT:
 	case P_COMMENT:
 		return "comment";
 		return "comment";
 	case P_MENU:
 	case P_MENU:

+ 0 - 30
scripts/kconfig/util.c

@@ -29,36 +29,6 @@ struct file *file_lookup(const char *name)
 	return file;
 	return file;
 }
 }
 
 
-/* write a dependency file as used by kbuild to track dependencies */
-int file_write_dep(const char *name)
-{
-	struct file *file;
-	FILE *out;
-
-	if (!name)
-		name = ".kconfig.d";
-	out = fopen("..config.tmp", "w");
-	if (!out)
-		return 1;
-	fprintf(out, "deps_config := \\\n");
-	for (file = file_list; file; file = file->next) {
-		if (file->next)
-			fprintf(out, "\t%s \\\n", file->name);
-		else
-			fprintf(out, "\t%s\n", file->name);
-	}
-	fprintf(out, "\n%s: \\\n"
-		     "\t$(deps_config)\n\n", conf_get_autoconfig_name());
-
-	env_write_dep(out, conf_get_autoconfig_name());
-
-	fprintf(out, "\n$(deps_config): ;\n");
-	fclose(out);
-	rename("..config.tmp", name);
-	return 0;
-}
-
-
 /* Allocate initial growable string */
 /* Allocate initial growable string */
 struct gstr str_new(void)
 struct gstr str_new(void)
 {
 {

+ 3 - 3
scripts/kconfig/zconf.y

@@ -31,7 +31,7 @@ struct symbol *symbol_hash[SYMBOL_HASHSIZE];
 static struct menu *current_menu, *current_entry;
 static struct menu *current_menu, *current_entry;
 
 
 %}
 %}
-%expect 31
+%expect 30
 
 
 %union
 %union
 {
 {
@@ -117,7 +117,7 @@ start: mainmenu_stmt stmt_list | stmt_list;
 
 
 /* mainmenu entry */
 /* mainmenu entry */
 
 
-mainmenu_stmt: T_MAINMENU prompt nl
+mainmenu_stmt: T_MAINMENU prompt T_EOL
 {
 {
 	menu_add_prompt(P_MENU, $2, NULL);
 	menu_add_prompt(P_MENU, $2, NULL);
 };
 };
@@ -265,7 +265,7 @@ symbol_option_arg:
 choice: T_CHOICE word_opt T_EOL
 choice: T_CHOICE word_opt T_EOL
 {
 {
 	struct symbol *sym = sym_lookup($2, SYMBOL_CHOICE);
 	struct symbol *sym = sym_lookup($2, SYMBOL_CHOICE);
-	sym->flags |= SYMBOL_AUTO;
+	sym->flags |= SYMBOL_NO_WRITE;
 	menu_add_entry(sym);
 	menu_add_entry(sym);
 	menu_add_expr(P_CHOICE, NULL, NULL);
 	menu_add_expr(P_CHOICE, NULL, NULL);
 	free($2);
 	free($2);