Message ID | 20180622192739.5327-4-dirk@gouders.net (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
2018-06-23 4:27 GMT+09:00 Dirk Gouders <dirk@gouders.net>: > Currently, we need to modify existing kconfig targets to generate debugging > information from the parser. That information then has to be filtered > somehow, automated tests are at least complicated to implement. > > Add a debugconfig target for pure debugging purposes; the initial > version of this target dumps the menu tree and with the --debug option > activates the parsers debugging output via it's global variable > cdebug. The environment variable ZCONF_DEBUG can be used to generate > even more detailed debugging information. > > Sample output for a simple Kconfig file: > > $ scripts/kconfig/dconf --debug Kconfig.dconfig > Kconfig.dconfig:1:config a > Kconfig.dconfig:2:type(1) > Kconfig.dconfig:4:endconfig > Kconfig.dconfig:5:if > Kconfig.dconfig:5:config b > Kconfig.dconfig:6:type(1) > Kconfig.dconfig:7:endconfig > Kconfig.dconfig:7:endif > > config a > bool > symbol a > prompt "a" > > config b > bool > symbol b > prompt "b" if a > > endmenu > > Signed-off-by: Dirk Gouders <dirk@gouders.net> > Cc: Sam Ravnborg <sam@ravnborg.org> > --- > scripts/kconfig/Makefile | 10 ++++++++- > scripts/kconfig/dconf.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++ > 2 files changed, 64 insertions(+), 1 deletion(-) > create mode 100644 scripts/kconfig/dconf.c > > diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile > index a3ac2c91331c..19906ff25392 100644 > --- a/scripts/kconfig/Makefile > +++ b/scripts/kconfig/Makefile > @@ -4,7 +4,7 @@ > # These targets are used from top-level makefile > > PHONY += xconfig gconfig menuconfig config syncconfig \ > - localmodconfig localyesconfig > + localmodconfig localyesconfig debugconfig > > ifdef KBUILD_KCONFIG > Kconfig := $(KBUILD_KCONFIG) > @@ -34,6 +34,9 @@ config: $(obj)/conf > nconfig: $(obj)/nconf > $< $(silent) $(Kconfig) > > +debugconfig: $(obj)/dconf > + $< $(silent) $(Kconfig) > + > # This has become an internal implementation detail and is now deprecated > # for external use. > syncconfig: $(obj)/conf > @@ -149,6 +152,7 @@ help: > @echo ' xenconfig - Enable additional options for xen dom0 and guest kernel support' > @echo ' tinyconfig - Configure the tiniest possible kernel' > @echo ' testconfig - Run Kconfig unit tests (requires python3 and pytest)' > + @echo ' debugconfig - Debugging tool for developers' > > # =========================================================================== > # Shared Makefile for the various kconfig executables: > @@ -165,6 +169,10 @@ targets += zconf.lex.c > HOSTCFLAGS_zconf.lex.o := -I$(src) > HOSTCFLAGS_zconf.tab.o := -I$(src) > > +# dconf: Used for kconfig debugging > +hostprogs-y += dconf > +dconf-objs := dconf.o zconf.tab.o > + > # nconf: Used for the nconfig target based on ncurses > hostprogs-y += nconf > nconf-objs := nconf.o zconf.tab.o nconf.gui.o > diff --git a/scripts/kconfig/dconf.c b/scripts/kconfig/dconf.c > new file mode 100644 > index 000000000000..ed1edf607d80 > --- /dev/null > +++ b/scripts/kconfig/dconf.c > @@ -0,0 +1,55 @@ > +// SPDX-License-Identifier: GPL-2.0 > +// > +// Copyright (C) 2018 Dirk Gouders <dirk@gouders.net> > + > +#include <stdlib.h> > +#include <stdio.h> > +#include <getopt.h> > + > +#include "lkc.h" > + > +extern int cdebug; > + > +void usage(const char *progname); > +void usage(const char *progname) > +{ > + printf("Usage: %s --help | [--debug] <kconfig-file>\n", progname); > +} > + > +int main(int argc, char *argv[]) > +{ > + int c; > + int opt_index = 0; > + char *filename; > + > + struct option long_opts[] = { > + {"debug", no_argument, NULL, 0}, > + {"help", no_argument, NULL, 1}, > + {0, 0, 0, 0} > + }; > + > + while (1 ) { > + c = getopt_long(argc, argv, "", long_opts, &opt_index); > + > + if (c == -1) > + break; > + if (c == 0) { > + cdebug = 0x02; > + } > + if (c == 1) { > + usage(argv[0]); > + exit(EXIT_SUCCESS); > + } > + } > + > + if (optind == argc) { > + usage(argv[0]); > + exit(EXIT_FAILURE); > + } else > + filename = argv[optind]; > + > + conf_parse(filename); > + zconfdump(stdout); > + > + exit(EXIT_SUCCESS); > +} > -- > 2.13.6 > > -- > To unsubscribe from this list: send the line "unsubscribe linux-kbuild" in > the body of a message to majordomo@vger.kernel.org > More majordomo info at http://vger.kernel.org/majordomo-info.html You mentioned ZCONF_DEBUG in the log. So, another possibility is to use an environment variable to turn on debug features. name = getenv("KCONFIG_DEBUG"); if (name && name[0] == '1') zconfdump(stdout);
Masahiro Yamada <yamada.masahiro@socionext.com> writes: > 2018-06-23 4:27 GMT+09:00 Dirk Gouders <dirk@gouders.net>: >> Currently, we need to modify existing kconfig targets to generate debugging >> information from the parser. That information then has to be filtered >> somehow, automated tests are at least complicated to implement. >> >> Add a debugconfig target for pure debugging purposes; the initial >> version of this target dumps the menu tree and with the --debug option >> activates the parsers debugging output via it's global variable >> cdebug. The environment variable ZCONF_DEBUG can be used to generate >> even more detailed debugging information. >> >> Sample output for a simple Kconfig file: >> >> $ scripts/kconfig/dconf --debug Kconfig.dconfig >> Kconfig.dconfig:1:config a >> Kconfig.dconfig:2:type(1) >> Kconfig.dconfig:4:endconfig >> Kconfig.dconfig:5:if >> Kconfig.dconfig:5:config b >> Kconfig.dconfig:6:type(1) >> Kconfig.dconfig:7:endconfig >> Kconfig.dconfig:7:endif >> >> config a >> bool >> symbol a >> prompt "a" >> >> config b >> bool >> symbol b >> prompt "b" if a >> >> endmenu >> >> Signed-off-by: Dirk Gouders <dirk@gouders.net> >> Cc: Sam Ravnborg <sam@ravnborg.org> >> --- >> scripts/kconfig/Makefile | 10 ++++++++- >> scripts/kconfig/dconf.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++ >> 2 files changed, 64 insertions(+), 1 deletion(-) >> create mode 100644 scripts/kconfig/dconf.c >> >> diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile >> index a3ac2c91331c..19906ff25392 100644 >> --- a/scripts/kconfig/Makefile >> +++ b/scripts/kconfig/Makefile >> @@ -4,7 +4,7 @@ >> # These targets are used from top-level makefile >> >> PHONY += xconfig gconfig menuconfig config syncconfig \ >> - localmodconfig localyesconfig >> + localmodconfig localyesconfig debugconfig >> >> ifdef KBUILD_KCONFIG >> Kconfig := $(KBUILD_KCONFIG) >> @@ -34,6 +34,9 @@ config: $(obj)/conf >> nconfig: $(obj)/nconf >> $< $(silent) $(Kconfig) >> >> +debugconfig: $(obj)/dconf >> + $< $(silent) $(Kconfig) >> + >> # This has become an internal implementation detail and is now deprecated >> # for external use. >> syncconfig: $(obj)/conf >> @@ -149,6 +152,7 @@ help: >> @echo ' xenconfig - Enable additional options for xen dom0 and guest kernel support' >> @echo ' tinyconfig - Configure the tiniest possible kernel' >> @echo ' testconfig - Run Kconfig unit tests (requires python3 and pytest)' >> + @echo ' debugconfig - Debugging tool for developers' >> >> # =========================================================================== >> # Shared Makefile for the various kconfig executables: >> @@ -165,6 +169,10 @@ targets += zconf.lex.c >> HOSTCFLAGS_zconf.lex.o := -I$(src) >> HOSTCFLAGS_zconf.tab.o := -I$(src) >> >> +# dconf: Used for kconfig debugging >> +hostprogs-y += dconf >> +dconf-objs := dconf.o zconf.tab.o >> + >> # nconf: Used for the nconfig target based on ncurses >> hostprogs-y += nconf >> nconf-objs := nconf.o zconf.tab.o nconf.gui.o >> diff --git a/scripts/kconfig/dconf.c b/scripts/kconfig/dconf.c >> new file mode 100644 >> index 000000000000..ed1edf607d80 >> --- /dev/null >> +++ b/scripts/kconfig/dconf.c >> @@ -0,0 +1,55 @@ >> +// SPDX-License-Identifier: GPL-2.0 >> +// >> +// Copyright (C) 2018 Dirk Gouders <dirk@gouders.net> >> + >> +#include <stdlib.h> >> +#include <stdio.h> >> +#include <getopt.h> >> + >> +#include "lkc.h" >> + >> +extern int cdebug; >> + >> +void usage(const char *progname); >> +void usage(const char *progname) >> +{ >> + printf("Usage: %s --help | [--debug] <kconfig-file>\n", progname); >> +} >> + >> +int main(int argc, char *argv[]) >> +{ >> + int c; >> + int opt_index = 0; >> + char *filename; >> + >> + struct option long_opts[] = { >> + {"debug", no_argument, NULL, 0}, >> + {"help", no_argument, NULL, 1}, >> + {0, 0, 0, 0} >> + }; >> + >> + while (1 ) { >> + c = getopt_long(argc, argv, "", long_opts, &opt_index); >> + >> + if (c == -1) >> + break; >> + if (c == 0) { >> + cdebug = 0x02; >> + } >> + if (c == 1) { >> + usage(argv[0]); >> + exit(EXIT_SUCCESS); >> + } >> + } >> + >> + if (optind == argc) { >> + usage(argv[0]); >> + exit(EXIT_FAILURE); >> + } else >> + filename = argv[optind]; >> + >> + conf_parse(filename); >> + zconfdump(stdout); >> + >> + exit(EXIT_SUCCESS); >> +} >> -- >> 2.13.6 >> >> -- >> To unsubscribe from this list: send the line "unsubscribe linux-kbuild" in >> the body of a message to majordomo@vger.kernel.org >> More majordomo info at http://vger.kernel.org/majordomo-info.html > > > You mentioned ZCONF_DEBUG in the log. > > So, another possibility is to use > an environment variable to turn on debug features. > > name = getenv("KCONFIG_DEBUG"); > if (name && name[0] == '1') > zconfdump(stdout); Yes, that would also be a possibility. Perhaps even more flexibility would be gained if a path is allowed for the content of the environment variable to specify where the dump should go, e.g. KCONFIG_DEBUG="./zconfdump-%d.out". This way, we could dump without disturbing std{err,out}. Since some days, I am thinking about the possibility of a "knob" for *config targets, once triggered, a dump will be produced to the specified location. But thinking of menuconfig, for example, I have not yet an idea what this "knob" could be -- we don't have many unused keys left. Perhaps a signal... The following is only meant for exchange of ideas -- I currently do some debugging this way but chances are that all of it is not thought trough, very well and too complicated: I am wondering if -- instead of providing a debugging tool -- it would be more practical to offer developers a hook to enable easy use of personal debugging tools through make(1) without disturbing git and the need to trimm the mainstream Makefile every time: 1) Add a hook to scripts/kconfig/Makefile to allow developers to add own tools if they want to: # # Include optional Makefile that developers can trimm without # disturbing git to make use of tools that are still under development # or not adequate for mainstream. # -include scripts/kconfig/Makefile.devel 2) My Makefile.devel then looks like PHONY += debugconfig debugconfig: $(obj)/dconf $< $(silent) $(dconfargs) $(Kconfig) # dconf: Used for kconfig debugging hostprogs-y += dconf dconf-objs := dconf.o zconf.tab.o 3) This allows me to call debugconfig like this: make dconfargs="--symdump=symdump" Kconfig=Kconfig_for_testing debugconfig 4) In case you are interested, my current debugging tool is attached. It grew a bit and it is bigger than it could be, because (for now) I want it to be standalone, without disturbing files that are controlled by git. The tool now also produces a dump of all symbols, a bit different compared to walking symbols via the menu. Dirk // SPDX-License-Identifier: GPL-2.0 // // Copyright (C) 2018 Dirk Gouders <dirk@gouders.net> #include <stdlib.h> #include <stdio.h> #include <getopt.h> #include <string.h> #include "lkc.h" #include "expr.h" extern int cdebug; #define SYMBOL_NO_WRITE 0x1000 void usage(const char *progname); void usage(const char *progname) { printf("Usage: %s --help | [--debug] [--menudump[=file]] [--symdump[=file]] <kconfig-file>\n", progname); } static void dconf_check_types() { } static void print_quoted_string(FILE *out, const char *str) { const char *p; int len; putc('"', out); while ((p = strchr(str, '"'))) { len = p - str; if (len) fprintf(out, "%.*s", len, str); fputs("\\\"", out); str = p + 1; } fputs(str, out); putc('"', out); } static void sym_print_flags(FILE *out, struct symbol *sym) { char *space = ""; fprintf(out, "Flags: "); if (!sym->flags) { fprintf(out, "\n"); return; } if (sym->flags & SYMBOL_CONST) { fprintf(out, "CONST"); space = ", "; } if (sym->flags & SYMBOL_CHECK) { fprintf(out, "%sCHECK", space); space = ", "; } if (sym->flags & SYMBOL_CHOICE) { fprintf(out, "%sCHOICE", space); space = ", "; } if (sym->flags & SYMBOL_CHOICEVAL) { fprintf(out, "%sCHOICEVAL", space); space = ", "; } if (sym->flags & SYMBOL_VALID) { fprintf(out, "%sVALID", space); space = ", "; } if (sym->flags & SYMBOL_OPTIONAL) { fprintf(out, "%sOPTIONAL", space); space = ", "; } if (sym->flags & SYMBOL_WRITE) { fprintf(out, "%sWRITE", space); space = ", "; } if (sym->flags & SYMBOL_CHANGED) { fprintf(out, "%sCHANGED", space); space = ", "; } if (sym->flags & SYMBOL_NO_WRITE) { fprintf(out, "%sNO_WRITE", space); space = ", "; } if (sym->flags & SYMBOL_CHECKED) { fprintf(out, "%sCHECKED", space); space = ", "; } if (sym->flags & SYMBOL_WARNED) { fprintf(out, "%sWARNED", space); } fprintf(out, "\n"); } static void print_symbol(FILE *out, struct symbol *sym) { struct property *prop; if (sym_is_choice(sym)) fprintf(out, "\nchoice\n"); else fprintf(out, "\nconfig %s\n", sym->name); sym_print_flags(out, sym); switch (sym->type) { case S_BOOLEAN: fputs(" bool\n", out); break; case S_TRISTATE: fputs(" tristate\n", out); break; case S_STRING: fputs(" string\n", out); break; case S_INT: fputs(" integer\n", out); break; case S_HEX: fputs(" hex\n", out); break; default: fputs(" unknown\n", out); break; } fprintf(out, "Value: %s\n", sym_get_string_value(sym)); for (prop = sym->prop; prop; prop = prop->next) { switch (prop->type) { case P_PROMPT: fputs(" prompt ", out); print_quoted_string(out, prop->text); if (!expr_is_yes(prop->visible.expr)) { fputs(" if ", out); expr_fprint(prop->visible.expr, out); } fputc('\n', out); break; case P_DEFAULT: fputs( " default ", out); expr_fprint(prop->expr, out); if (!expr_is_yes(prop->visible.expr)) { fputs(" if ", out); expr_fprint(prop->visible.expr, out); } fputc('\n', out); break; case P_CHOICE: fputs(" #choice value\n", out); break; case P_SELECT: fputs( " select ", out); expr_fprint(prop->expr, out); if (!expr_is_yes(prop->visible.expr)) { fputs(" if ", out); expr_fprint(prop->visible.expr, out); } fputc('\n', out); break; case P_IMPLY: fputs( " imply ", out); expr_fprint(prop->expr, out); if (!expr_is_yes(prop->visible.expr)) { fputs(" if ", out); expr_fprint(prop->visible.expr, out); } fputc('\n', out); break; case P_RANGE: fputs( " range ", out); expr_fprint(prop->expr, out); if (!expr_is_yes(prop->visible.expr)) { fputs(" if ", out); expr_fprint(prop->visible.expr, out); } fputc('\n', out); break; case P_MENU: fputs( " menu ", out); print_quoted_string(out, prop->text); fputc('\n', out); break; case P_SYMBOL: fputs( " symbol ", out); if (prop->sym) fprintf(out, "%s (file %s:%d)\n", prop->sym->name, prop->file->name, prop->lineno); break; default: fprintf(out, " unknown prop %d!\n", prop->type); break; } } fprintf(out, " Depends on: "); if (!expr_is_yes(sym->dir_dep.expr)) expr_fprint(sym->dir_dep.expr, out); fprintf(out, "\n Selected by: "); if (!expr_is_yes(sym->rev_dep.expr)) expr_fprint(sym->rev_dep.expr, out); fprintf(out, "\n Implied by: "); if (!expr_is_yes(sym->implied.expr)) expr_fprint(sym->implied.expr, out); fputc('\n', out); } void sym_dump(FILE *); void sym_dump(FILE *out) { struct symbol *sym; int i; print_symbol(out, &symbol_yes); print_symbol(out, &symbol_mod); print_symbol(out, &symbol_no); for_all_symbols(i, sym) { print_symbol(out, sym); } } int main(int argc, char *argv[]) { int c; int opt_index = 0; char *filename; int menudump = 0; /* Print menu structure */ FILE *menudump_out; int symdump = 0; /* Print all symbols */ FILE *symdump_out; struct option long_opts[] = { {"debug", no_argument, NULL, 0}, {"help", no_argument, NULL, 1}, {"menudump", optional_argument, NULL, 2}, {"symdump", optional_argument, NULL, 3}, {0, 0, 0, 0} }; while (1 ) { c = getopt_long(argc, argv, "", long_opts, &opt_index); if (c == -1) break; if (c == 0) { cdebug = 0x02; } if (c == 1) { usage(argv[0]); exit(EXIT_SUCCESS); } if (c == 2) { menudump = 1; if (optarg) { if (!strcmp(optarg, "stdout")) menudump_out = stdout; else if (!strcmp(optarg, "stderr")) menudump_out = stderr; else { menudump_out = fopen(optarg, "w"); if (!menudump_out) { perror(optarg); } } } else menudump_out = stdout; } if (c == 3) { symdump = 1; if (optarg) { if (!strcmp(optarg, "stdout")) symdump_out = stdout; else if (!strcmp(optarg, "stderr")) symdump_out = stderr; else { symdump_out = fopen(optarg, "w"); if (!symdump_out) { perror(optarg); } } } else symdump_out = stdout; } } if (optind == argc) { usage(argv[0]); exit(EXIT_FAILURE); } else filename = argv[optind]; //getc(stdin); conf_parse(filename); //conf_read(NULL); if (menudump) zconfdump(menudump_out); if (symdump) sym_dump(symdump_out); exit(EXIT_SUCCESS); }
diff --git a/scripts/kconfig/Makefile b/scripts/kconfig/Makefile index a3ac2c91331c..19906ff25392 100644 --- a/scripts/kconfig/Makefile +++ b/scripts/kconfig/Makefile @@ -4,7 +4,7 @@ # These targets are used from top-level makefile PHONY += xconfig gconfig menuconfig config syncconfig \ - localmodconfig localyesconfig + localmodconfig localyesconfig debugconfig ifdef KBUILD_KCONFIG Kconfig := $(KBUILD_KCONFIG) @@ -34,6 +34,9 @@ config: $(obj)/conf nconfig: $(obj)/nconf $< $(silent) $(Kconfig) +debugconfig: $(obj)/dconf + $< $(silent) $(Kconfig) + # This has become an internal implementation detail and is now deprecated # for external use. syncconfig: $(obj)/conf @@ -149,6 +152,7 @@ help: @echo ' xenconfig - Enable additional options for xen dom0 and guest kernel support' @echo ' tinyconfig - Configure the tiniest possible kernel' @echo ' testconfig - Run Kconfig unit tests (requires python3 and pytest)' + @echo ' debugconfig - Debugging tool for developers' # =========================================================================== # Shared Makefile for the various kconfig executables: @@ -165,6 +169,10 @@ targets += zconf.lex.c HOSTCFLAGS_zconf.lex.o := -I$(src) HOSTCFLAGS_zconf.tab.o := -I$(src) +# dconf: Used for kconfig debugging +hostprogs-y += dconf +dconf-objs := dconf.o zconf.tab.o + # nconf: Used for the nconfig target based on ncurses hostprogs-y += nconf nconf-objs := nconf.o zconf.tab.o nconf.gui.o diff --git a/scripts/kconfig/dconf.c b/scripts/kconfig/dconf.c new file mode 100644 index 000000000000..ed1edf607d80 --- /dev/null +++ b/scripts/kconfig/dconf.c @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// Copyright (C) 2018 Dirk Gouders <dirk@gouders.net> + +#include <stdlib.h> +#include <stdio.h> +#include <getopt.h> + +#include "lkc.h" + +extern int cdebug; + +void usage(const char *progname); +void usage(const char *progname) +{ + printf("Usage: %s --help | [--debug] <kconfig-file>\n", progname); +} + +int main(int argc, char *argv[]) +{ + int c; + int opt_index = 0; + char *filename; + + struct option long_opts[] = { + {"debug", no_argument, NULL, 0}, + {"help", no_argument, NULL, 1}, + {0, 0, 0, 0} + }; + + while (1 ) { + c = getopt_long(argc, argv, "", long_opts, &opt_index); + + if (c == -1) + break; + if (c == 0) { + cdebug = 0x02; + } + if (c == 1) { + usage(argv[0]); + exit(EXIT_SUCCESS); + } + } + + if (optind == argc) { + usage(argv[0]); + exit(EXIT_FAILURE); + } else + filename = argv[optind]; + + conf_parse(filename); + zconfdump(stdout); + + exit(EXIT_SUCCESS); +}
Currently, we need to modify existing kconfig targets to generate debugging information from the parser. That information then has to be filtered somehow, automated tests are at least complicated to implement. Add a debugconfig target for pure debugging purposes; the initial version of this target dumps the menu tree and with the --debug option activates the parsers debugging output via it's global variable cdebug. The environment variable ZCONF_DEBUG can be used to generate even more detailed debugging information. Sample output for a simple Kconfig file: $ scripts/kconfig/dconf --debug Kconfig.dconfig Kconfig.dconfig:1:config a Kconfig.dconfig:2:type(1) Kconfig.dconfig:4:endconfig Kconfig.dconfig:5:if Kconfig.dconfig:5:config b Kconfig.dconfig:6:type(1) Kconfig.dconfig:7:endconfig Kconfig.dconfig:7:endif config a bool symbol a prompt "a" config b bool symbol b prompt "b" if a endmenu Signed-off-by: Dirk Gouders <dirk@gouders.net> Cc: Sam Ravnborg <sam@ravnborg.org> --- scripts/kconfig/Makefile | 10 ++++++++- scripts/kconfig/dconf.c | 55 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 scripts/kconfig/dconf.c