Commit d9119b59 authored by Eugeniu Rosca's avatar Eugeniu Rosca Committed by Masahiro Yamada

kconfig: Print reverse dependencies in groups

Surprisingly or not, disabling a CONFIG option (which is assumed to
be unneeded) may be not so trivial. Especially it is not trivial, when
this CONFIG option is selected by a dozen of other configs. Before the
moment commit 1ccb2714 ("kconfig: make "Selected by:" and
"Implied by:" readable") popped up in v4.16-rc1, it was an absolute pain
to break down the "Selected by" reverse dependency expression in order
to identify all those configs which select (IOW *do not allow
disabling*) a certain feature (assumed to be not needed).

This patch tries to make one step further by putting at users'
fingertips the revdep top level OR sub-expressions grouped/clustered by
the tristate value they evaluate to. This should allow the users to
directly concentrate on and tackle the _active_ reverse dependencies.

To give some numbers and quantify the complexity of certain reverse
dependencies, assuming commit 617aebe6 ("Merge tag
'usercopy-v4.16-rc1' of
git://git.kernel.org/pub/scm/linux/kernel/git/kees/linux"), ARCH=arm64
and vanilla arm64 defconfig, here is the top 10 CONFIG options with
the highest amount of top level "||" sub-expressions/tokens that make
up the final "Selected by" reverse dependency expression.

| Config            | All revdep | Active revdep |
|-------------------|------------|---------------|
| REGMAP_I2C        | 212        | 9             |
| CRC32             | 167        | 25            |
| FW_LOADER         | 128        | 5             |
| MFD_CORE          | 124        | 9             |
| FB_CFB_IMAGEBLIT  | 114        | 2             |
| FB_CFB_COPYAREA   | 111        | 2             |
| FB_CFB_FILLRECT   | 110        | 2             |
| SND_PCM           | 103        | 2             |
| CRYPTO_HASH       | 87         | 19            |
| WATCHDOG_CORE     | 86         | 6             |

The story behind the above is that users need to visually
review/evaluate 212 expressions which *potentially* select REGMAP_I2C
in order to identify the expressions which *actually* select REGMAP_I2C,
for a particular ARCH and for a particular defconfig used.

To make this experience smoother, change the way reverse dependencies
are displayed to the user from [1] to [2].

[1] Old representation of DMA_ENGINE_RAID:
  Selected by:
  - AMCC_PPC440SPE_ADMA [=n] && DMADEVICES [=y] && (440SPe || 440SP)
  - BCM_SBA_RAID [=m] && DMADEVICES [=y] && (ARM64 [=y] || ...
  - FSL_RAID [=n] && DMADEVICES [=y] && FSL_SOC && ...
  - INTEL_IOATDMA [=n] && DMADEVICES [=y] && PCI [=y] && X86_64
  - MV_XOR [=n] && DMADEVICES [=y] && (PLAT_ORION || ARCH_MVEBU [=y] ...
  - MV_XOR_V2 [=y] && DMADEVICES [=y] && ARM64 [=y]
  - XGENE_DMA [=n] && DMADEVICES [=y] && (ARCH_XGENE [=y] || ...
  - DMATEST [=n] && DMADEVICES [=y] && DMA_ENGINE [=y]

[2] New representation of DMA_ENGINE_RAID:
  Selected by [y]:
  - MV_XOR_V2 [=y] && DMADEVICES [=y] && ARM64 [=y]
  Selected by [m]:
  - BCM_SBA_RAID [=m] && DMADEVICES [=y] && (ARM64 [=y] || ...
  Selected by [n]:
  - AMCC_PPC440SPE_ADMA [=n] && DMADEVICES [=y] && (440SPe || ...
  - FSL_RAID [=n] && DMADEVICES [=y] && FSL_SOC && ...
  - INTEL_IOATDMA [=n] && DMADEVICES [=y] && PCI [=y] && X86_64
  - MV_XOR [=n] && DMADEVICES [=y] && (PLAT_ORION || ARCH_MVEBU [=y] ...
  - XGENE_DMA [=n] && DMADEVICES [=y] && (ARCH_XGENE [=y] || ...
  - DMATEST [=n] && DMADEVICES [=y] && DMA_ENGINE [=y]
Suggested-by: default avatarMasahiro Yamada <yamada.masahiro@socionext.com>
Signed-off-by: default avatarEugeniu Rosca <erosca@de.adit-jv.com>
Reviewed-by: default avatarPetr Vorel <pvorel@suse.cz>
Reviewed-by: default avatarUlf Magnusson <ulfalizer@gmail.com>
Signed-off-by: default avatarMasahiro Yamada <yamada.masahiro@socionext.com>
parent 9a47ceec
...@@ -1323,19 +1323,25 @@ void expr_gstr_print(struct expr *e, struct gstr *gs) ...@@ -1323,19 +1323,25 @@ void expr_gstr_print(struct expr *e, struct gstr *gs)
*/ */
static void expr_print_revdep(struct expr *e, static void expr_print_revdep(struct expr *e,
void (*fn)(void *, struct symbol *, const char *), void (*fn)(void *, struct symbol *, const char *),
void *data) void *data, tristate pr_type, const char **title)
{ {
if (e->type == E_OR) { if (e->type == E_OR) {
expr_print_revdep(e->left.expr, fn, data); expr_print_revdep(e->left.expr, fn, data, pr_type, title);
expr_print_revdep(e->right.expr, fn, data); expr_print_revdep(e->right.expr, fn, data, pr_type, title);
} else { } else if (expr_calc_value(e) == pr_type) {
if (*title) {
fn(data, NULL, *title);
*title = NULL;
}
fn(data, NULL, " - "); fn(data, NULL, " - ");
expr_print(e, fn, data, E_NONE); expr_print(e, fn, data, E_NONE);
fn(data, NULL, "\n"); fn(data, NULL, "\n");
} }
} }
void expr_gstr_print_revdep(struct expr *e, struct gstr *gs) void expr_gstr_print_revdep(struct expr *e, struct gstr *gs,
tristate pr_type, const char *title)
{ {
expr_print_revdep(e, expr_print_gstr_helper, gs); expr_print_revdep(e, expr_print_gstr_helper, gs, pr_type, &title);
} }
...@@ -310,7 +310,8 @@ struct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2); ...@@ -310,7 +310,8 @@ struct expr *expr_simplify_unmet_dep(struct expr *e1, struct expr *e2);
void expr_fprint(struct expr *e, FILE *out); void expr_fprint(struct expr *e, FILE *out);
struct gstr; /* forward */ struct gstr; /* forward */
void expr_gstr_print(struct expr *e, struct gstr *gs); void expr_gstr_print(struct expr *e, struct gstr *gs);
void expr_gstr_print_revdep(struct expr *e, struct gstr *gs); void expr_gstr_print_revdep(struct expr *e, struct gstr *gs,
tristate pr_type, const char *title);
static inline int expr_is_yes(struct expr *e) static inline int expr_is_yes(struct expr *e)
{ {
......
...@@ -828,16 +828,16 @@ static void get_symbol_str(struct gstr *r, struct symbol *sym, ...@@ -828,16 +828,16 @@ 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) { if (sym->rev_dep.expr) {
str_append(r, _(" Selected by: ")); expr_gstr_print_revdep(sym->rev_dep.expr, r, yes, " Selected by [y]:\n");
str_append(r, "\n"); expr_gstr_print_revdep(sym->rev_dep.expr, r, mod, " Selected by [m]:\n");
expr_gstr_print_revdep(sym->rev_dep.expr, r); 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) { if (sym->implied.expr) {
str_append(r, _(" Implied by: ")); expr_gstr_print_revdep(sym->implied.expr, r, yes, " Implied by [y]:\n");
str_append(r, "\n"); expr_gstr_print_revdep(sym->implied.expr, r, mod, " Implied by [m]:\n");
expr_gstr_print_revdep(sym->implied.expr, r); expr_gstr_print_revdep(sym->implied.expr, r, no, " Implied by [n]:\n");
} }
str_append(r, "\n\n"); str_append(r, "\n\n");
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment