Commit 7cf3d73b4360e91b14326632ab1aeda4cb26308d

Authored by Sam Ravnborg
Committed by Michal Marek
1 parent 49192f266f

kconfig: add savedefconfig

savedefconfig will save a minimal config to a file
named "defconfig".

The config symbols are saved in the same order as
they appear in the menu structure so it should
be possible to map them to the relevant menus
if desired.

The implementation was tested against several minimal
configs for arm which was created using brute-force.

There was one regression related to default numbers
which had their valid range further limited by another symbol.

Sample:

config FOO
	int "foo"
	default 4

config BAR
	int "bar"
	range 0 FOO

If FOO is set to 3 then BAR cannot take a value higher than 3.
But the current implementation will set BAR equal to 4.

This is seldomly used and the final configuration is OK,
and the fix was non-trivial.
So it was documented in the code and left as is.

Signed-off-by: Sam Ravnborg <sam@ravnborg.org>
Acked-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
Signed-off-by: Michal Marek <mmarek@suse.cz>

Showing 6 changed files with 171 additions and 1 deletions Side-by-side Diff

scripts/kconfig/Makefile
... ... @@ -90,11 +90,14 @@
90 90 allnoconfig allyesconfig allmodconfig alldefconfig randconfig: $(obj)/conf
91 91 $< --$@ $(Kconfig)
92 92  
93   -PHONY += listnewconfig oldnoconfig defconfig
  93 +PHONY += listnewconfig oldnoconfig savedefconfig defconfig
94 94  
95 95 listnewconfig oldnoconfig: $(obj)/conf
96 96 $< --$@ $(Kconfig)
97 97  
  98 +savedefconfig: $(obj)/conf
  99 + $< --$@=defconfig $(Kconfig)
  100 +
98 101 defconfig: $(obj)/conf
99 102 ifeq ($(KBUILD_DEFCONFIG),)
100 103 $< --defconfig $(Kconfig)
... ... @@ -118,6 +121,7 @@
118 121 @echo ' localyesconfig - Update current config converting local mods to core'
119 122 @echo ' silentoldconfig - Same as oldconfig, but quietly, additionally update deps'
120 123 @echo ' defconfig - New config with default from ARCH supplied defconfig'
  124 + @echo ' savedefconfig - Save current config as ./defconfig (minimal config)'
121 125 @echo ' allnoconfig - New config where all options are answered with no'
122 126 @echo ' allyesconfig - New config where all options are accepted with yes'
123 127 @echo ' allmodconfig - New config selecting modules when possible'
scripts/kconfig/conf.c
... ... @@ -30,6 +30,7 @@
30 30 alldefconfig,
31 31 randconfig,
32 32 defconfig,
  33 + savedefconfig,
33 34 listnewconfig,
34 35 oldnoconfig,
35 36 } input_mode = oldaskconfig;
... ... @@ -444,6 +445,7 @@
444 445 {"oldconfig", no_argument, NULL, oldconfig},
445 446 {"silentoldconfig", no_argument, NULL, silentoldconfig},
446 447 {"defconfig", optional_argument, NULL, defconfig},
  448 + {"savedefconfig", required_argument, NULL, savedefconfig},
447 449 {"allnoconfig", no_argument, NULL, allnoconfig},
448 450 {"allyesconfig", no_argument, NULL, allyesconfig},
449 451 {"allmodconfig", no_argument, NULL, allmodconfig},
... ... @@ -471,6 +473,7 @@
471 473 sync_kconfig = 1;
472 474 break;
473 475 case defconfig:
  476 + case savedefconfig:
474 477 defconfig_file = optarg;
475 478 break;
476 479 case randconfig:
... ... @@ -526,6 +529,9 @@
526 529 exit(1);
527 530 }
528 531 break;
  532 + case savedefconfig:
  533 + conf_read(NULL);
  534 + break;
529 535 case silentoldconfig:
530 536 case oldaskconfig:
531 537 case oldconfig:
... ... @@ -591,6 +597,8 @@
591 597 case defconfig:
592 598 conf_set_all_new_symbols(def_default);
593 599 break;
  600 + case savedefconfig:
  601 + break;
594 602 case oldconfig:
595 603 case oldaskconfig:
596 604 rootEntry = &rootmenu;
... ... @@ -620,6 +628,12 @@
620 628 }
621 629 if (conf_write_autoconf()) {
622 630 fprintf(stderr, _("\n*** Error during update of the kernel configuration.\n\n"));
  631 + return 1;
  632 + }
  633 + } else if (input_mode == savedefconfig) {
  634 + if (conf_write_defconfig(defconfig_file)) {
  635 + fprintf(stderr, _("n*** Error while saving defconfig to: %s\n\n"),
  636 + defconfig_file);
623 637 return 1;
624 638 }
625 639 } else if (input_mode != listnewconfig) {
scripts/kconfig/confdata.c
... ... @@ -457,6 +457,82 @@
457 457 }
458 458 }
459 459  
  460 +/*
  461 + * Write out a minimal config.
  462 + * All values that has default values are skipped as this is redundant.
  463 + */
  464 +int conf_write_defconfig(const char *filename)
  465 +{
  466 + struct symbol *sym;
  467 + struct menu *menu;
  468 + FILE *out;
  469 +
  470 + out = fopen(filename, "w");
  471 + if (!out)
  472 + return 1;
  473 +
  474 + sym_clear_all_valid();
  475 +
  476 + /* Traverse all menus to find all relevant symbols */
  477 + menu = rootmenu.list;
  478 +
  479 + while (menu != NULL)
  480 + {
  481 + sym = menu->sym;
  482 + if (sym == NULL) {
  483 + if (!menu_is_visible(menu))
  484 + goto next_menu;
  485 + } else if (!sym_is_choice(sym)) {
  486 + sym_calc_value(sym);
  487 + if (!(sym->flags & SYMBOL_WRITE))
  488 + goto next_menu;
  489 + sym->flags &= ~SYMBOL_WRITE;
  490 + /* If we cannot change the symbol - skip */
  491 + if (!sym_is_changable(sym))
  492 + goto next_menu;
  493 + /* If symbol equals to default value - skip */
  494 + if (strcmp(sym_get_string_value(sym), sym_get_string_default(sym)) == 0)
  495 + goto next_menu;
  496 +
  497 + /*
  498 + * If symbol is a choice value and equals to the
  499 + * default for a choice - skip.
  500 + * But only if value equal to "y".
  501 + */
  502 + if (sym_is_choice_value(sym)) {
  503 + struct symbol *cs;
  504 + struct symbol *ds;
  505 +
  506 + cs = prop_get_symbol(sym_get_choice_prop(sym));
  507 + ds = sym_choice_default(cs);
  508 + if (sym == ds) {
  509 + if ((sym->type == S_BOOLEAN ||
  510 + sym->type == S_TRISTATE) &&
  511 + sym_get_tristate_value(sym) == yes)
  512 + goto next_menu;
  513 + }
  514 + }
  515 + conf_write_symbol(sym, sym->type, out, true);
  516 + }
  517 +next_menu:
  518 + if (menu->list != NULL) {
  519 + menu = menu->list;
  520 + }
  521 + else if (menu->next != NULL) {
  522 + menu = menu->next;
  523 + } else {
  524 + while ((menu = menu->parent)) {
  525 + if (menu->next != NULL) {
  526 + menu = menu->next;
  527 + break;
  528 + }
  529 + }
  530 + }
  531 + }
  532 + fclose(out);
  533 + return 0;
  534 +}
  535 +
460 536 int conf_write(const char *name)
461 537 {
462 538 FILE *out;
scripts/kconfig/lkc.h
... ... @@ -127,6 +127,7 @@
127 127 void sym_set_all_changed(void);
128 128 void sym_set_changed(struct symbol *sym);
129 129 struct symbol *sym_choice_default(struct symbol *sym);
  130 +const char *sym_get_string_default(struct symbol *sym);
130 131 struct symbol *sym_check_deps(struct symbol *sym);
131 132 struct property *prop_alloc(enum prop_type type, struct symbol *sym);
132 133 struct symbol *prop_get_symbol(struct property *prop);
scripts/kconfig/lkc_proto.h
... ... @@ -3,6 +3,7 @@
3 3 P(conf_parse,void,(const char *name));
4 4 P(conf_read,int,(const char *name));
5 5 P(conf_read_simple,int,(const char *name, int));
  6 +P(conf_write_defconfig,int,(const char *name));
6 7 P(conf_write,int,(const char *name));
7 8 P(conf_write_autoconf,int,(void));
8 9 P(conf_get_changed,bool,(void));
scripts/kconfig/symbol.c
... ... @@ -661,6 +661,80 @@
661 661 return true;
662 662 }
663 663  
  664 +/*
  665 + * Find the default value associated to a symbol.
  666 + * For tristate symbol handle the modules=n case
  667 + * in which case "m" becomes "y".
  668 + * If the symbol does not have any default then fallback
  669 + * to the fixed default values.
  670 + */
  671 +const char *sym_get_string_default(struct symbol *sym)
  672 +{
  673 + struct property *prop;
  674 + struct symbol *ds;
  675 + const char *str;
  676 + tristate val;
  677 +
  678 + sym_calc_visibility(sym);
  679 + sym_calc_value(modules_sym);
  680 + val = symbol_no.curr.tri;
  681 + str = symbol_empty.curr.val;
  682 +
  683 + /* If symbol has a default value look it up */
  684 + prop = sym_get_default_prop(sym);
  685 + if (prop != NULL) {
  686 + switch (sym->type) {
  687 + case S_BOOLEAN:
  688 + case S_TRISTATE:
  689 + /* The visibility imay limit the value from yes => mod */
  690 + val = EXPR_AND(expr_calc_value(prop->expr), prop->visible.tri);
  691 + break;
  692 + default:
  693 + /*
  694 + * The following fails to handle the situation
  695 + * where a default value is further limited by
  696 + * the valid range.
  697 + */
  698 + ds = prop_get_symbol(prop);
  699 + if (ds != NULL) {
  700 + sym_calc_value(ds);
  701 + str = (const char *)ds->curr.val;
  702 + }
  703 + }
  704 + }
  705 +
  706 + /* Handle select statements */
  707 + val = EXPR_OR(val, sym->rev_dep.tri);
  708 +
  709 + /* transpose mod to yes if modules are not enabled */
  710 + if (val == mod)
  711 + if (!sym_is_choice_value(sym) && modules_sym->curr.tri == no)
  712 + val = yes;
  713 +
  714 + /* transpose mod to yes if type is bool */
  715 + if (sym->type == S_BOOLEAN && val == mod)
  716 + val = yes;
  717 +
  718 + switch (sym->type) {
  719 + case S_BOOLEAN:
  720 + case S_TRISTATE:
  721 + switch (val) {
  722 + case no: return "n";
  723 + case mod: return "m";
  724 + case yes: return "y";
  725 + }
  726 + case S_INT:
  727 + case S_HEX:
  728 + return str;
  729 + case S_STRING:
  730 + return str;
  731 + case S_OTHER:
  732 + case S_UNKNOWN:
  733 + break;
  734 + }
  735 + return "";
  736 +}
  737 +
664 738 const char *sym_get_string_value(struct symbol *sym)
665 739 {
666 740 tristate val;