diff mbox series

docs: kconfig: Mention IS_REACHABLE as way for optional dependency

Message ID 20250215114223.140688-1-krzysztof.kozlowski@linaro.org (mailing list archive)
State New
Headers show
Series docs: kconfig: Mention IS_REACHABLE as way for optional dependency | expand

Commit Message

Krzysztof Kozlowski Feb. 15, 2025, 11:42 a.m. UTC
Several drivers express optional Kconfig dependency with FOO || !FOO,
but for many choices this is neither suitable (lack of stubs for !FOO
like in HWMON) nor really needed and driver can be built in even if FOO
is the module.  This is achieved with IS_REACHABLE, so provide cross
reference to it.

Cc: Masahiro Yamada <masahiroy@kernel.org>
Cc: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
---
 Documentation/kbuild/kconfig-language.rst | 13 ++++++++++---
 1 file changed, 10 insertions(+), 3 deletions(-)

Comments

Krzysztof Kozlowski Feb. 15, 2025, 12:44 p.m. UTC | #1
On 15/02/2025 12:42, Krzysztof Kozlowski wrote:
> @@ -580,10 +582,15 @@ Some drivers are able to optionally use a feature from another module
>  or build cleanly with that module disabled, but cause a link failure
>  when trying to use that loadable module from a built-in driver.
>  
> -The most common way to express this optional dependency in Kconfig logic
> -uses the slightly counterintuitive::
> +There are two ways to express this optional dependency:
>  
> -  config FOO
> +1. If pre-processor can discard entire optional code or module FOO does not
> +   provide !FOO stubs then in the C code :ref:`IS_REACHABLE<is_reachable>`
> +
> +2. Otherwise (and module FOO must provide all !FOO stubs) use the slightly

Obviously this should be "module BAR", similarly above.

I will send a v2.

> +   counterintuitive Kconfig syntax::
> +
> +     config FOO
>  	tristate "Support for foo hardware"
>  	depends on BAR || !BAR
>  


Best regards,
Krzysztof
Masahiro Yamada Feb. 15, 2025, 12:54 p.m. UTC | #2
On Sat, Feb 15, 2025 at 8:42 PM Krzysztof Kozlowski
<krzysztof.kozlowski@linaro.org> wrote:
>
> Several drivers express optional Kconfig dependency with FOO || !FOO,
> but for many choices this is neither suitable (lack of stubs for !FOO
> like in HWMON) nor really needed and driver can be built in even if FOO
> is the module.  This is achieved with IS_REACHABLE, so provide cross
> reference to it.
>
> Cc: Masahiro Yamada <masahiroy@kernel.org>
> Cc: Arnd Bergmann <arnd@arndb.de>
> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> ---
>  Documentation/kbuild/kconfig-language.rst | 13 ++++++++++---
>  1 file changed, 10 insertions(+), 3 deletions(-)
>
> diff --git a/Documentation/kbuild/kconfig-language.rst b/Documentation/kbuild/kconfig-language.rst
> index 2619fdf56e68..66248294a552 100644
> --- a/Documentation/kbuild/kconfig-language.rst
> +++ b/Documentation/kbuild/kconfig-language.rst
> @@ -194,6 +194,8 @@ applicable everywhere (see syntax).
>    ability to hook into a secondary subsystem while allowing the user to
>    configure that subsystem out without also having to unset these drivers.
>
> +.. _is_reachable:

Instead of this, could you move this hunk below ?





>    Note: If the combination of FOO=y and BAZ=m causes a link error,
>    you can guard the function call with IS_REACHABLE()::
>
> @@ -580,10 +582,15 @@ Some drivers are able to optionally use a feature from another module
>  or build cleanly with that module disabled, but cause a link failure
>  when trying to use that loadable module from a built-in driver.
>
> -The most common way to express this optional dependency in Kconfig logic
> -uses the slightly counterintuitive::
> +There are two ways to express this optional dependency:
>
> -  config FOO
> +1. If pre-processor can discard entire optional code or module FOO does not
> +   provide !FOO stubs then in the C code :ref:`IS_REACHABLE<is_reachable>`

Instead of the link, please move the code example at line 200 to here.

The note at line 197 is not strongly related to the 'imply' keyword.


One more thing, please document the drawback of IS_REACHABLE.

It is true that IS_REACHABLE() resolves the link error, but we
will end up with run-time debugging.

foo_init()
{
        if (IS_REACHABLE(CONFIG_BAZ))
                baz_register(&foo);
        ...
}

Even if CONFIG_BAZ is enabled, baz_register() may get discarded.
Users may scratch their head why baz_register() does not work.
Due to this reason, IS_REACHABLE() tends to be avoided.


"depends on BAR || !BAR" is configuration-time debugging.


> +
> +2. Otherwise (and module FOO must provide all !FOO stubs) use the slightly
> +   counterintuitive Kconfig syntax::
> +
> +     config FOO
>         tristate "Support for foo hardware"
>         depends on BAR || !BAR
>
> --
> 2.43.0
>
Krzysztof Kozlowski Feb. 15, 2025, 1:01 p.m. UTC | #3
On 15/02/2025 13:54, Masahiro Yamada wrote:
> On Sat, Feb 15, 2025 at 8:42 PM Krzysztof Kozlowski
> <krzysztof.kozlowski@linaro.org> wrote:
>>
>> Several drivers express optional Kconfig dependency with FOO || !FOO,
>> but for many choices this is neither suitable (lack of stubs for !FOO
>> like in HWMON) nor really needed and driver can be built in even if FOO
>> is the module.  This is achieved with IS_REACHABLE, so provide cross
>> reference to it.
>>
>> Cc: Masahiro Yamada <masahiroy@kernel.org>
>> Cc: Arnd Bergmann <arnd@arndb.de>
>> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
>> ---
>>  Documentation/kbuild/kconfig-language.rst | 13 ++++++++++---
>>  1 file changed, 10 insertions(+), 3 deletions(-)
>>
>> diff --git a/Documentation/kbuild/kconfig-language.rst b/Documentation/kbuild/kconfig-language.rst
>> index 2619fdf56e68..66248294a552 100644
>> --- a/Documentation/kbuild/kconfig-language.rst
>> +++ b/Documentation/kbuild/kconfig-language.rst
>> @@ -194,6 +194,8 @@ applicable everywhere (see syntax).
>>    ability to hook into a secondary subsystem while allowing the user to
>>    configure that subsystem out without also having to unset these drivers.
>>
>> +.. _is_reachable:
> 
> Instead of this, could you move this hunk below ?
> 

Ack

> 
> 
> 
> 
>>    Note: If the combination of FOO=y and BAZ=m causes a link error,
>>    you can guard the function call with IS_REACHABLE()::
>>
>> @@ -580,10 +582,15 @@ Some drivers are able to optionally use a feature from another module
>>  or build cleanly with that module disabled, but cause a link failure
>>  when trying to use that loadable module from a built-in driver.
>>
>> -The most common way to express this optional dependency in Kconfig logic
>> -uses the slightly counterintuitive::
>> +There are two ways to express this optional dependency:
>>
>> -  config FOO
>> +1. If pre-processor can discard entire optional code or module FOO does not
>> +   provide !FOO stubs then in the C code :ref:`IS_REACHABLE<is_reachable>`
> 
> Instead of the link, please move the code example at line 200 to here.
> 
> The note at line 197 is not strongly related to the 'imply' keyword.
> 
> 
> One more thing, please document the drawback of IS_REACHABLE.

Ack

> 
> It is true that IS_REACHABLE() resolves the link error, but we
> will end up with run-time debugging.
> 
> foo_init()
> {
>         if (IS_REACHABLE(CONFIG_BAZ))
>                 baz_register(&foo);
>         ...
> }
> 
> Even if CONFIG_BAZ is enabled, baz_register() may get discarded.

Hm, why would that happen? For compiler this would be "if(true)", so
what case would lead to discarding?

> Users may scratch their head why baz_register() does not work.
> Due to this reason, IS_REACHABLE() tends to be avoided.

I would rather say IS_REACHABLE should be avoided if someone really
wants to document the dependency, not optional feature.

> 
> 
> "depends on BAR || !BAR" is configuration-time debugging.
> 



Best regards,
Krzysztof
Krzysztof Kozlowski Feb. 15, 2025, 1:06 p.m. UTC | #4
On 15/02/2025 14:01, Krzysztof Kozlowski wrote:
>> One more thing, please document the drawback of IS_REACHABLE.
> 
> Ack
> 
>>
>> It is true that IS_REACHABLE() resolves the link error, but we
>> will end up with run-time debugging.
>>
>> foo_init()
>> {
>>         if (IS_REACHABLE(CONFIG_BAZ))
>>                 baz_register(&foo);
>>         ...
>> }
>>
>> Even if CONFIG_BAZ is enabled, baz_register() may get discarded.
> 
> Hm, why would that happen? For compiler this would be "if(true)", so
> what case would lead to discarding?
> 
>> Users may scratch their head why baz_register() does not work.
>> Due to this reason, IS_REACHABLE() tends to be avoided.
> 
> I would rather say IS_REACHABLE should be avoided if someone really
> wants to document the dependency, not optional feature.
I hope I got your intention right below:



@@ -580,15 +570,31 @@ Some drivers are able to optionally use a feature from another module
-The most common way to express this optional dependency in Kconfig logic
-uses the slightly counterintuitive::
+There are two ways to express this optional dependency:
 
-  config FOO
+1. If pre-processor can discard entire optional code or module BAR does not
+   provide !BAR stubs then call can be guarded with IS_REACHABLE()::
+
+       foo_init()
+       {
+               if (IS_REACHABLE(CONFIG_BAR))
+                       bar_register(&foo);
+               ...
+       }
+
+   Drawback: this might lead to run-time debugging, when looking why
+   bar_register() was not called.
+
+2. Otherwise (and module BAR must provide all !BAR stubs) use the slightly
+   counterintuitive Kconfig syntax::
+
+     config FOO
        tristate "Support for foo hardware"
        depends on BAR || !BAR
 
 This means that there is either a dependency on BAR that disallows
-the combination of FOO=y with BAR=m, or BAR is completely disabled.
+the combination of FOO=y with BAR=m, or BAR is completely disabled.  Unlike
+IS_REACHABLE(), this option favors configuration-time debugging.
 For a more formalized approach if there are multiple drivers that have
 the same dependency, a helper symbol can be used, like::




Best regards,
Krzysztof
Masahiro Yamada Feb. 15, 2025, 2:19 p.m. UTC | #5
On Sat, Feb 15, 2025 at 10:02 PM Krzysztof Kozlowski
<krzysztof.kozlowski@linaro.org> wrote:
>
> On 15/02/2025 13:54, Masahiro Yamada wrote:
> > On Sat, Feb 15, 2025 at 8:42 PM Krzysztof Kozlowski
> > <krzysztof.kozlowski@linaro.org> wrote:
> >>
> >> Several drivers express optional Kconfig dependency with FOO || !FOO,
> >> but for many choices this is neither suitable (lack of stubs for !FOO
> >> like in HWMON) nor really needed and driver can be built in even if FOO
> >> is the module.  This is achieved with IS_REACHABLE, so provide cross
> >> reference to it.
> >>
> >> Cc: Masahiro Yamada <masahiroy@kernel.org>
> >> Cc: Arnd Bergmann <arnd@arndb.de>
> >> Signed-off-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
> >> ---
> >>  Documentation/kbuild/kconfig-language.rst | 13 ++++++++++---
> >>  1 file changed, 10 insertions(+), 3 deletions(-)
> >>
> >> diff --git a/Documentation/kbuild/kconfig-language.rst b/Documentation/kbuild/kconfig-language.rst
> >> index 2619fdf56e68..66248294a552 100644
> >> --- a/Documentation/kbuild/kconfig-language.rst
> >> +++ b/Documentation/kbuild/kconfig-language.rst
> >> @@ -194,6 +194,8 @@ applicable everywhere (see syntax).
> >>    ability to hook into a secondary subsystem while allowing the user to
> >>    configure that subsystem out without also having to unset these drivers.
> >>
> >> +.. _is_reachable:
> >
> > Instead of this, could you move this hunk below ?
> >
>
> Ack
>
> >
> >
> >
> >
> >>    Note: If the combination of FOO=y and BAZ=m causes a link error,
> >>    you can guard the function call with IS_REACHABLE()::
> >>
> >> @@ -580,10 +582,15 @@ Some drivers are able to optionally use a feature from another module
> >>  or build cleanly with that module disabled, but cause a link failure
> >>  when trying to use that loadable module from a built-in driver.
> >>
> >> -The most common way to express this optional dependency in Kconfig logic
> >> -uses the slightly counterintuitive::
> >> +There are two ways to express this optional dependency:
> >>
> >> -  config FOO
> >> +1. If pre-processor can discard entire optional code or module FOO does not
> >> +   provide !FOO stubs then in the C code :ref:`IS_REACHABLE<is_reachable>`
> >
> > Instead of the link, please move the code example at line 200 to here.
> >
> > The note at line 197 is not strongly related to the 'imply' keyword.
> >
> >
> > One more thing, please document the drawback of IS_REACHABLE.
>
> Ack
>
> >
> > It is true that IS_REACHABLE() resolves the link error, but we
> > will end up with run-time debugging.
> >
> > foo_init()
> > {
> >         if (IS_REACHABLE(CONFIG_BAZ))
> >                 baz_register(&foo);
> >         ...
> > }
> >
> > Even if CONFIG_BAZ is enabled, baz_register() may get discarded.
>
> Hm, why would that happen? For compiler this would be "if(true)", so
> what case would lead to discarding?



Let's say this code hunk exists in foo-init.c
and it is compiled by CONFIG_FOO.

  obj-$(CONFIG_FOO) += foo-init.o

If you see the top Makefile, 'MODULE' is defined only when
this code is compiled as a module.

   KBUILD_CFLAGS_MODULE  := -DMODULE

For the combination of CONFIG_FOO=y and CONFIG_BAZ=m,

   IS_BUILTIN(CONFIG_BAZ) is 0
   IS_MODULE(CONFIG_BAZ) is 1
   __is_defined(MODULE) is 0

Hence, IS_REACHABLE(CONFIG_BAZ) is 0

This code becomes

   if (0)
          baz_register(&foo);


and the compiler will optimize out this function call.



--
Best Regards
Masahiro Yamada
diff mbox series

Patch

diff --git a/Documentation/kbuild/kconfig-language.rst b/Documentation/kbuild/kconfig-language.rst
index 2619fdf56e68..66248294a552 100644
--- a/Documentation/kbuild/kconfig-language.rst
+++ b/Documentation/kbuild/kconfig-language.rst
@@ -194,6 +194,8 @@  applicable everywhere (see syntax).
   ability to hook into a secondary subsystem while allowing the user to
   configure that subsystem out without also having to unset these drivers.
 
+.. _is_reachable:
+
   Note: If the combination of FOO=y and BAZ=m causes a link error,
   you can guard the function call with IS_REACHABLE()::
 
@@ -580,10 +582,15 @@  Some drivers are able to optionally use a feature from another module
 or build cleanly with that module disabled, but cause a link failure
 when trying to use that loadable module from a built-in driver.
 
-The most common way to express this optional dependency in Kconfig logic
-uses the slightly counterintuitive::
+There are two ways to express this optional dependency:
 
-  config FOO
+1. If pre-processor can discard entire optional code or module FOO does not
+   provide !FOO stubs then in the C code :ref:`IS_REACHABLE<is_reachable>`
+
+2. Otherwise (and module FOO must provide all !FOO stubs) use the slightly
+   counterintuitive Kconfig syntax::
+
+     config FOO
 	tristate "Support for foo hardware"
 	depends on BAR || !BAR