linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v2 0/3] kconfig: rework symbol help text
@ 2019-12-17 16:15 Thomas Hebb
  2019-12-17 16:15 ` [PATCH v2 1/3] kconfig: list all definitions of a symbol in " Thomas Hebb
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Thomas Hebb @ 2019-12-17 16:15 UTC (permalink / raw)
  To: linux-kernel, linux-kbuild
  Cc: Masahiro Yamada, Thomas Hebb, Palmer Dabbelt, Paul Walmsley, linux-riscv

This series fixes several issues with help text generated by Kconfig,
mainly affecting symbols that are defined in multiple places. Although
results of these patches are somewhat visible for the symbols in Linux,
what prompted me to write the series was working on U-Boot, which also
uses Kconfig and makes very heavy use of multiple definitions (e.g. for
overriding defaults). I have provided Linux examples where I could find
them, but the example for the biggest patch (the first one) is taken
from U-Boot because it was more illustrative than anything I could find
in Linux.

Changes in v2:
- Added explicit U-Boot version in commit message + other rewordings
- Made the new "Depends on:" line print actual dependencies instead of
  visibility to avoid an intra-series regression, and noted that in the
  commit message.
- Get rid of redundant "with prompt" and "without prompt" notes in
  definition text, but continue to ensure that definitions with prompts
  are printed before ones without.
- Fixed checkpatch issues
- Omit already-merged patch "kconfig: don't crash on NULL expressions in
  expr_eq()"

Thomas Hebb (3):
  kconfig: list all definitions of a symbol in help text
  kconfig: distinguish between dependencies and visibility in help text
  kconfig: fix nesting of symbol help text

 scripts/kconfig/expr.c |  3 +-
 scripts/kconfig/expr.h |  1 +
 scripts/kconfig/menu.c | 82 +++++++++++++++++++++++++-----------------
 3 files changed, 52 insertions(+), 34 deletions(-)

-- 
2.24.1


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v2 1/3] kconfig: list all definitions of a symbol in help text
  2019-12-17 16:15 [PATCH v2 0/3] kconfig: rework symbol help text Thomas Hebb
@ 2019-12-17 16:15 ` Thomas Hebb
  2019-12-17 16:15 ` [PATCH v2 2/3] kconfig: distinguish between dependencies and visibility " Thomas Hebb
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Thomas Hebb @ 2019-12-17 16:15 UTC (permalink / raw)
  To: linux-kernel, linux-kbuild
  Cc: Masahiro Yamada, Thomas Hebb, Palmer Dabbelt, Paul Walmsley, linux-riscv

In Kconfig, each symbol (representing a config option) can be defined in
multiple places. Each definition may or may not have a prompt, which
allows the option to be set via an interface like menuconfig. Each
definition has a set of dependencies, which determine whether its prompt
is visible and whether other pieces of the definition, like a default
value, take effect.

Historically, a symbol's help text (i.e. what's shown when a user
presses '?' in menuconfig) contained some symbol-wide information not
tied to any particular definition (e.g. what other symbols it selects)
as well as the location (file name and line number) and dependencies of
each prompt. Notably, the help text did not show the location or
dependencies of definitions without prompts.

Because this made it hard to reason about symbols that had no prompts,
commit bcdedcc1afd6 ("menuconfig: print more info for symbol without
prompts") changed the help text so that, instead of containing the
location and dependencies of each prompt, it contained the location and
dependencies of the symbol's first definition, regardless of whether or
not that definition had a prompt.

For symbols with only one definition, that change makes sense. However,
it breaks down for symbols with multiple definitions: each definition
has its own set of dependencies (the `dep` field of `struct menu`), and
those dependencies are ORed together to get the symbol's dependency list
(the `dir_dep` field of `struct symbol`). By printing only the
dependencies of the first definition, the help text misleads users into
believing that an option is more narrowly-applicable than it actually
is.

For an extreme example of this, we can look at the SYS_TEXT_BASE symbol
in the Das U-Boot project (version 2019.10), which also uses Kconfig. (I
unfortunately could not find an illustrative example in Linux.) This
config option specifies the load address of the built binary and, as
such, is applicable to basically every configuration possible. And yet,
without this patch, its help text is as follows:

  Symbol: SYS_TEXT_BASE [=]
  Type  : hex
  Prompt: U-Boot base address
    Location:
      -> ARM architecture
  Prompt: Text Base
    Location:
      -> Boot images
    Defined at arch/arm/mach-aspeed/Kconfig:9
    Depends on: ARM [=n] && ARCH_ASPEED [=n]

The help text indicates that the option is applicable only for a
specific unselected architecture (aspeed), because that architecture's
promptless definition (which just sets a default value), happens to be
the first one seen. No definition or dependency information is printed
for either of the two prompts listed.

Because source locations and dependencies are fundamentally properties
of definitions and not of symbols, we should treat them as such. This
patch brings back the pre-bcdedcc1afd6 behavior for definitions with
prompts but also separately prints the location and dependencies of
those without prompts, solving the original problem in a different way.
With this change, our SYS_TEXT_BASE example becomes

   Symbol: SYS_TEXT_BASE [=]
   Type  : hex
   Defined at arch/arm/mach-stm32mp/Kconfig:83
     Prompt: U-Boot base address
     Depends on: ARM [=n] && ARCH_STM32MP [=n]
     Location:
       -> ARM architecture
   Defined at Kconfig:532
     Prompt: Text Base
     Depends on: !NIOS2 [=n] && !XTENSA [=n] && !EFI_APP [=n]
     Location:
       -> Boot images
   Defined at arch/arm/mach-aspeed/Kconfig:9
     Depends on: ARM [=n] && ARCH_ASPEED [=n]
   Defined  at arch/arm/mach-socfpga/Kconfig:25
     Depends on: ARM [=n] && ARCH_SOCFPGA [=n]
   <snip>
   Defined at board/sifive/fu540/Kconfig:15
     Depends on: RISCV [=n] && TARGET_SIFIVE_FU540 [=n]

which is a much more accurate representation.

Note that there is one notable difference between what gets printed for
prompts after this change and what got printed before bcdedcc1afd6: the
"Depends on" line now accurately represents the prompt's dependencies
instead of conflating those with the prompt's visibility (which can
include extra conditions). See the patch later in this series titled
"kconfig: distinguish between dependencies and visibility in help text"
for more details and better handling of that nuance.

Signed-off-by: Thomas Hebb <tommyhebb@gmail.com>
---

Changes in v2:
- Added explicit U-Boot version in commit message + other rewordings
- Made the new "Depends on:" line print actual dependencies instead of
  visibility to avoid an intra-series regression, and noted that in the
  commit message.
- Get rid of redundant "with prompt" and "without prompt" notes in
  definition text, but continue to ensure that definitions with prompts
  are printed before ones without.

 scripts/kconfig/menu.c | 55 ++++++++++++++++++++++++------------------
 1 file changed, 31 insertions(+), 24 deletions(-)

diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index d9d16469859a..0e54632d2043 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -698,6 +698,21 @@ const char *menu_get_help(struct menu *menu)
 		return "";
 }
 
+static void get_def_str(struct gstr *r, struct menu *menu)
+{
+	str_printf(r, "Defined at %s:%d\n",
+		   menu->file->name, menu->lineno);
+}
+
+static void get_dep_str(struct gstr *r, struct expr *expr, const char *prefix)
+{
+	if (!expr_is_yes(expr)) {
+		str_append(r, prefix);
+		expr_gstr_print(expr, r);
+		str_append(r, "\n");
+	}
+}
+
 static void get_prompt_str(struct gstr *r, struct property *prop,
 			   struct list_head *head)
 {
@@ -705,7 +720,9 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
 	struct menu *submenu[8], *menu, *location = NULL;
 	struct jump_key *jump = NULL;
 
-	str_printf(r, "Prompt: %s\n", prop->text);
+	str_printf(r, "  Prompt: %s\n", prop->text);
+
+	get_dep_str(r, prop->menu->dep, "  Depends on: ");
 	menu = prop->menu->parent;
 	for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) {
 		bool accessible = menu_is_visible(menu);
@@ -755,18 +772,6 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
 	}
 }
 
-/*
- * get property of type P_SYMBOL
- */
-static struct property *get_symbol_prop(struct symbol *sym)
-{
-	struct property *prop = NULL;
-
-	for_all_properties(sym, prop, P_SYMBOL)
-		break;
-	return prop;
-}
-
 static void get_symbol_props_str(struct gstr *r, struct symbol *sym,
 				 enum prop_type tok, const char *prefix)
 {
@@ -806,17 +811,19 @@ static void get_symbol_str(struct gstr *r, struct symbol *sym,
 			}
 		}
 	}
-	for_all_prompts(sym, prop)
-		get_prompt_str(r, prop, head);
-
-	prop = get_symbol_prop(sym);
-	if (prop) {
-		str_printf(r, "  Defined at %s:%d\n", prop->menu->file->name,
-			prop->menu->lineno);
-		if (!expr_is_yes(prop->visible.expr)) {
-			str_append(r, "  Depends on: ");
-			expr_gstr_print(prop->visible.expr, r);
-			str_append(r, "\n");
+
+	/* Print the definitions with prompts before the ones without */
+	for_all_properties(sym, prop, P_SYMBOL) {
+		if (prop->menu->prompt) {
+			get_def_str(r, prop->menu);
+			get_prompt_str(r, prop->menu->prompt, head);
+		}
+	}
+
+	for_all_properties(sym, prop, P_SYMBOL) {
+		if (!prop->menu->prompt) {
+			get_def_str(r, prop->menu);
+			get_dep_str(r, prop->menu->dep, "  Depends on: ");
 		}
 	}
 
-- 
2.24.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v2 2/3] kconfig: distinguish between dependencies and visibility in help text
  2019-12-17 16:15 [PATCH v2 0/3] kconfig: rework symbol help text Thomas Hebb
  2019-12-17 16:15 ` [PATCH v2 1/3] kconfig: list all definitions of a symbol in " Thomas Hebb
@ 2019-12-17 16:15 ` Thomas Hebb
  2019-12-17 16:15 ` [PATCH v2 3/3] kconfig: fix nesting of symbol " Thomas Hebb
  2019-12-18 14:09 ` [PATCH v2 0/3] kconfig: rework " Masahiro Yamada
  3 siblings, 0 replies; 5+ messages in thread
From: Thomas Hebb @ 2019-12-17 16:15 UTC (permalink / raw)
  To: linux-kernel, linux-kbuild; +Cc: Masahiro Yamada, Thomas Hebb

Kconfig makes a distinction between dependencies (defined by "depends
on" expressions and enclosing "if" blocks) and visibility (which
includes all dependencies, but also includes inline "if" expressions of
individual properties as well as, for prompts, "visible if" expressions
of enclosing menus).

Before commit bcdedcc1afd6 ("menuconfig: print more info for symbol
without prompts"), the "Depends on" lines of a symbol's help text
indicated the visibility of the prompt property they appeared under.
After bcdedcc1afd, there was always only a single "Depends on" line,
which indicated the visibility of the first P_SYMBOL property of the
symbol. Since P_SYMBOLs never have inline if expressions, this was in
effect the same as the dependencies of the menu item that the P_SYMBOL
was attached to.

Neither of these situations accurately conveyed the dependencies of a
symbol--the first because it was actually the visibility, and the second
because it only showed the dependencies from a single definition.

With this series, we are back to printing separate dependencies for each
definition, but we print the actual dependencies (rather than the
visibility) in the "Depends on" line. However, it can still be useful to
know the visibility of a prompt, so this patch adds a "Visible if" line
that shows the visibility only if the visibility is different from the
dependencies (which it isn't for most prompts in Linux).

Before:

  Symbol: THUMB2_KERNEL [=n]
  Type  : bool
  Defined at arch/arm/Kconfig:1417
    Prompt: Compile the kernel in Thumb-2 mode
    Depends on: (CPU_V7 [=y] || CPU_V7M [=n]) && !CPU_V6 [=n] && !CPU_V6K [=n]
    Location:
      -> Kernel Features
    Selects: ARM_UNWIND [=n]

After:

   Symbol: THUMB2_KERNEL [=n]
   Type  : bool
   Defined at arch/arm/Kconfig:1417
     Prompt: Compile the kernel in Thumb-2 mode
     Depends on: (CPU_V7 [=y] || CPU_V7M [=n]) && !CPU_V6 [=n] && !CPU_V6K [=n]
     Visible if: (CPU_V7 [=y] || CPU_V7M [=n]) && !CPU_V6 [=n] && !CPU_V6K [=n] && !CPU_THUMBONLY [=n]
     Location:
       -> Kernel Features
     Selects: ARM_UNWIND [=n]

Signed-off-by: Thomas Hebb <tommyhebb@gmail.com>
---

Changes in v2:
- Fixed checkpatch issues

 scripts/kconfig/expr.c |  3 +--
 scripts/kconfig/expr.h |  1 +
 scripts/kconfig/menu.c | 11 +++++++++++
 3 files changed, 13 insertions(+), 2 deletions(-)

diff --git a/scripts/kconfig/expr.c b/scripts/kconfig/expr.c
index 9f1de58e9f0c..81ebf8108ca7 100644
--- a/scripts/kconfig/expr.c
+++ b/scripts/kconfig/expr.c
@@ -13,7 +13,6 @@
 
 #define DEBUG_EXPR	0
 
-static int expr_eq(struct expr *e1, struct expr *e2);
 static struct expr *expr_eliminate_yn(struct expr *e);
 
 struct expr *expr_alloc_symbol(struct symbol *sym)
@@ -250,7 +249,7 @@ void expr_eliminate_eq(struct expr **ep1, struct expr **ep2)
  * equals some operand in the other (operands do not need to appear in the same
  * order), recursively.
  */
-static int expr_eq(struct expr *e1, struct expr *e2)
+int expr_eq(struct expr *e1, struct expr *e2)
 {
 	int res, old_count;
 
diff --git a/scripts/kconfig/expr.h b/scripts/kconfig/expr.h
index 017843c9a4f4..d0f17bc9c4ef 100644
--- a/scripts/kconfig/expr.h
+++ b/scripts/kconfig/expr.h
@@ -301,6 +301,7 @@ struct expr *expr_alloc_or(struct expr *e1, struct expr *e2);
 struct expr *expr_copy(const struct expr *org);
 void expr_free(struct expr *e);
 void expr_eliminate_eq(struct expr **ep1, struct expr **ep2);
+int expr_eq(struct expr *e1, struct expr *e2);
 tristate expr_calc_value(struct expr *e);
 struct expr *expr_trans_bool(struct expr *e);
 struct expr *expr_eliminate_dups(struct expr *e);
diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index 0e54632d2043..dcf7f32f0bba 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -723,6 +723,17 @@ static void get_prompt_str(struct gstr *r, struct property *prop,
 	str_printf(r, "  Prompt: %s\n", prop->text);
 
 	get_dep_str(r, prop->menu->dep, "  Depends on: ");
+	/*
+	 * Most prompts in Linux have visibility that exactly matches their
+	 * dependencies. For these, we print only the dependencies to improve
+	 * readability. However, prompts with inline "if" expressions and
+	 * prompts with a parent that has a "visible if" expression have
+	 * differing dependencies and visibility. In these rare cases, we
+	 * print both.
+	 */
+	if (!expr_eq(prop->menu->dep, prop->visible.expr))
+		get_dep_str(r, prop->visible.expr, "  Visible if: ");
+
 	menu = prop->menu->parent;
 	for (i = 0; menu != &rootmenu && i < 8; menu = menu->parent) {
 		bool accessible = menu_is_visible(menu);
-- 
2.24.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v2 3/3] kconfig: fix nesting of symbol help text
  2019-12-17 16:15 [PATCH v2 0/3] kconfig: rework symbol help text Thomas Hebb
  2019-12-17 16:15 ` [PATCH v2 1/3] kconfig: list all definitions of a symbol in " Thomas Hebb
  2019-12-17 16:15 ` [PATCH v2 2/3] kconfig: distinguish between dependencies and visibility " Thomas Hebb
@ 2019-12-17 16:15 ` Thomas Hebb
  2019-12-18 14:09 ` [PATCH v2 0/3] kconfig: rework " Masahiro Yamada
  3 siblings, 0 replies; 5+ messages in thread
From: Thomas Hebb @ 2019-12-17 16:15 UTC (permalink / raw)
  To: linux-kernel, linux-kbuild; +Cc: Masahiro Yamada, Thomas Hebb

When we generate the help text of a symbol (e.g. when a user presses '?'
in menuconfig), we do two things:

 1. We iterate through every prompt that belongs to that symbol,
    printing its text and its location in the menu tree.
 2. We print symbol-wide information that's not linked to a particular
    prompt, such as what it selects/is selected by and what it
    implies/is implied by.

Each prompt we print for 1 starts with a line that's not indented
indicating where the prompt is defined, then continues with indented
lines that describe properties of that particular definition.

Once we get to 2, however, we print all the global data indented as
well! Visually, this makes it look like the symbol-wide data is
associated with the last prompt we happened to print rather than
the symbol as a whole.

Fix this by removing the indentation for symbol-wide information.

Before:

  Symbol: CPU_FREQ [=n]
  Type  : bool
  Defined at drivers/cpufreq/Kconfig:4
    Prompt: CPU Frequency scaling
    Location:
      -> CPU Power Management
        -> CPU Frequency scaling
    Selects: SRCU [=n]
    Selected by [n]:
    - ARCH_SA1100 [=n] && <choice>

After:

  Symbol: CPU_FREQ [=n]
  Type  : bool
  Defined at drivers/cpufreq/Kconfig:4
    Prompt: CPU Frequency scaling
    Location:
      -> CPU Power Management
        -> CPU Frequency scaling
  Selects: SRCU [=n]
  Selected by [n]:
    - ARCH_SA1100 [=n] && <choice>

Signed-off-by: Thomas Hebb <tommyhebb@gmail.com>
---

Changes in v2: None

 scripts/kconfig/menu.c | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/scripts/kconfig/menu.c b/scripts/kconfig/menu.c
index dcf7f32f0bba..ef36d1cf2a76 100644
--- a/scripts/kconfig/menu.c
+++ b/scripts/kconfig/menu.c
@@ -838,18 +838,18 @@ static void get_symbol_str(struct gstr *r, struct symbol *sym,
 		}
 	}
 
-	get_symbol_props_str(r, sym, P_SELECT, "  Selects: ");
+	get_symbol_props_str(r, sym, P_SELECT, "Selects: ");
 	if (sym->rev_dep.expr) {
-		expr_gstr_print_revdep(sym->rev_dep.expr, r, yes, "  Selected by [y]:\n");
-		expr_gstr_print_revdep(sym->rev_dep.expr, r, mod, "  Selected by [m]:\n");
-		expr_gstr_print_revdep(sym->rev_dep.expr, r, no, "  Selected by [n]:\n");
+		expr_gstr_print_revdep(sym->rev_dep.expr, r, yes, "Selected by [y]:\n");
+		expr_gstr_print_revdep(sym->rev_dep.expr, r, mod, "Selected by [m]:\n");
+		expr_gstr_print_revdep(sym->rev_dep.expr, r, no, "Selected by [n]:\n");
 	}
 
-	get_symbol_props_str(r, sym, P_IMPLY, "  Implies: ");
+	get_symbol_props_str(r, sym, P_IMPLY, "Implies: ");
 	if (sym->implied.expr) {
-		expr_gstr_print_revdep(sym->implied.expr, r, yes, "  Implied by [y]:\n");
-		expr_gstr_print_revdep(sym->implied.expr, r, mod, "  Implied by [m]:\n");
-		expr_gstr_print_revdep(sym->implied.expr, r, no, "  Implied by [n]:\n");
+		expr_gstr_print_revdep(sym->implied.expr, r, yes, "Implied by [y]:\n");
+		expr_gstr_print_revdep(sym->implied.expr, r, mod, "Implied by [m]:\n");
+		expr_gstr_print_revdep(sym->implied.expr, r, no, "Implied by [n]:\n");
 	}
 
 	str_append(r, "\n\n");
-- 
2.24.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH v2 0/3] kconfig: rework symbol help text
  2019-12-17 16:15 [PATCH v2 0/3] kconfig: rework symbol help text Thomas Hebb
                   ` (2 preceding siblings ...)
  2019-12-17 16:15 ` [PATCH v2 3/3] kconfig: fix nesting of symbol " Thomas Hebb
@ 2019-12-18 14:09 ` Masahiro Yamada
  3 siblings, 0 replies; 5+ messages in thread
From: Masahiro Yamada @ 2019-12-18 14:09 UTC (permalink / raw)
  To: Thomas Hebb
  Cc: Linux Kernel Mailing List, Linux Kbuild mailing list,
	Palmer Dabbelt, Paul Walmsley, open list:SIFIVE DRIVERS

On Wed, Dec 18, 2019 at 1:15 AM Thomas Hebb <tommyhebb@gmail.com> wrote:
>
> This series fixes several issues with help text generated by Kconfig,
> mainly affecting symbols that are defined in multiple places. Although
> results of these patches are somewhat visible for the symbols in Linux,
> what prompted me to write the series was working on U-Boot, which also
> uses Kconfig and makes very heavy use of multiple definitions (e.g. for
> overriding defaults). I have provided Linux examples where I could find
> them, but the example for the biggest patch (the first one) is taken
> from U-Boot because it was more illustrative than anything I could find
> in Linux.
>
> Changes in v2:
> - Added explicit U-Boot version in commit message + other rewordings
> - Made the new "Depends on:" line print actual dependencies instead of
>   visibility to avoid an intra-series regression, and noted that in the
>   commit message.
> - Get rid of redundant "with prompt" and "without prompt" notes in
>   definition text, but continue to ensure that definitions with prompts
>   are printed before ones without.
> - Fixed checkpatch issues
> - Omit already-merged patch "kconfig: don't crash on NULL expressions in
>   expr_eq()"
>
> Thomas Hebb (3):
>   kconfig: list all definitions of a symbol in help text
>   kconfig: distinguish between dependencies and visibility in help text
>   kconfig: fix nesting of symbol help text

All applied to linux-kbuild. Thanks.


>  scripts/kconfig/expr.c |  3 +-
>  scripts/kconfig/expr.h |  1 +
>  scripts/kconfig/menu.c | 82 +++++++++++++++++++++++++-----------------
>  3 files changed, 52 insertions(+), 34 deletions(-)
>
> --
> 2.24.1
>


-- 
Best Regards
Masahiro Yamada

^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2019-12-18 14:10 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-12-17 16:15 [PATCH v2 0/3] kconfig: rework symbol help text Thomas Hebb
2019-12-17 16:15 ` [PATCH v2 1/3] kconfig: list all definitions of a symbol in " Thomas Hebb
2019-12-17 16:15 ` [PATCH v2 2/3] kconfig: distinguish between dependencies and visibility " Thomas Hebb
2019-12-17 16:15 ` [PATCH v2 3/3] kconfig: fix nesting of symbol " Thomas Hebb
2019-12-18 14:09 ` [PATCH v2 0/3] kconfig: rework " Masahiro Yamada

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).