build/kconfig/tips.html · build/kconfig/tips.rst 공식 원문 ↗

Zephyr 3.7.0 · Build · Kconfig

Kconfig tip과 best practice

유효한 configuration을 유지하고 읽기 쉬운 Kconfig를 작성하는 실전 지침입니다.

Official pathbuild/kconfig/tips.html
Source filebuild/kconfig/tips.rst
Source versionZephyr 3.7.0
TranslationFull · reviewed

본문 기준: Zephyr 3.7.0 LTS3 · 이후 유지보수 패치는 별도입니다.

Part 1

요약·해설

select 위험, hidden symbol, dependency factoring, shorthand, imply·optional·visible if를 49개 예제로 설명합니다.

Hardware

Devicetree 우선

Dependency

depends on

Helper

select

Advanced

imply · visible if

Part 2

접을 수 있는 영어 원문 전체

영어 원문 전체 펼치기
원문 SHA-256 0B2AAAC9C6509D0FAA366FA7E3329B0760D61C75F186A30C79BC7E71F854F459
.. _kconfig_tips_and_tricks:

Kconfig - Tips and Best Practices
#################################

This page covers some Kconfig best practices and explains some Kconfig
behaviors and features that might be cryptic or that are easily overlooked.

.. note::

   The official Kconfig documentation is `kconfig-language.rst
   <https://www.kernel.org/doc/html/latest/kbuild/kconfig-language.html>`__
   and `kconfig-macro-language.rst
   <https://www.kernel.org/doc/html/latest/kbuild/kconfig-macro-language.html>`__.

.. contents::
   :local:
   :depth: 2


What to turn into Kconfig options
*********************************

When deciding whether something belongs in Kconfig, it helps to distinguish
between symbols that have prompts and symbols that don't.

If a symbol has a prompt (e.g. ``bool "Enable foo"``), then the user can change
the symbol's value in the ``menuconfig`` or ``guiconfig`` interface (see
:ref:`menuconfig`), or by manually editing configuration files. Conversely, a
symbol without a prompt can never be changed directly by the user, not even by
manually editing configuration files.

Only put a prompt on a symbol if it makes sense for the user to change its
value.

Symbols without prompts are called *hidden* or *invisible* symbols, because
they don't show up in ``menuconfig`` and ``guiconfig``. Symbols that have
prompts can also be invisible, when their dependencies are not satisfied.

Symbols without prompts can't be configured directly by the user (they derive
their value from other symbols), so less restrictions apply to them. If some
derived setting is easier to calculate in Kconfig than e.g. during the build,
then do it in Kconfig, but keep the distinction between symbols with and
without prompts in mind.

See the `optional prompts`_ section for a way to deal with settings that are
fixed on some machines and configurable on other machines.

What not to turn into Kconfig options
*************************************

In Zephyr, Kconfig configuration is done after selecting a target board. In
general, it does not make sense to use Kconfig for a value that corresponds to
a fixed machine-specific setting. Usually, such settings should be handled via
:ref:`devicetree <dt-guide>` instead.

In particular, avoid adding new Kconfig options of the following types:

Options that specify a device in the system by name
===================================================

For example, if you are writing an I2C device driver, avoid creating an option
named ``MY_DEVICE_I2C_BUS_NAME`` for specifying the bus node your device is
controlled by. See :ref:`dt-drivers-that-depend` for alternatives.

Similarly, if your application depends on a hardware-specific PWM device to
control an RGB LED, avoid creating an option like ``MY_PWM_DEVICE_NAME``. See
:ref:`dt-apps-that-depend` for alternatives.

Options that specify fixed hardware configuration
=================================================

For example, avoid Kconfig options specifying a GPIO pin.

An alternative applicable to device drivers is to define a GPIO specifier with
type phandle-array in the device binding, and using the
:ref:`devicetree-gpio-api` devicetree API from C. Similar advice applies to
other cases where devicetree.h provides :ref:`devicetree-hw-api` for referring
to other nodes in the system. Search the source code for drivers using these
APIs for examples.

An application-specific devicetree :ref:`binding <dt-bindings>` to identify
board specific properties may be appropriate. See
:zephyr_file:`tests/drivers/gpio/gpio_basic_api` for an example.

For applications, see :zephyr:code-sample:`blinky` for a devicetree-based alternative.

``select`` statements
*********************

The ``select`` statement is used to force one symbol to ``y`` whenever another
symbol is ``y``. For example, the following code forces ``CONSOLE`` to ``y``
whenever ``USB_CONSOLE`` is ``y``:

.. code-block:: kconfig

   config CONSOLE
   	bool "Console support"

   ...

   config USB_CONSOLE
   	bool "USB console support"
   	select CONSOLE

This section covers some pitfalls and good uses for ``select``.


``select`` pitfalls
===================

``select`` might seem like a generally useful feature at first, but can cause
configuration issues if overused.

For example, say that a new dependency is added to the ``CONSOLE`` symbol
above, by a developer who is unaware of the ``USB_CONSOLE`` symbol (or simply
forgot about it):

.. code-block:: kconfig

   config CONSOLE
   	bool "Console support"
   	depends on STRING_ROUTINES

Enabling ``USB_CONSOLE`` now forces ``CONSOLE`` to ``y``, even if
``STRING_ROUTINES`` is ``n``.

To fix the problem, the ``STRING_ROUTINES`` dependency needs to be added to
``USB_CONSOLE`` as well:

.. code-block:: kconfig

   config USB_CONSOLE
   	bool "USB console support"
   	select CONSOLE
   	depends on STRING_ROUTINES

   ...

   config STRING_ROUTINES
   	bool "Include string routines"

More insidious cases with dependencies inherited from ``if`` and ``menu``
statements are common.

An alternative attempt to solve the issue might be to turn the ``depends on``
into another ``select``:

.. code-block:: kconfig

   config CONSOLE
   	bool "Console support"
   	select STRING_ROUTINES

   ...

   config USB_CONSOLE
   	bool "USB console support"
   	select CONSOLE

In practice, this often amplifies the problem, because any dependencies added
to ``STRING_ROUTINES`` now need to be copied to both ``CONSOLE`` and
``USB_CONSOLE``.

In general, whenever the dependencies of a symbol are updated, the dependencies
of all symbols that (directly or indirectly) select it have to be updated as
well. This is very often overlooked in practice, even for the simplest case
above.

Chains of symbols selecting each other should be avoided in particular, except
for simple helper symbols, as covered below in :ref:`good_select_use`.

Liberal use of ``select`` also tends to make Kconfig files harder to read, both
due to the extra dependencies and due to the non-local nature of ``select``,
which hides ways in which a symbol might get enabled.


Alternatives to ``select``
==========================

For the example in the previous section, a better solution is usually to turn
the ``select`` into a ``depends on``:

.. code-block:: kconfig

   config CONSOLE
   	bool "Console support"

   ...

   config USB_CONSOLE
   	bool "USB console support"
   	depends on CONSOLE

This makes it impossible to generate an invalid configuration, and means that
dependencies only ever have to be updated in a single spot.

An objection to using ``depends on`` here might be that configuration files
that enable ``USB_CONSOLE`` now also need to enable ``CONSOLE``:

.. code-block:: cfg

   CONFIG_CONSOLE=y
   CONFIG_USB_CONSOLE=y

This comes down to a trade-off, but if enabling ``CONSOLE`` is the norm, then a
mitigation is to make ``CONSOLE`` default to ``y``:

.. code-block:: kconfig

   config CONSOLE
   	bool "Console support"
   	default y

This gives just a single assignment in configuration files:

.. code-block:: cfg

   CONFIG_USB_CONSOLE=y

Note that configuration files that do not want ``CONSOLE`` enabled now have to
explicitly disable it:

.. code-block:: cfg

   CONFIG_CONSOLE=n


.. _good_select_use:

Using ``select`` for helper symbols
===================================

A good and safe use of ``select`` is for setting "helper" symbols that capture
some condition. Such helper symbols should preferably have no prompt or
dependencies.

For example, a helper symbol for indicating that a particular CPU/SoC has an
FPU could be defined as follows:

.. code-block:: kconfig

   config CPU_HAS_FPU
   	bool
   	help
   	  If y, the CPU has an FPU

   ...

   config SOC_FOO
   	bool "FOO SoC"
   	select CPU_HAS_FPU

   ...

   config SOC_BAR
   	bool "BAR SoC"
   	select CPU_HAS_FPU

This makes it possible for other symbols to check for FPU support in a generic
way, without having to look for particular architectures:

.. code-block:: kconfig

   config FPU
   	bool "Support floating point operations"
   	depends on CPU_HAS_FPU

The alternative would be to have dependencies like the following, possibly
duplicated in several spots:

.. code-block:: kconfig

   config FPU
   	bool "Support floating point operations"
   	depends on SOC_FOO || SOC_BAR || ...

Invisible helper symbols can also be useful without ``select``. For example,
the following code defines a helper symbol that has the value ``y`` if the
machine has some arbitrarily-defined "large" amount of memory:

.. code-block:: kconfig

   config LARGE_MEM
   	def_bool MEM_SIZE >= 64

.. note::

   This is short for the following:

   .. code-block:: kconfig

      config LARGE_MEM
      	bool
      	default MEM_SIZE >= 64


``select`` recommendations
==========================

In summary, here are some recommended practices for ``select``:

- Avoid selecting symbols with prompts or dependencies. Prefer ``depends on``.
  If ``depends on`` causes annoying bloat in configuration files, consider
  adding a Kconfig default for the most common value.

  Rare exceptions might include cases where you're sure that the dependencies
  of the selecting and selected symbol will never drift out of sync, e.g. when
  dealing with two simple symbols defined close to one another within the same
  ``if``.

  Common sense applies, but be aware that ``select`` often causes issues in
  practice. ``depends on`` is usually a cleaner and safer solution.

- Select simple helper symbols without prompts and dependencies however much
  you like. They're a great tool for simplifying Kconfig files.

- An exemption are buses like I2C and SPI, and following the same thought
  process things like MFD as well. Drivers on these buses should use
  ``select`` to allow the automatic activation of the necessary bus drivers
  when devices on the bus are enabled in the devicetree.

.. code-block:: kconfig

   config ADC_FOO
      bool "external SPI ADC foo driver"
      select SPI

(Lack of) conditional includes
******************************

``if`` blocks add dependencies to each item within the ``if``, as if ``depends
on`` was used.

A common misunderstanding related to ``if`` is to think that the following code
conditionally includes the file :file:`Kconfig.other`:

.. code-block:: kconfig

   if DEP
   source "Kconfig.other"
   endif

In reality, there are no conditional includes in Kconfig. ``if`` has no special
meaning around a ``source``.

.. note::

   Conditional includes would be impossible to implement, because ``if``
   conditions may contain (either directly or indirectly) forward references to
   symbols that haven't been defined yet.

Say that :file:`Kconfig.other` above contains this definition:

.. code-block:: kconfig

   config FOO
   	bool "Support foo"

In this case, ``FOO`` will end up with this definition:

.. code-block:: kconfig

   config FOO
   	bool "Support foo"
   	depends on DEP

Note that it is redundant to add ``depends on DEP`` to the definition of
``FOO`` in :file:`Kconfig.other`, because the ``DEP`` dependency has already
been added by ``if DEP``.

In general, try to avoid adding redundant dependencies. They can make the
structure of the Kconfig files harder to understand, and also make changes more
error-prone, since it can be hard to spot that the same dependency is added
twice.


"Stuck" symbols in menuconfig and guiconfig
*******************************************

There is a common subtle gotcha related to interdependent configuration symbols
with prompts. Consider these symbols:

.. code-block:: kconfig

   config FOO
   	bool "Foo"

   config STACK_SIZE
   	hex "Stack size"
   	default 0x200 if FOO
   	default 0x100

Assume that the intention here is to use a larger stack whenever ``FOO`` is
enabled, and that the configuration initially has ``FOO`` disabled. Also,
remember that Zephyr creates an initial configuration in :file:`zephyr/.config`
in the build directory by merging configuration files (including e.g.
:file:`prj.conf`). This configuration file exists before
``menuconfig`` or ``guiconfig`` is run.

When first entering the configuration interface, the value of ``STACK_SIZE`` is
0x100, as expected. After enabling ``FOO``, you might reasonably expect the
value of ``STACK_SIZE`` to change to 0x200, but it stays as 0x100.

To understand what's going on, remember that ``STACK_SIZE`` has a prompt,
meaning it is user-configurable, and consider that all Kconfig has to go on
from the initial configuration is this:

.. code-block:: cfg

   CONFIG_STACK_SIZE=0x100

Since Kconfig can't know if the 0x100 value came from a ``default`` or was
typed in by the user, it has to assume that it came from the user. Since
``STACK_SIZE`` is user-configurable, the value from the configuration file is
respected, and any symbol defaults are ignored. This is why the value of
``STACK_SIZE`` appears to be "frozen" at 0x100 when toggling ``FOO``.

The right fix depends on what the intention is. Here's some different scenarios
with suggestions:

- If ``STACK_SIZE`` can always be derived automatically and does not need to be
  user-configurable, then just remove the prompt:

  .. code-block:: kconfig

     config STACK_SIZE
     	hex
     	default 0x200 if FOO
     	default 0x100

  Symbols without prompts ignore any value from the saved configuration.

- If ``STACK_SIZE`` should usually be user-configurable, but needs to be set to
  0x200 when ``FOO`` is enabled, then disable its prompt when ``FOO`` is
  enabled, as described in `optional prompts`_:

  .. code-block:: kconfig

     config STACK_SIZE
     	hex "Stack size" if !FOO
     	default 0x200 if FOO
     	default 0x100

- If ``STACK_SIZE`` should usually be derived automatically, but needs to be
  set to a custom value in rare circumstances, then add another option for
  making ``STACK_SIZE`` user-configurable:

  .. code-block:: kconfig

     config CUSTOM_STACK_SIZE
     	bool "Use a custom stack size"
     	help
     	  Enable this if you need to use a custom stack size. When disabled, a
     	  suitable stack size is calculated automatically.

     config STACK_SIZE
     	hex "Stack size" if CUSTOM_STACK_SIZE
     	default 0x200 if FOO
     	default 0x100

  As long as ``CUSTOM_STACK_SIZE`` is disabled, ``STACK_SIZE`` will ignore the
  value from the saved configuration.

It is a good idea to try out changes in the ``menuconfig`` or ``guiconfig``
interface, to make sure that things behave the way you expect. This is
especially true when making moderately complex changes like these.


Assignments to promptless symbols in configuration files
********************************************************

Assignments to hidden (promptless, also called *invisible*) symbols in
configuration files are always ignored. Hidden symbols get their value
indirectly from other symbols, via e.g. ``default`` and ``select``.

A common source of confusion is opening the output configuration file
(:file:`zephyr/.config`), seeing a bunch of assignments to hidden symbols,
and assuming that those assignments must be respected when the configuration is
read back in by Kconfig. In reality, all assignments to hidden symbols in
:file:`zephyr/.config` are ignored by Kconfig, like for other configuration
files.

To understand why :file:`zephyr/.config` still includes assignments to hidden
symbols, it helps to realize that :file:`zephyr/.config` serves two separate
purposes:

1. It holds the saved configuration, and

2. it holds configuration output. :file:`zephyr/.config` is parsed by the CMake
   files to let them query configuration settings, for example.

The assignments to hidden symbols in :file:`zephyr/.config` are just
configuration output. Kconfig itself ignores assignments to hidden symbols when
calculating symbol values.

.. note::

   A *minimal configuration*, which can be generated from within the
   :ref:`menuconfig and guiconfig interfaces <menuconfig>`, could be considered
   closer to just a saved configuration, without the full configuration output.


``depends on`` and ``string``/``int``/``hex`` symbols
*****************************************************

``depends on`` works not just for ``bool`` symbols, but also for ``string``,
``int``, and ``hex`` symbols (and for choices).

The Kconfig definitions below will hide the ``FOO_DEVICE_FREQUENCY`` symbol and
disable any configuration output for it when ``FOO_DEVICE`` is disabled.

.. code-block:: kconfig

   config FOO_DEVICE
   	bool "Foo device"

   config FOO_DEVICE_FREQUENCY
   	int "Foo device frequency"
   	depends on FOO_DEVICE

In general, it's a good idea to check that only relevant symbols are ever shown
in the ``menuconfig``/``guiconfig`` interface. Having ``FOO_DEVICE_FREQUENCY``
show up when ``FOO_DEVICE`` is disabled (and possibly hidden) makes the
relationship between the symbols harder to understand, even if code never looks
at ``FOO_DEVICE_FREQUENCY`` when ``FOO_DEVICE`` is disabled.


``menuconfig`` symbols
**********************

If the definition of a symbol ``FOO`` is immediately followed by other symbols
that depend on ``FOO``, then those symbols become children of ``FOO``. If
``FOO`` is defined with ``config FOO``, then the children are shown indented
relative to ``FOO``. Defining ``FOO`` with ``menuconfig FOO`` instead puts the
children in a separate menu rooted at ``FOO``.

``menuconfig`` has no effect on evaluation. It's just a display option.

``menuconfig`` can cut down on the number of menus and make the menu structure
easier to navigate. For example, say you have the following definitions:

.. code-block:: kconfig

   menu "Foo subsystem"

   config FOO_SUBSYSTEM
   	bool "Foo subsystem"

   if FOO_SUBSYSTEM

   config FOO_FEATURE_1
   	bool "Foo feature 1"

   config FOO_FEATURE_2
   	bool "Foo feature 2"

   config FOO_FREQUENCY
   	int "Foo frequency"

   ... lots of other FOO-related symbols

   endif # FOO_SUBSYSTEM

   endmenu

In this case, it's probably better to get rid of the ``menu`` and turn
``FOO_SUBSYSTEM`` into a ``menuconfig`` symbol:

.. code-block:: kconfig

   menuconfig FOO_SUBSYSTEM
   	bool "Foo subsystem"

   if FOO_SUBSYSTEM

   config FOO_FEATURE_1
   	bool "Foo feature 1"

   config FOO_FEATURE_2
   	bool "Foo feature 2"

   config FOO_FREQUENCY
   	int "Foo frequency"

   ... lots of other FOO-related symbols

   endif # FOO_SUBSYSTEM

In the ``menuconfig`` interface, this will be displayed as follows:

.. code-block:: none

   [*] Foo subsystem  --->

Note that making a symbol without children a ``menuconfig`` is meaningless. It
should be avoided, because it looks identical to a symbol with all children
invisible:

.. code-block:: none

   [*] I have no children  ----
   [*] All my children are invisible  ----


Commas in macro arguments
*************************

Kconfig uses commas to separate macro arguments.
This means a construct like this will fail:

.. code-block:: kconfig

    config FOO
        bool
        default y if $(dt_chosen_enabled,"zephyr,bar")

To solve this problem, create a variable with the text and use this variable as
argument, as follows:

.. code-block:: kconfig

    DT_CHOSEN_ZEPHYR_BAR := zephyr,bar

    config FOO
        bool
        default y if $(dt_chosen_enabled,$(DT_CHOSEN_ZEPHYR_BAR))


Checking changes in menuconfig/guiconfig
****************************************

When adding new symbols or making other changes to Kconfig files, it is a good
idea to look up the symbols in :ref:`menuconfig or guiconfig <menuconfig>`
afterwards. To get to a symbol quickly, use the jump-to feature (press
:kbd:`/`).

Here are some things to check:

* Are the symbols placed in a good spot? Check that they appear in a menu where
  they make sense, close to related symbols.

  If one symbol depends on another, then it's often a good idea to place it
  right after the symbol it depends on. It will then be shown indented relative
  to the symbol it depends on in the ``menuconfig`` interface, and in a
  separate menu rooted at the symbol in ``guiconfig``. This also works if
  several symbols are placed after the symbol they depend on.

* Is it easy to guess what the symbols do from their prompts?

* If many symbols are added, do all combinations of values they can be set to
  make sense?

  For example, if two symbols ``FOO_SUPPORT`` and ``NO_FOO_SUPPORT`` are added,
  and both can be enabled at the same time, then that makes a nonsensical
  configuration. In this case, it's probably better to have a single
  ``FOO_SUPPORT`` symbol.

* Are there any duplicated dependencies?

  This can be checked by selecting a symbol and pressing :kbd:`?` to view the
  symbol information. If there are duplicated dependencies, then use the
  ``Included via ...`` path shown in the symbol information to figure out where
  they come from.


Checking changes with :file:`scripts/kconfig/lint.py`
*****************************************************

After you make Kconfig changes, you can use the
:zephyr_file:`scripts/kconfig/lint.py` script to check for some potential
issues, like unused symbols and symbols that are impossible to enable. Use
``--help`` to see available options.

Some checks are necessarily a bit heuristic, so a symbol being flagged by a
check does not necessarily mean there's a problem. If a check returns a false
positive e.g. due to token pasting in C (``CONFIG_FOO_##index##_BAR``), just
ignore it.

When investigating an unknown symbol ``FOO_BAR``, it is a good idea to run
``git grep FOO_BAR`` to look for references. It is also a good idea to search
for some components of the symbol name with e.g. ``git grep FOO`` and
``git grep BAR``, as it can help uncover token pasting.


Style recommendations and shorthands
************************************

This section gives some style recommendations and explains some common Kconfig
shorthands.


Factoring out common dependencies
=================================

If a sequence of symbols/choices share a common dependency, the dependency can
be factored out with an ``if``.

As an example, consider the following code:

.. code-block:: kconfig

   config FOO
   	bool "Foo"
   	depends on DEP

   config BAR
   	bool "Bar"
   	depends on DEP

   choice
   	prompt "Choice"
   	depends on DEP

   config BAZ
   	bool "Baz"

   config QAZ
   	bool "Qaz"

   endchoice

Here, the ``DEP`` dependency can be factored out like this:

.. code-block:: kconfig

   if DEP

   config FOO
   	bool "Foo"

   config BAR
   	bool "Bar"

   choice
   	prompt "Choice"

   config BAZ
   	bool "Baz"

   config QAZ
   	bool "Qaz"

   endchoice

   endif # DEP

.. note::

   Internally, the second version of the code is transformed into the first.

If a sequence of symbols/choices with shared dependencies are all in the same
menu, the dependency can be put on the menu itself:

.. code-block:: kconfig

   menu "Foo features"
   	depends on FOO_SUPPORT

   config FOO_FEATURE_1
   	bool "Foo feature 1"

   config FOO_FEATURE_2
   	bool "Foo feature 2"

   endmenu

If ``FOO_SUPPORT`` is ``n``, the entire menu disappears.


Redundant defaults
==================

``bool`` symbols implicitly default to ``n``, and ``string`` symbols implicitly
default to the empty string. Therefore, ``default n`` and ``default ""`` are
(almost) always redundant.

The recommended style in Zephyr is to skip redundant defaults for ``bool`` and
``string`` symbols. That also generates clearer documentation: (*Implicitly
defaults to n* instead of *n if <dependencies, possibly inherited>*).

Defaults *should* always be given for ``int`` and ``hex`` symbols, however, as
they implicitly default to the empty string. This is partly for compatibility
with the C Kconfig tools, though an implicit 0 default might be less likely to
be what was intended compared to other symbol types as well.

The one case where ``default n``/``default ""`` is not redundant is when
defining a symbol in multiple locations and wanting to override e.g. a
``default y`` on a later definition. Note that a ``default n`` does not override
a previously defined ``default y``.

That is, FOO will be set to ``n`` in the example below. If the ``default n`` was
omitted in the first definition, FOO would have been set to ``y``.

  .. code-block:: kconfig

     config FOO
     	bool "foo"
     	default n

     config FOO
     	bool "foo"
     	default y

In the following example FOO will get the value ``y``.

  .. code-block:: kconfig

     config FOO
     	bool "foo"
     	default y

     config FOO
     	bool "foo"
     	default n

.. _kconfig_shorthands:

Common Kconfig shorthands
=========================

Kconfig has two shorthands that deal with prompts and defaults.

- ``<type> "prompt"`` is a shorthand for giving a symbol/choice a type and a
  prompt at the same time. These two definitions are equal:

  .. code-block:: kconfig

     config FOO
     	bool "foo"

  .. code-block:: kconfig

     config FOO
     	bool
     	prompt "foo"

  The first style, with the shorthand, is preferred in Zephyr.

- ``def_<type> <value>`` is a shorthand for giving a type and a value at the
  same time. These two definitions are equal:

  .. code-block:: kconfig

     config FOO
     	def_bool BAR && BAZ

  .. code-block:: kconfig

     config FOO
     	bool
     	default BAR && BAZ

Using both the ``<type> "prompt"`` and the ``def_<type> <value>`` shorthand in
the same definition is redundant, since it gives the type twice.

The ``def_<type> <value>`` shorthand is generally only useful for symbols
without prompts, and somewhat obscure.

.. note::

   For a symbol defined in multiple locations (e.g., in a ``Kconfig.defconfig``
   file in Zephyr), it is best to only give the symbol type for the "base"
   definition of the symbol, and to use ``default`` (instead of ``def_<type>
   value``) for the remaining definitions. That way, if the base definition of
   the symbol is removed, the symbol ends up without a type, which generates a
   warning that points to the other definitions. That makes the extra
   definitions easier to discover and remove.


Prompt strings
==============

For a Kconfig symbol that enables a driver/subsystem FOO, consider having just
"Foo" as the prompt, instead of "Enable Foo support" or the like. It will
usually be clear in the context of an option that can be toggled on/off, and
makes things consistent.


Header comments and other nits
==============================

A few formatting nits, to help keep things consistent:

- Use this format for any header comments at the top of ``Kconfig`` files:

  .. code-block:: none

     # <Overview of symbols defined in the file, preferably in plain English>
     (Blank line)
     # Copyright (c) 2019 ...
     # SPDX-License-Identifier: <License>
     (Blank line)
     (Kconfig definitions)

- Format comments as ``# Comment`` rather than ``#Comment``

- Put a blank line before/after each top-level ``if`` and ``endif``

- Use a single tab for each indentation

- Indent help text with two extra spaces


Lesser-known/used Kconfig features
**********************************

This section lists some more obscure Kconfig behaviors and features that might
still come in handy.


The ``imply`` statement
=======================

The ``imply`` statement is similar to ``select``, but respects dependencies and
doesn't force a value. For example, the following code could be used to enable
USB keyboard support by default on the FOO SoC, while still allowing the user
to turn it off:

.. code-block:: kconfig

   config SOC_FOO
   	bool "FOO SoC"
   	imply USB_KEYBOARD

   ...

   config USB_KEYBOARD
   	bool "USB keyboard support"

``imply`` acts like a suggestion, whereas ``select`` forces a value.


Optional prompts
================

A condition can be put on a symbol's prompt to make it optionally configurable
by the user. For example, a value ``MASK`` that's hardcoded to 0xFF on some
boards and configurable on others could be expressed as follows:

.. code-block:: kconfig

   config MASK
   	hex "Bitmask" if HAS_CONFIGURABLE_MASK
   	default 0xFF

.. note::

   This is short for the following:

   .. code-block:: kconfig

      config MASK
      	hex
      	prompt "Bitmask" if HAS_CONFIGURABLE_MASK
      	default 0xFF

The ``HAS_CONFIGURABLE_MASK`` helper symbol would get selected by boards to
indicate that ``MASK`` is configurable. When ``MASK`` is configurable, it will
also default to 0xFF.


Optional choices
================

Defining a choice with the ``optional`` keyword allows the whole choice to be
toggled off to select none of the symbols:

.. code-block:: kconfig

   choice
   	prompt "Use legacy protocol"
   	optional

   config LEGACY_PROTOCOL_1
   	bool "Legacy protocol 1"

   config LEGACY_PROTOCOL_2
   	bool "Legacy protocol 2"

   endchoice

In the ``menuconfig`` interface, this will be displayed e.g. as
``[*] Use legacy protocol (Legacy protocol 1) --->``, where the choice can be
toggled off to enable neither of the symbols.


``visible if`` conditions
=========================

Putting a ``visible if`` condition on a menu hides the menu and all the symbols
within it, while still allowing symbol default values to kick in.

As a motivating example, consider the following code:

.. code-block:: kconfig

   menu "Foo subsystem"
   	depends on HAS_CONFIGURABLE_FOO

   config FOO_SETTING_1
   	int "Foo setting 1"
   	default 1

   config FOO_SETTING_2
   	int "Foo setting 2"
   	default 2

   endmenu

When ``HAS_CONFIGURABLE_FOO`` is ``n``, no configuration output is generated
for ``FOO_SETTING_1`` and ``FOO_SETTING_2``, as the code above is logically
equivalent to the following code:

.. code-block:: kconfig

   config FOO_SETTING_1
   	int "Foo setting 1"
   	default 1
   	depends on HAS_CONFIGURABLE_FOO

   config FOO_SETTING_2
   	int "Foo setting 2"
   	default 2
   	depends on HAS_CONFIGURABLE_FOO

If we want the symbols to still get their default values even when
``HAS_CONFIGURABLE_FOO`` is ``n``, but not be configurable by the user, then we
can use ``visible if`` instead:

.. code-block:: kconfig

   menu "Foo subsystem"
   	visible if HAS_CONFIGURABLE_FOO

   config FOO_SETTING_1
   	int "Foo setting 1"
   	default 1

   config FOO_SETTING_2
   	int "Foo setting 2"
   	default 2

   endmenu

This is logically equivalent to the following:

.. code-block:: kconfig

   config FOO_SETTING_1
   	int "Foo setting 1" if HAS_CONFIGURABLE_FOO
   	default 1

   config FOO_SETTING_2
   	int "Foo setting 2" if HAS_CONFIGURABLE_FOO
   	default 2

.. note::

   See the `optional prompts`_ section for the meaning of the conditions on the
   prompts.

When ``HAS_CONFIGURABLE_FOO`` is ``n``, we now get the following configuration
output for the symbols, instead of no output:

.. code-block:: cfg

   ...
   CONFIG_FOO_SETTING_1=1
   CONFIG_FOO_SETTING_2=2
   ...


Other resources
***************

The *Intro to symbol values* section in the `Kconfiglib docstring
<https://github.com/ulfalizer/Kconfiglib/blob/master/kconfiglib.py>`__ goes
over how symbols values are calculated in more detail.

Part 3

한국어 전문 번역

Kconfig tip과 best practice

쉽게 놓치거나 이해하기 어려운 Kconfig behavior와 권장 작성법을 설명합니다. 언어 자체의 기준은 Linux의 kconfig-language.rst와 kconfig-macro-language.rst입니다.

무엇을 Kconfig option으로 만들 것인가

Prompt가 있는 symbol은 menuconfig·guiconfig 또는 configuration file에서 user가 값을 바꿀 수 있습니다. Prompt가 없는 hidden/invisible symbol은 직접 바꿀 수 없고 다른 symbol에서 값을 계산합니다. User가 값을 바꾸는 것이 의미 있을 때만 prompt를 붙이십시오.

Prompt가 있어도 dependency가 충족되지 않으면 invisible할 수 있습니다. Prompt 없는 derived setting은 build보다 Kconfig에서 계산하는 편이 쉬울 때 Kconfig에 둘 수 있지만, user-facing option과 내부 계산 symbol의 구분은 유지해야 합니다. Machine에 따라 고정되거나 configurable한 값은 optional prompt를 사용할 수 있습니다.

Kconfig option으로 만들지 말아야 할 것

Zephyr는 target board를 고른 뒤 Kconfig를 수행합니다. 고정된 machine-specific 값은 보통 Devicetree가 담당해야 합니다.

  • System device를 이름으로 지정하는 MY_DEVICE_I2C_BUS_NAME 또는 MY_PWM_DEVICE_NAME 같은 option을 만들지 마십시오. Driver와 application은 Devicetree 관계를 사용합니다.
  • GPIO pin 같은 고정 hardware configuration을 Kconfig로 만들지 마십시오. Binding의 phandle-array GPIO specifier와 C Devicetree API를 사용합니다.
  • Application-specific board property에는 application 전용 binding이 적절할 수 있습니다. GPIO basic test와 blinky sample이 예입니다.

select statement

select는 한 symbol이 y일 때 다른 symbol을 강제로 y로 만듭니다. 다음은 USB_CONSOLE이 CONSOLE을 select합니다.

config CONSOLE
	bool "Console support"

...

config USB_CONSOLE
	bool "USB console support"
	select CONSOLE

select의 함정

나중에 CONSOLE에 새 dependency가 추가되었다고 하겠습니다.

config CONSOLE
	bool "Console support"
	depends on STRING_ROUTINES

USB_CONSOLE을 enable하면 STRING_ROUTINES=n이어도 CONSOLE이 강제로 y가 됩니다. 이를 막으려면 selecting symbol에도 dependency를 복사해야 합니다.

config USB_CONSOLE
	bool "USB console support"
	select CONSOLE
	depends on STRING_ROUTINES

...

config STRING_ROUTINES
	bool "Include string routines"

if와 menu에서 상속된 dependency가 있으면 더 알아보기 어렵습니다. depends on을 또 다른 select로 바꾸는 해결책도 좋지 않습니다.

config CONSOLE
	bool "Console support"
	select STRING_ROUTINES

...

config USB_CONSOLE
	bool "USB console support"
	select CONSOLE

이제 STRING_ROUTINES의 dependency가 바뀔 때 CONSOLE과 USB_CONSOLE 모두를 갱신해야 합니다. 일반적으로 symbol dependency를 변경할 때 그 symbol을 직접·간접 select하는 모든 symbol의 dependency도 함께 바꿔야 하지만 실전에서 자주 누락됩니다. Helper symbol을 제외한 select chain은 피해야 하며, non-local activation 때문에 Kconfig file도 읽기 어려워집니다.

select 대신 depends on

config CONSOLE
	bool "Console support"

...

config USB_CONSOLE
	bool "USB console support"
	depends on CONSOLE

이 방식은 invalid configuration을 만들 수 없고 dependency를 한 위치에서만 관리합니다. 대신 configuration file에서 두 symbol을 모두 enable해야 합니다.

CONFIG_CONSOLE=y
CONFIG_USB_CONSOLE=y

CONSOLE을 enable하는 것이 일반적이라면 default를 y로 완화할 수 있습니다.

config CONSOLE
	bool "Console support"
	default y

그러면 application은 다음 assignment 하나만 필요합니다.

CONFIG_USB_CONSOLE=y

Console이 필요 없는 configuration만 명시적으로 끕니다.

CONFIG_CONSOLE=n

Helper symbol에 안전하게 select 사용

Prompt와 dependency가 없는 단순 helper symbol에 condition을 기록하는 것은 좋은 사용법입니다. 특정 CPU/SoC에 FPU가 있음을 나타내는 helper는 다음과 같습니다.

config CPU_HAS_FPU
	bool
	help
	  If y, the CPU has an FPU

...

config SOC_FOO
	bool "FOO SoC"
	select CPU_HAS_FPU

...

config SOC_BAR
	bool "BAR SoC"
	select CPU_HAS_FPU

다른 symbol은 architecture 이름을 나열하지 않고 generic helper에 의존합니다.

config FPU
	bool "Support floating point operations"
	depends on CPU_HAS_FPU

그렇지 않으면 여러 위치에서 SoC 목록을 반복해야 합니다.

config FPU
	bool "Support floating point operations"
	depends on SOC_FOO || SOC_BAR || ...

Invisible helper는 select 없이 계산할 수도 있습니다. 다음은 memory가 64 이상이면 y인 helper입니다.

config LARGE_MEM
	def_bool MEM_SIZE >= 64

이는 type과 default를 풀어 쓴 다음 정의의 shorthand입니다.

config LARGE_MEM
	bool
	default MEM_SIZE >= 64

select 권장 사항

  • Prompt나 dependency가 있는 symbol은 select하지 말고 depends on을 우선합니다. Configuration file이 길어지면 흔한 값에 default를 고려합니다.
  • Prompt와 dependency가 없는 simple helper symbol은 자유롭게 select해도 좋습니다.
  • I2C·SPI 같은 bus와 같은 원리의 MFD driver는 Devicetree에서 device가 enable될 때 필요한 bus driver를 자동 활성화하도록 select를 사용합니다.
config ADC_FOO
   bool "external SPI ADC foo driver"
   select SPI

Conditional include는 없다

if block은 내부 item마다 depends on을 추가합니다. 다음이 file을 조건부 include한다고 생각하기 쉽지만 그렇지 않습니다.

if DEP
source "Kconfig.other"
endif

Kconfig에는 conditional include가 없습니다. 아직 정의되지 않은 symbol을 forward reference할 수 있어 include 자체를 조건화하는 구현이 불가능하기 때문입니다. Included file에 다음 정의가 있다면:

config FOO
	bool "Support foo"

최종적으로 DEP dependency가 추가된 다음 정의와 같습니다.

config FOO
	bool "Support foo"
	depends on DEP

Included file 안에 depends on DEP을 다시 쓰는 것은 중복입니다. 중복 dependency는 구조를 이해하기 어렵게 하고 변경 시 누락을 만들기 쉬우므로 피합니다.

Menuconfig에서 값이 고정된 것처럼 보이는 symbol

서로 의존하는 prompt symbol에서 미묘한 문제가 생길 수 있습니다.

config FOO
	bool "Foo"

config STACK_SIZE
	hex "Stack size"
	default 0x200 if FOO
	default 0x100

처음 FOO=n이면 STACK_SIZE=0x100입니다. Interface에서 FOO를 enable해도 0x200으로 바뀌지 않고 0x100에 머물 수 있습니다. Interface 실행 전 merge된 zephyr/.config에는 다음 값이 이미 있기 때문입니다.

CONFIG_STACK_SIZE=0x100

Kconfig는 0x100이 default에서 왔는지 user가 직접 썼는지 알 수 없으므로 user assignment로 간주합니다. Prompt가 있는 user-configurable symbol은 saved configuration 값을 존중하고 default를 무시합니다.

의도에 따라 다음 중 하나로 해결합니다.

항상 자동 계산한다면 prompt 제거

config STACK_SIZE
	hex
	default 0x200 if FOO
	default 0x100

Prompt 없는 symbol은 saved configuration 값을 무시합니다.

보통 configurable하지만 FOO에서 0x200으로 고정한다면 conditional prompt

config STACK_SIZE
	hex "Stack size" if !FOO
	default 0x200 if FOO
	default 0x100

보통 자동이지만 드물게 custom 값이 필요하다면 별도 switch

config CUSTOM_STACK_SIZE
	bool "Use a custom stack size"
	help
	  Enable this if you need to use a custom stack size. When disabled, a
	  suitable stack size is calculated automatically.

config STACK_SIZE
	hex "Stack size" if CUSTOM_STACK_SIZE
	default 0x200 if FOO
	default 0x100

CUSTOM_STACK_SIZE=n인 동안 STACK_SIZE는 saved value를 무시합니다. 이런 중간 이상 복잡도의 변경은 menuconfig와 guiconfig에서 실제 behavior를 시험해야 합니다.

Prompt 없는 symbol의 assignment

Configuration file에서 hidden symbol에 준 assignment는 항상 무시됩니다. Hidden symbol은 default와 select 등으로 간접 값을 얻습니다.

zephyr/.config에 hidden symbol assignment가 보이는 이유는 이 file이 saved configuration과 configuration output 두 역할을 하기 때문입니다. CMake도 이 file을 parse해 설정을 조회합니다. Hidden assignment는 output일 뿐 Kconfig의 값 계산 입력으로는 무시됩니다. Interactive interface에서 만드는 minimal configuration은 전체 output을 제외한 saved configuration에 더 가깝습니다.

depends on과 non-boolean symbol

depends on은 bool뿐 아니라 string·int·hex symbol과 choice에도 적용됩니다. 다음은 FOO_DEVICE=n일 때 frequency symbol을 숨기고 output도 생성하지 않습니다.

config FOO_DEVICE
	bool "Foo device"

config FOO_DEVICE_FREQUENCY
	int "Foo device frequency"
	depends on FOO_DEVICE

관련 device가 꺼졌는데 frequency가 보이면 관계를 이해하기 어렵습니다. Code가 값을 읽지 않더라도 interface에는 relevant symbol만 표시하는 것이 좋습니다.

menuconfig symbol

FOO 바로 뒤에 FOO에 의존하는 symbol을 두면 child가 됩니다. config FOO면 child가 아래에 indent되고, menuconfig FOO면 FOO를 root로 하는 별도 menu에 들어갑니다. 값 계산에는 영향을 주지 않는 표시 option입니다.

다음처럼 별도 menu와 subsystem enable symbol을 둘 수도 있습니다.

menu "Foo subsystem"

config FOO_SUBSYSTEM
	bool "Foo subsystem"

if FOO_SUBSYSTEM

config FOO_FEATURE_1
	bool "Foo feature 1"

config FOO_FEATURE_2
	bool "Foo feature 2"

config FOO_FREQUENCY
	int "Foo frequency"

... lots of other FOO-related symbols

endif # FOO_SUBSYSTEM

endmenu

하지만 menu를 없애고 root symbol을 menuconfig로 바꾸면 구조가 더 간결합니다.

menuconfig FOO_SUBSYSTEM
	bool "Foo subsystem"

if FOO_SUBSYSTEM

config FOO_FEATURE_1
	bool "Foo feature 1"

config FOO_FEATURE_2
	bool "Foo feature 2"

config FOO_FREQUENCY
	int "Foo frequency"

... lots of other FOO-related symbols

endif # FOO_SUBSYSTEM

Terminal에서는 다음처럼 보입니다.

[*] Foo subsystem  --->

Child가 없는 symbol을 menuconfig로 만드는 것은 의미가 없고, 모든 child가 invisible한 symbol과 구분되지 않으므로 피합니다.

[*] I have no children  ----
[*] All my children are invisible  ----

Macro argument의 comma

Kconfig는 comma로 macro argument를 구분하므로 comma가 든 literal을 직접 넣으면 실패합니다.

 config FOO
     bool
     default y if $(dt_chosen_enabled,"zephyr,bar")

Text를 variable에 넣고 그 variable을 argument로 사용합니다.

 DT_CHOSEN_ZEPHYR_BAR := zephyr,bar

 config FOO
     bool
     default y if $(dt_chosen_enabled,$(DT_CHOSEN_ZEPHYR_BAR))

Menuconfig·guiconfig에서 변경 검토

새 symbol을 추가하거나 Kconfig를 바꾼 뒤에는 / jump-to로 각 symbol을 찾아 다음을 확인합니다.

  • 관련 symbol 가까이의 알맞은 menu 위치에 있는가
  • Prompt만 보고 역할을 짐작할 수 있는가
  • 추가한 symbol의 모든 값 조합이 의미 있는가. 반대 의미의 두 bool보다 bool 하나가 나을 수 있습니다.
  • 중복 dependency가 없는가. ? 정보의 Included via ... path로 출처를 찾습니다.

scripts/kconfig/lint.py 검사

Kconfig 변경 뒤 lint script로 unused symbol과 enable 불가능한 symbol 같은 잠재 문제를 찾습니다. Option은 --help로 확인합니다. 일부 검사는 heuristic이므로 C token pasting 같은 false positive는 무시할 수 있습니다. Unknown FOO_BAR는 git grep FOO_BAR뿐 아니라 이름 일부인 FOO, BAR도 검색해 token pasting을 찾습니다.

Style 권장 사항과 shorthand

공통 dependency 묶기

여러 symbol과 choice가 같은 dependency를 반복하면 if로 묶습니다. 원래 형태:

config FOO
	bool "Foo"
	depends on DEP

config BAR
	bool "Bar"
	depends on DEP

choice
	prompt "Choice"
	depends on DEP

config BAZ
	bool "Baz"

config QAZ
	bool "Qaz"

endchoice

공통 dependency를 factor out한 형태:

if DEP

config FOO
	bool "Foo"

config BAR
	bool "Bar"

choice
	prompt "Choice"

config BAZ
	bool "Baz"

config QAZ
	bool "Qaz"

endchoice

endif # DEP

내부적으로 두 번째 형태는 첫 번째로 변환됩니다. 같은 menu 안이라면 dependency를 menu 자체에 둘 수 있습니다.

menu "Foo features"
	depends on FOO_SUPPORT

config FOO_FEATURE_1
	bool "Foo feature 1"

config FOO_FEATURE_2
	bool "Foo feature 2"

endmenu

FOO_SUPPORT=n이면 menu 전체가 사라집니다.

중복 default

Bool은 암묵적으로 n, string은 empty string이므로 default n과 default ""은 거의 항상 중복입니다. Zephyr style은 생략합니다. Int와 hex는 암묵 default가 empty string이므로 항상 default를 주는 것이 좋습니다.

예외는 symbol을 여러 위치에서 정의하고 뒤쪽의 default y보다 앞쪽 정의를 우선하려는 경우입니다. 다음은 FOO가 n입니다.

config FOO
	bool "foo"
	default n

config FOO
	bool "foo"
	default y

다음은 먼저 만족한 default y 때문에 FOO가 y입니다.

config FOO
	bool "foo"
	default y

config FOO
	bool "foo"
	default n

공통 Kconfig shorthand

<type> "prompt"는 type과 prompt를 함께 주는 shorthand입니다. 다음 두 정의는 같습니다.

config FOO
	bool "foo"
config FOO
	bool
	prompt "foo"

Zephyr에서는 첫 번째 shorthand style을 선호합니다. def_<type> <value>는 type과 default를 함께 주며 다음 두 정의가 같습니다.

config FOO
	def_bool BAR && BAZ
config FOO
	bool
	default BAR && BAZ

한 정의에서 prompt shorthand와 def_*를 함께 쓰면 type을 두 번 주므로 중복입니다. def_*는 주로 prompt 없는 symbol에서만 유용합니다. 여러 위치에 정의한 symbol은 base definition에만 type을 주고 나머지에는 default만 사용하면 base가 삭제될 때 no-type warning으로 남은 정의를 찾기 쉽습니다.

Prompt 문자열

Driver나 subsystem FOO를 enable하는 bool의 prompt는 Enable Foo support보다 간결한 Foo를 고려합니다. Toggle option이라는 문맥에서 의미가 분명하고 전체 표현도 일관됩니다.

Header comment와 formatting

Kconfig file 첫 부분의 header comment는 다음 형식을 사용합니다.

# <Overview of symbols defined in the file, preferably in plain English>
(Blank line)
# Copyright (c) 2019 ...
# SPDX-License-Identifier: <License>
(Blank line)
(Kconfig definitions)
  • Comment는 #Comment가 아니라 # Comment
  • Top-level if와 endif 앞뒤에 blank line
  • Indentation은 single tab
  • Help text는 추가로 두 space indent

덜 알려진 Kconfig 기능

imply

imply는 select와 비슷하지만 dependency를 존중하고 값을 강제하지 않습니다. 다음은 FOO SoC에서 USB keyboard를 default enable하되 user가 끌 수 있게 합니다.

config SOC_FOO
	bool "FOO SoC"
	imply USB_KEYBOARD

...

config USB_KEYBOARD
	bool "USB keyboard support"

imply는 제안이고 select는 강제입니다.

Optional prompt

Prompt에 condition을 달아 machine에 따라 user-configurable하게 만들 수 있습니다. 일부 board에서 0xFF로 고정되고 다른 board에서 바꿀 수 있는 MASK는 다음과 같습니다.

config MASK
	hex "Bitmask" if HAS_CONFIGURABLE_MASK
	default 0xFF

이를 풀어 쓰면 다음과 같습니다.

config MASK
	hex
	prompt "Bitmask" if HAS_CONFIGURABLE_MASK
	default 0xFF

Board가 helper HAS_CONFIGURABLE_MASK를 select해 configurable 여부를 알립니다. Configurable할 때도 default는 0xFF입니다.

Optional choice

Choice에 optional keyword를 붙이면 choice 전체를 끄고 어떤 symbol도 선택하지 않을 수 있습니다.

choice
	prompt "Use legacy protocol"
	optional

config LEGACY_PROTOCOL_1
	bool "Legacy protocol 1"

config LEGACY_PROTOCOL_2
	bool "Legacy protocol 2"

endchoice

Menuconfig에서는 choice 자체를 toggle해 두 protocol 모두 enable하지 않을 수 있습니다.

visible if condition

Menu의 visible if는 menu와 내부 symbol을 숨기지만 symbol default는 계속 적용합니다. 먼저 depends on menu를 보겠습니다.

menu "Foo subsystem"
	depends on HAS_CONFIGURABLE_FOO

config FOO_SETTING_1
	int "Foo setting 1"
	default 1

config FOO_SETTING_2
	int "Foo setting 2"
	default 2

endmenu

HAS_CONFIGURABLE_FOO=n이면 두 setting의 configuration output이 없으며 논리상 각 symbol에 dependency를 준 다음과 같습니다.

config FOO_SETTING_1
	int "Foo setting 1"
	default 1
	depends on HAS_CONFIGURABLE_FOO

config FOO_SETTING_2
	int "Foo setting 2"
	default 2
	depends on HAS_CONFIGURABLE_FOO

Helper가 n이어도 default는 적용하되 user에게 숨기려면 visible if를 사용합니다.

menu "Foo subsystem"
	visible if HAS_CONFIGURABLE_FOO

config FOO_SETTING_1
	int "Foo setting 1"
	default 1

config FOO_SETTING_2
	int "Foo setting 2"
	default 2

endmenu

이는 각 prompt에 condition을 붙인 다음 형태와 같습니다.

config FOO_SETTING_1
	int "Foo setting 1" if HAS_CONFIGURABLE_FOO
	default 1

config FOO_SETTING_2
	int "Foo setting 2" if HAS_CONFIGURABLE_FOO
	default 2

HAS_CONFIGURABLE_FOO=n일 때도 이제 다음 output이 생성됩니다.

...
CONFIG_FOO_SETTING_1=1
CONFIG_FOO_SETTING_2=2
...

Symbol 값 계산의 더 자세한 설명은 Kconfiglib docstring의 Intro to symbol values 절을 참고합니다.

Source

출처

영어 원문에는 문단, 문서 지시문, 표, 코드, 코드 심벌, 경로를 그대로 보존했습니다.