The build2 Kconfig Module

The `build2` Kconfig Module

Revision `0.3.0`, June 2023
This revision of the document describes the `build2` Kconfig module `0.3.X` series.

Copyright © 2020-2023 the build2 authors.
Permission is granted to copy, distribute and/or modify this document under the terms of the GPLv2 license.

# Table of Contents

# Preface

This document describes the `build2` Kconfig module. It starts with an introduction to the Linux kernel configuration system (Kconfig) and the `build2` Kconfig module. The next chapter expands on that and describes the integration of Kconfig into the `build2` configuration model in more detail.

The remainder of the document serves as a guide to the Kconfig language with examples based on the `kconfig-hello` package. Besides this guide, see also the official Kconfig Language and Kconfig Macro Language documentation as well as the Kconfig Tips and Best Practices from the Zephyr project.

# 1 Introduction

This chapter provides a brief overview of the Linux kernel configuration system (Kconfig) and the functionality provided by the `build2` Kconfig module. Its aim is to show how everything fits and works together based on a customary "Hello, World!" example.

## 1.1 What is Kconfig?

Kconfig is the configuration system of the Linux kernel. Over the years it has evolved into a sophisticated variability modeling language and a toolset that are used by the Linux kernel to manage over ten thousand configuration options. It is also increasingly being used by other projects that need to manage complex configurations.

The Kconfig system consists of the following main parts:

- The configuration definition language.
- The configuration management tools.
- The configuration values format.

The configuration definition language, or the Kconfig language for short, defines a hierarchy of menus containing configuration options as well as relationships between them. Traditionally, configuration definitions are stored in files called `Kconfig` (with a capital `K`). Here is a simple configuration containing two options:

    config FANCY
            bool "Fancy options"
            help
              Enable more fancy configuration options.

    config GREETING
            string "Custom greeting"
            default "Hello"
            depends on FANCY
            help
              Custom string to use as a greeting.

While the examples in this document assume a UNIX-like operation system, they should work with minimal modifications on Windows.

To create and manage configurations, the Kconfig system includes a number of tools called configurators. The most prominent of those are `kconfig-conf` which provides a terminal-based question-and-answer configuration method, `kconfig-mconf` which provides a terminal-based menu configuration method based on a curses library, and `kconfig-qconf` which provides a graphical configuration method based on Qt. The `kconfig-conf` configurator also provides a number of non-interactive configuration methods (default, random, etc), support for updating old configurations to new definitions (both interactively and non), as well as other configuration management facilities (creation of default configurations, etc).

Given the above configuration definition saved in the `Kconfig` file, we can run one of the configurators to create a new configuration. For example:

    $ kconfig-conf Kconfig
    *
    * Main menu
    *
    Fancy options (FANCY) [N/y/?] (NEW) y
      Custom greeting (GREETING) [Hello] (NEW) Hi
    #
    # configuration written to .config
    #

The configuration values are saved into a file that is traditionally called `.config` though this naming convention is not as universal as for the definition file (`Kconfig`). If we examine the `.config` file produced by the above command, we will see the following:

    #
    # Automatically generated file; DO NOT EDIT.
    # Main menu
    #
    CONFIG_FANCY=y
    CONFIG_GREETING="Hi"

The Kconfig system is best suited for complex configuration requirements where user input is needed at least in some situations (for example, new platforms, custom/optimized configurations, etc). Some of its more advanced features include:

- String, integer, and choice configuration options in addition to boolean.
- Direct (`depends on`) and reverse (`select`, `imply`) option relationships.
- Grouping into sub-menus and multi-file definitions (`source`).
- Make-like macro substitution in the definition language.
- Sophisticated set of tools for managing configurations.

## 1.2 What is `build2` Kconfig module?

The `build2` Kconfig module provides the ability to use the Linux kernel configuration system to configure `build2` projects. Specifically, it integrates the execution of one of the Kconfig configurators into the `build2` `configure` meta-operation and loads the resulting configuration file presenting its values as `kconfig.*` Buildfile variables. We can then use these `kconfig.*` values to make decisions in `buildfiles`, `testscripts`, and/or propagate them to our source code, similar to `config.*` values (Project Configuration).

As an example, let's see what it takes to add the Kconfig configuration shown in the previous section to a simple `build2` project. As a first step, let's create the `libhello` library using `bdep-new(1)`:

    $ bdep new -l c++ -t lib --no-init libhello
    $ cd libhello

Next we copy the `Kconfig` definition file from the previous section into the `libhello/build/` subdirectory:

    $ cp ../Kconfig build/

Finally, we edit `libhello/build/bootstrap.build` and load the `kconfig` module. Here is what the new `bootstrap.build` could look like:

    project = libhello

    using version
    using config
    using kconfig
    using test
    using install
    using dist

The `kconfig` module is part of the standard pre-installed `build2` modules and no extra integration steps are required other than the `using` directive in `bootstrap.build`.

Now if we configure our project, we will see the familiar prompt:

    $ b configure
    kconfig build/config.kconfig.new
    *
    * libhello 0.1.0-a.0.19700101000000
    *
    Fancy options (FANCY) [N/y/?] (NEW) y
      Custom greeting (GREETING) [Hello] (NEW) Hi
    save build/config.build
    mv build/config.kconfig.new build/config.kconfig

From other diagnostics we can gather that the configuration file was saved as `build/config.kconfig`. The reason for first saving it as `config.kconfig.new` is explained in the next chapter. We can confirm that its contents are similar to what we have already seen:

    $ cat build/config.kconfig
    #
    # Automatically generated file; DO NOT EDIT.
    # libhello 0.1.0-a.0.19700101000000
    #
    CONFIG_FANCY=y
    CONFIG_GREETING="Hi"

The only difference in this file (as well as in the above prompt) is the replacement of `Main menu` with `libhello 0.1.0-a.0.19700101000000`. As the name suggests, this is the title of the main menu which is the root of the Kconfig menu hierarchy. Customarily, it is set to the project name and version which the `kconfig` module does automatically. However, it can also be set to a custom value with the `kconfig.kconfig.title` variable, as discussed later.

By default the `kconfig` module uses the terminal-based question-and-answer configurator. It's a conservative choice that will work in most circumstances and is built into the module, so the presence of the `kconfig-conf` executable is not required. However, we can use the `config.kconfig` variable to select a different configurator. For example, we can reconfigure our project using the graphical `kconfig-qconf` configurator This requires the presence of the `kconfig-qconf` executable:

    $ b configure config.kconfig=qconf

The `CONFIG_*` values from the configuration file are made available as `kconfig.<project>.*` variables in `buildfiles` with the configuration option name converted to the lower case. For example, we can examine our values by adding the following `info` directives at the beginning of `libhello/buildfile`:

    info "fancy: $kconfig.libhello.fancy"
    info "greeting: $kconfig.libhello.greeting"

If we now update our `libhello` project, we should see the following output:

    $ b
    libhello/buildfile:1:1: info: fancy: true
    libhello/buildfile:2:1: info: greeting: Hi
    ...

The Kconfig configuration is also reported at a sufficiently high verbosity level (Configuration Report). For example:

    $ b configure -v
    kconfig libhello@/tmp/libhello/
      fancy      true
      greeting   Hi

The configuration values (`fancy` and `greeting`) used in this example are the same as what's shown in Project Configuration and the same mechanisms for post-processing and propagating configuration values apply here; in most examples from that chapter you can simply replace `config.libhello.*` with `kconfig.libhello.*`.

Note, however, that if a non-bool option is disabled (for example, because its dependencies are unsatisfied), then the corresponding `kconfig.*` variable will be `null`. At the same time, the `in` module treats a `null` substitution as an error unless a fallback value is specified with the `in.null` variable. As a result, if non-bool `kconfig.*` variables are used in the `.in` file substitutions, then it is a good idea to specify the fallback, for example:

    h{config}: in{config}
    {
      # Instruct the in rule to substitute null with empty.
      #
      in.null = ''
    }

See `kconfig-hello` for a complete example that uses these mechanisms.

Analogous to `configure`, the standard `disfigure` meta-operation removes the Kconfig configuration, or, more precisely, moves it to `config.kconfig.old`. For example:

    $ b disfigure
    mv build/config.kconfig build/config.kconfig.old
    rm build/config.build

And that's pretty much all we have to do to integrate Kconfig-based configuration management into our project. One last touch would be to add `config.kconfig` to `build/.gitignore`, next to `config.build`:

    /config.build
    /config.kconfig*
    ...

We've used a wildcard after `config.kconfig` to also ignore intermediate `config.kconfig.new` files (discussed later) as well as the `config.kconfig.old` file where Kconfig configurators traditionally save the previous configuration.

The next chapter, Interface and Functionality, provides more details on the functionality offered by the `kconfig` module, including the available configurators, customization points, etc. For an introduction to the Kconfig language that also covers relevant `build2` integration aspects, refer to Kconfig Language.

# 2 Interface and Functionality

This chapter provides a more detailed discussion of the `kconfig` module's interface and functionality including its integration with the `config` module's configuration process as well as the customization points available to projects that use Kconfig.

## 2.1 Configuration Methods

As we have seen in the introduction, the `config.kconfig` variable can be used to select an alternative configurator, such as `mconf` or `qconf`. This variables also controls a few other aspects of producing new or updating an existing configuration which together we will call a configuration method. It has the following overall structure:

`[(new|old)-](def|ask|reask|mconf|qconf|env) [...]`

The optional first component controls the reuse of existing `config.kconfig`. If `new` is specified, then the configuration is created from scratch (with existing `config.kconfig`, if exists, saved as `config.kconfig.old`). If `old` is specified, then the configuration is created based on existing `config.kconfig` (with what "based" means determined by the second component). In this case, it's an error for there to be no existing `config.kconfig`. If the first component is omitted, then existing `config.kconfig` is reused if present (`old` semantics) and created from scratch otherwise (`new` semantics).

Given a configuration option definition in the Kconfig file, its value can come from the following sources:

1. Existing `config.kconfig` file.
2. Default configuration file.
3. Default value from the `Kconfig` file.

A configuration option that does not have a value in existing `config.kconfig` is referred to as a newly-defined configuration option. Naturally, if `config.kconfig` does not exist or is not used (because of the `new` first component), then all options are newly-defined.

The second component determines the configurator and its mode and has the following possible values:

`def [file]`
  Set newly-defined configuration options to values from `file` if specified and to their default values from `Kconfig` otherwise (if some options are missing in `file`, they are set to default values as well). To reset all the configuration options, use `new-def`.
`ask [file]`
  Ask for values of only newly-defined configuration options. For default answers use values from `file` if specified and default values from `Kconfig` otherwise.

  Note that if `config.kconfig` does not exist or is not used (`new-ask`) then this method is equivalent to `reask`.

`reask [file]`
  Ask for values of all the configuration options. For default answers use values from `config.kconfig` if exists, from `file` if specified, and default values from `Kconfig` otherwise.
`mconf`
  Present all the configuration options in a menu interface. For default answers, use values from `config.kconfig` if exists and default values from `Kconfig` otherwise.
`qconf`
  Present all the configuration options in a graphical interface. For default answers, use values from `config.kconfig` if exists and default values from `Kconfig` otherwise.
`env prog [args]`
  Run `prog` in the configuration environment (`KCONFIG_CONFIG`, etc) passing the `Kconfig` file as the last argument. For example:

      config.kconfig="env kconfig-conf --savedefconfig defconfig.kconfig"

The `def`, `ask`, and `reask` methods are implemented as builtins and do not require the presence of the `kconfig-conf` executable.

If no configuration method is specified with `config.kconfig`, then `ask` is used by default. However, a project may specify a different default configuration method as discussed in the next section.

Mapping for some of the `kconfig-conf` options to the above methods:

    --oldconfig             ask
    --oldaskconfig          reask
    --olddefconfig          def
    --alldefconfig      new-def
    --defconfig <file>  new-def <file>

Note that the following methods have no `kconfig-conf` equivalents:

    old-def <file>
    [re]ask <file>

Another useful application of the `env` method is the generation of random configurations with the `kconfig-conf` `--randconfig` mode. For example:

    $ b configure config.kconfig="env kconfig-conf -s --randconfig"
    kconfig build/config.kconfig.new
    KCONFIG_SEED=0xD6A72753
    save build/config.build
    mv build/config.kconfig.new build/config.kconfig

This can be used to automatically try various configurations, for example, by continuously configuring and testing the project in a loop This example is UNIX-specific:

    $ while \
      b configure config.kconfig="env kconfig-conf -s --randconfig" && \
      b test; do :; done

As can be seen on the previous listing, in the `--randconfig` mode, `kconfig-conf` prints the seed that it used to generate the configuration. This seed can be passed back to `kconfig-conf` as an environment variable in order to recreate the same random configuration. For example:

    $ KCONFIG_SEED=0xD6A72753 \
      b configure config.kconfig="env kconfig-conf -s --randconfig"

Another useful `--randconfig` environment variable is `KCONFIG_ALLCONFIG` which can be used to specify a configuration file containing a subset of options that must be set to specific rather than random values.

## 2.2 Configuring and Loading

As mentioned briefly in the introduction, `kconfig` acts as a second-level configuration mechanism to the builtin support in the form of `config.*` variables and the `config` module. In particular, the `kconfig` module hooks into the `configure` and `disfigure` meta-operations of the `config` module providing an integrated configuration process. It is also possible to use the `config.*` variables (as well as other Buildfile variables) as inputs to the `kconfig` configuration. This chapter provides more details on how this is achieved and the available customization points.

To understand how `kconfig` fits in, we begin with an overview of the builtin configuration process, that is, what happens when we execute the `configure` meta-operation. While the `config` module is loaded in `bootstrap.build`, the `config.build` file (if exists) is loaded as a first step of loading `root.build` (more precisely, `config.build` is loaded before any bootstrapped module is initialized, which happens prior to loading `root.build`). After that, `root.build` and the rest of the project are loaded as usual. In particular, during this stage, `root.build` or any other `buildfile` can examine the `config.*` variables (as loaded from `config.build` and/or specified as command line overrides) and cause this stage to fail (for example, using the `assert` directive) if any values are deemed invalid. If, however, loading of the project succeeds, the `config` module saves the new `config.build` file which completes the `configure` meta-operation.

The important point about this process is that the new configuration is saved as the last step, after successfully loading the project. And the `kconfig` module attempts to provide the second-level configuration semantics that is consistent with this behavior. Specifically, while the `kconfig` module must also be loaded (bootstrapped) in `bootstrap.build`, it also delays loading `config.kconfig` until later. However, unlike the `config` module, by default, `kconfig` loads its configuration after `root.build`. This semantics was chosen to allow the first-level configuration as well as any other information made available by modules loaded in `root.build` to influence the Kconfig configuration. However, we can also load `config.kconfig` at any point in `root.build` by explicitly loading (initializing) the `kconfig` module. For example, continuing with the `libhello` project from the previous chapter, we could have something like this in our `root.build`:

    using cxx

    using kconfig

    if ($kconfig.libhello.fancy && $cxx.target.class == 'windows')
      fail "have to keep it basic on Windows"

Similar to the `config` behavior, the `kconfig` module also saves the configuration only after the project has successfully been loaded. Achieving this semantics, however, is not as straightforward as in the `config` module because the configuration must also be made available during the project loading, as discussed above. To implement this, `kconfig` first saves the configuration to a temporary file, `config.kconfig.new`, and then renames it to `config.kconfig` at the end. Specifically, the `kconfig` module performs the following steps during `configure`:

`bootstrap.build`
  Register the post-`configure` callback with the `config` module.
`root.build`
  Run the configurator saving the result to `config.kconfig.new`.
`configure`
  In post-`configure` rename `config.kconfig.new` to `config.kconfig`.

When not configuring, the `kconfig` module simply loads `config.kconfig` and verifies it is up-to-date with definitions in `Kconfig`. If that's not the case, for example, because we've added or removed a configuration option, then `kconfig` fails suggesting that we reconfigure the project.

As mentioned in the previous section, a project may specify the default configuration method that will be used if not explicitly specified with `config.kconfig`. More precisely, the project may set any of the `kconfig.kconfig.{configure,reconfigure,retryconfigure}` variables to select the default method for creating new, updating existing, and trying to fix previously created/updated configuration, respectively.

To elaborate, the `kconfig.kconfig.configure` method is used when configuring a project from scratch, without existing `config.kconfig`, while `kconfig.kconfig.reconfigure` is used while reconfiguring a project with existing `config.kconfig`. The `kconfig.kconfig.retryconfigure` method is used when reconfiguring a project with existing `config.kconfig.new`, which normally means that the previous (re)configuration attempt has failed or was interrupted. The default values for these variables are `reask`, `ask`, and `reask`, respectively.

Setting `kconfig.kconfig.retryconfigure` to a method that does not allow the user to adjust every configuration option may result in an invalid configuration that can only be fixed by first disfiguring the project.

As an example, if we wanted our project to use the default values from `Kconfig` and only use interactive configuration if explicitly requested by the user (or if the default configuration turned out to be invalid), we could add the following to our `root.build` before loading `kconfig`:

    kconfig.kconfig.configure = new-def
    kconfig.kconfig.reconfigure = old-def

    using kconfig

Provided this makes sense for your project, it's a good idea to make the default configuration method non-interactive. This will allow you to use the CI service and, if desired, publish your project to a package repository. While interactive default configuration may make sense for an end-product kind of projects, for reusable components such as libraries a non-interactive default that enables most of the functionality is probably the best choice. See Project Configuration for background.

What happens if we try to build our project without `config.kconfig`? By default `kconfig` fails suggesting that we configure the project. However, this behavior can be altered with the `kconfig.kconfig.transient` variable. Setting it to `ask` (which is the default), disables the ability to use transient configurations. But in the above project it would make sense to also use default values for transient configurations, for example:

    kconfig.kconfig.configure = new-def
    kconfig.kconfig.reconfigure = old-def
    kconfig.kconfig.transient = def

    using kconfig

Besides the default values from `Kconfig` files, another common source of default values are default configurations. This method becomes more appropriate when we have multiple sets of default values, for instance, one per target platform. As an example, let's convert the above project to use the default configuration files in the `defconfig-platform.kconfig` form where `platform` is the target class as supplied by the `cxx.target.class` variable (`linux`, `windows`, `macos`, etc). Here are the changes to `root.build`:

    using cxx

    defconfig = $src_root/build/defconfig-$(cxx.target.class).kconfig

    kconfig.kconfig.configure = new-def $defconfig
    kconfig.kconfig.reconfigure = old-def $defconfig
    kconfig.kconfig.transient = def $defconfig

    using kconfig

The `build/Kconfig` file and files that it sources (transitively) as well as `build/defconfig*.kconfig` are automatically added to the distribution and need not be explicitly mentioned as prerequisites in `buildfiles`.

While any Kconfig configuration file can serve as a default configuration, normally a minimal version is produced using `kconfig-conf --savedefconfig`. Given a suitably configured project, we can extract the corresponding default configuration using the `env` method:

    $ b configure config.kconfig=\
    "env kconfig-conf --savedefconfig defconfig-linux.kconfig"

We can also do it manually given just the configuration file, for example:

    $ KCONFIG_CONFIG=config.kconfig \
      kconfig-conf --savedefconfig defconfig-linux.kconfig Kconfig

If your `Kconfig` definition file relies on external inputs (as discussed next), then with the manual extraction you will also need to manually supply such inputs via environment variables.

## 2.3 External Kconfig Macro Variables

Selecting the default configuration based on the target platform as shown in the previous section is one example of using information from the first-level configuration and/or modules loaded before `kconfig` to adjust the Kconfig configuration. It is, however, also possible to modify the `Kconfig` definition file itself based on such information by setting external Kconfig macro variables.

The Kconfig language includes a macro variable facility that can be used for textual substitution (see Macro Language for details). As an example, let's try to improve on our previous attempt to only allow fancy options in certain cases. To recap, this is what we did:

    using cxx

    using kconfig

    if ($kconfig.libhello.fancy && $cxx.target.class == 'windows')
      fail "have to keep it basic on Windows"

Ideally, instead of allowing the user to select the `FANCY` option and then complaining that it can't be selected for certain platforms, we would want to make it impossible to select it in the first place when configuring for such platforms. As a first step, let's introduce a Kconfig macro variable and make the `FANCY` option depend on its value:

    ENABLE_FANCY := y

    config FANCY
            bool "Fancy options"
            depends on $(ENABLE_FANCY)
            help
              Enable more fancy configuration options.

    ...

With this change we can now enable/disable the fancy options by adjusting the `ENABLE_FANCY` Kconfig macro variable. The next step is to somehow set it from outside the `Kconfig` file. With the `kconfig` module we can do that by simply setting the corresponding `Kconfig.*` variable (with a capital `K`) in our `buildfile`. If invoking one of the configurators directly, then such variables are set via the environment. In our example, let's remove the `ENABLE_FANCY` assignment from `Kconfig` and rewrite `root.build` as follows:

    using cxx

    Kconfig.ENABLE_FANCY = ($cxx.target.class != 'windows')

    using kconfig

`Kconfig.*` values of type `bool` are automatically converted from Buildfile `true`/`false` to Kconfig `y`/`n`. Other value types are passed to Kconfig by converting to string.

The Kconfig macro variables can be used in many contexts, for example, in default values. However, such dynamically-changing Kconfig definitions become hard to reason about and can lead to surprises. As a result, it's probably wise to limit the use of external variables to disabling options and menus rather than altering their definitions.

A macro substitution referencing a variable that is not set inside the `Kconfig` file nor via the `Kconfig.*` Buildfile variable is an error. The only builtin variable set automatically by the `kconfig` module is `SRC_ROOT` which contains the project's source root directory (the same as the `src_root` Buildfile variable). It is normally used to source (Source) additional `Kconfig` files, for example:

    source "$(SRC_ROOT)/libhello/Kconfig"

# 3 Kconfig Language

Kconfig is a line-oriented language. That is, a construct ends at the end of the line unless escaped with line continuation (trailing `\`). The `#` character starts a comment with everything from this character until the end of the line ignored. This character and other special characters (quotes, `$`, etc) can be escaped with a backslash.

Kconfig has single-quoted (`'`) and double-quoted (`"`) strings with identical semantics. Inside strings, all characters except the closing quote and `$` (macro substitution) are treated literally. For example, the following two Kconfig strings are the same:

    "foo \"bar\" \$(baz)"
    'foo "bar" \$(baz)'

A `Kconfig` file starts with zero or more macro variable assignments (Macro Language) followed by zero or more Kconfig definitions which may source (Source) other `Kconfig` files. Each definition starts with a keyword. For example:

    # This is a comment.

    DEFAULT_GREETING := Hello

    config GREETING
            string "Custom greeting"
            default "$(DEFAULT_GREETING)"

    source "$(SRC_ROOT)/Kconfig"

The following synopsis lists all the available Kconfig definitions with the subsequent sections explaining their semantics using examples from the `kconfig-hello` package. For additional background and details see also the official Kconfig Language and Kconfig Macro Language documentation as well as the Kconfig Tips and Best Practices from the Zephyr project.

`config symbol
type [prompt [if expr]]
prompt prompt [if expr]
default value [if expr]
range integer integer [if expr]
depends on expr
select symbol [if expr]
imply symbol [if expr]
help
text
if expr
...
endif
menu prompt
visible if expr
depends on expr
...
endmenu
menuconfig symbol
...
choice [symbol]
optional
default symbol [if expr]
...
...
endchoice
comment prompt
depends on expr
source path
type = bool | string | int | hex | tristate
value = (y|n) | string | integer | (y|m|n)
string = "text" | 'text'
integer = dec-integer | 0xhex-integer
prompt = string
path = string
term = symbol | value
expr = term |
term = term |
term != term |
term < term |
term > term |
term <= term |
term >= term |
( expr ) |
! expr |
expr && expr |
expr || expr`

## 3.1 Option (`config`)

`config symbol
type [prompt [if expr]]
prompt prompt [if expr]
default value [if expr]
range integer integer [if expr]
depends on expr
select symbol [if expr]
imply symbol [if expr]
help
text
if expr
...
endif
type = bool | string | int | hex | tristate
value = (y|n) | string | integer | (y|m|n)
string = "text" | 'text'
integer = dec-integer | 0xhex-integer
prompt = string
term = symbol | value
expr = term |
term = term |
term != term |
term < term |
term > term |
term <= term |
term >= term |
( expr ) |
! expr |
expr && expr |
expr || expr`

The central part of Kconfig is the configuration option definition with the rest of the language is mostly serving to organize options into sub-menus. A simple `Kconfig` file may consist of just option definitions which all become entries of the implicitly-defined main menu (discussed in the next section).

The option definition starts with the `config` keyword followed by the option name, which in the Kconfig language is called a symbol. For example:

    config IO
            bool "IO support"
            help
              Enable stdin/stdout input/output. Note that if this option
              is disabled, then you won't see any output.

Other Kconfig documentation often uses the term symbol to mean the configuration option, not just its name.

The name is traditionally spelled in upper case and is the same name that will end up in the configuration file but prefixed with `CONFIG_` and as a Buildfile variable but converted into lower case and prefixed with `kconfig.<project>.`.

Following the `config` keyword and the name we have a number of lines that define the option's attributes. They are traditionally indented by 8 spaces (or an equivalent TAB). While none of the attributes are mandatory, a definition will normally include at least the type and usually also the prompt and help, as in the above example.

A number of attributes support the trailing `if expr` condition. If specified, the attribute only applies if the expression evaluates to true (Expressions). Such attributes can also be specified multiple times. For example:

    config GREETING_TEXT
            string "Custom greeting" if GREETING_CUSTOM
            default "Hello" if GREETING_HELLO
            default "Hi"    if GREETING_HI
            default "Howdy" if GREETING_HOWDY
            help
              Custom string to use as a greeting.

In this example, the `GREETING_TEXT` option will only be visible if the `GREETING_CUSTOM` option is selected and the default value is chosen based on which `GREETING_H*` option is selected.

### 3.1.1 Prompt and Help

`config symbol
type [prompt [if expr]]
prompt prompt [if expr]
help
text
string = "text" | 'text'
prompt = string`

The configuration option prompt is a short text that describes the option to the user while the option help provides a more detailed description. For example:

    config IO
            bool
            prompt "IO support"
            help
              Enable stdin/stdout input/output. Note that if this option
              is disabled, then you won't see any output.

If an option has a visible prompt (that is, the prompt is not disabled with `if expr`) and its dependencies are satisfied (Dependencies), then the option is presented to the user for customization. For example:

    $ b configure
    IO support (IO) [N/y/?] (NEW) ?

    CONFIG_IO:

    Enable stdin/stdout input/output. Note that if this option
    is disabled, then you won't see any output.

    Symbol: IO [=n]
    Type  : bool
    Defined at kconfig-hello/build/Kconfig:18
      Prompt: IO support
      Location:
        -> Basic options

The option prompt can be specified with the `prompt` attribute as in the above example or it can be combined with the type attribute for brevity. For example:

    config IO
            bool "IO support"
            ...

This shorter version is customarily preferred unless selecting between several prompts with `if expr`. In both versions the prompt text can be specified using either single or double quotes.

The option help often contains several lines of text and is specified indented (customarily with 2 spaces) relative to the line that contains the `help` keyword. The help text ends at the line that has a smaller indentation than the first line of the help text.

While an option with an invisible prompt cannot be modified by the user, it can still be modified by other options through reverse dependencies and its value is accessible via the corresponding `kconfig.*` variable. An option with an absent prompt that is selected through such reverse dependencies is called a helper option. See Helper Options for more information on their use-cases.

### 3.1.2 Type, Default Value, and Range

`config symbol
type [prompt [if expr]]
default value [if expr]
range integer integer [if expr]
type = bool | string | int | hex | tristate
value = (y|n) | string | integer | (y|m|n)
string = "text" | 'text'
integer = dec-integer | 0xhex-integer`

Configuration option type can be `bool` (boolean), `string`, `int` (decimal integer), `hex` (hexadecimal integer), and `tristate`:

`bool`
  True or false state. Values of this type are spelled as `y` or `n`, for example:

      config FOO
              bool
              default y

  When converted to the `kconfig.*` variables, such values have the `bool` Buildfile type.

`string`
  Text string. Values of this type are spelled using either single or double quotes, for example:

      config FOO
              string
              default "foo"

  When converted to the `kconfig.*` variables, such values have the `string` Buildfile type.

`int`
  Signed 64-bit decimal integer. Values of this type are spelled as a sequence of decimal digits, for example:

      config FOO
              int
              default 123

  When converted to the `kconfig.*` variables, such values have the `int64` Buildfile type.

`hex`
  Unsigned 64-bit hexadecimal integer. Values of this type are spelled as a sequence of hexadecimal digits prefixed with `0x`, for example:

      config FOO
              hex
              default 0x1ab2c3d4

  When converted to the `kconfig.*` variables, such values have the `uint64` Buildfile type.

`tristate`
  Like `bool` but with an extra state (`m`) used to express modularity. See Modularity Support for details on this functionality.

The `kconfig.*` variables are overridable which means, similar to the first-level configuration, we can temporarily tweak the Kconfig configuration (as seen by `buildfiles`) without reconfiguring the project. For example:

    $ b kconfig.hello.io=false

Note, however, that such changes do not go through the usual Kconfig processing which, in particular, means no option dependency resolution is performed. As a result, care must be taken not to end up with an invalid configuration.

The default value for a configuration option can be specified with the `default` attribute. For example:

    config PUNCT
            string "End of greeting punctuation"
            default "!"
            help
              Character for punctuating the end of the greeting sentence.

This value will be used as the suggested answer in interactive configurations methods and as a fallback in non-interactive ones (see Configuration Methods for details). If no default value is specified, `n` is assumed for `bool` and `tristate` and empty string for `string` while there is no assumed default for `int` and `hex`.

While `int` and `hex` options without default values are valid, creating a configuration in a way that would require default values (for example with the `config.kconfig=def` method) is an error.

Options of type `int` and `hex` can also specify the expected value range with the `range` attribute (both ends are inclusive). If specified, the user will not be allowed to enter a value that is out of this range. For example:

    config NAME_ASK_MAX
            int "Max times to ask for name"
    	default 5
    	range 1 10
            help
              Maximum number of times to ask for the name to greet.

### 3.1.3 Dependencies

`config symbol
depends on expr
if expr
...
endif`

The `depends on` attribute is used to specify a dependency of one option on another. Collectively, dependencies determine what configurations are valid. For example:

    config IO
            bool "IO support"

    config NAME_ASK
            bool "Ask for name"
            depends on IO

If an option's dependency is not satisfied, then the option becomes disabled: the user is not prompted for its value and its default value is not used. For `bool` and `tristate`, the disabled option is set to `n`. For other types, the disabled option's value is not set and the corresponding `kconfig.*` variable is `null`.

We use the term enabled/disabled when we refer to the option's state based on its dependencies and visible/invisible – based on its prompt. An option is only presented to the user for customization if it is both enabled and visible. If a `bool` option is set to `y`, we call it selected.

The `depends on` attribute can also be used to specify a dependency on an expression involving more than one option or non-boolean options (see Expressions for details). For example:

    config IO
            bool "IO support"

    config RETRY
            int "Max times to retry"

    config NAME_ASK
            bool "Ask for name"
            depends on IO && RETRY != 0

Specifying multiple `depends on` attributes is equivalent to specifying their expressions with a single `depends on` attribute combined with `&&`. For example, this variant is equivalent to the above:

    config NAME_ASK
            bool "Ask for name"
            depends on IO
            depends on RETRY != 0

If we have multiple options with the same dependency, then instead of repeating the `depends on` attribute for each of them we can use the `if`-block for a more succinct result. For example:

    config IO
            bool "IO support"

    if IO

    config NAME_ASK
            bool "Ask for name"

    config TRACE
            bool "Trace execution"

    endif

The semantics of the `if`-block is equivalent to specifying an explicit `depends on` attribute with the `if`-expression for each entry until `endif`.

### 3.1.4 Reverse Dependencies

`config symbol
select symbol [if expr]
imply symbol [if expr]`

A reverse dependency is used to select an option from another option. For example:

    config IO
            bool "IO support"

    config NAME_ASK
            bool "Ask for name"
            select IO

In this example, if `NAME_ASK` is set to `y`, then `IO` is forced to `y` as well.

Reverse dependencies can only be used with `bool` and `tristate` options and there are two flavors: strong and weak.

A strong reverse dependency is specified with the `select` attribute. It forces the option specified after the `select` keyword to `y` whenever the option containing this attribute is set to `y` (for `tristate` options, the same logic applies for `m`). And by forces we mean just that: it disregards unsatisfied dependencies and user selection.

Note that this forceful nature of strong reverse dependencies often leads to puzzling configuration issues. For example, a user may be trying to unsuccessfully disable a feature without realizing that it is forced by another, seemingly unrelated option. Such issues can be very frustrating and time-consuming to figure out and, as a result, the use of reverse dependencies on user-visible options is not recommended. Using `select` on invisible options, however, is a useful technique as described in Helper Options.

A weak reverse dependency is specified with the `imply` attribute. As the name suggests, it does not force but merely recommends. The other option can still be set to `n` by the user or if any of its dependencies are unsatisfied. For example:

    config IO
            bool "IO support"
            default y
            imply NAME_ASK

    config NAME_ASK
            bool "Ask for name"

In this example, if the user selects `y` for `IO`, then the prompt for `NAME_ASK` will also have `y` as the default answer. However, the user can still disable `NAME_ASK` by answering `n`. Similarly, if configuring non-interactively using the default values (`config.kconfig=def`), then `NAME_ASK` will be set to `y` because `IO` is set to `y` (because of its `default y` attribute).

### 3.1.5 Expressions

`value = (y|n) | string | integer | (y|m|n)
string = "text" | 'text'
integer = dec-integer | 0xhex-integer
term = symbol | value
expr = term |
term = term |
term != term |
term < term |
term > term |
term <= term |
term >= term |
( expr ) |
! expr |
expr && expr |
expr || expr`

Kconfig expressions are used in a number of option attributes to determine visibility, establish dependencies, and to enable default values. And as we will see in later sections, they are also used for similar purposes in other Kconfig definitions. The result of evaluating an expression is boolean `y` (true) or `n` (false).

More precisely, Kconfig expressions use the tristate logic with the extra `m` state used to represent modularity. For the evaluation purposes, the `m` state is equivalent to `y` if modules are enabled. See Modularity Support for details.

Expression alternatives in the above production are listed in the decreasing order of precedence. Values in expressions are spelled as in the `default` attribute (Type, Default Value, and Range).

A terminal expression consisting of a symbol evaluates to true if the corresponding option is of type `bool` (or `tristate`) and is `y` (or `m` and modules are enabled). In this context options of all other types always evaluate to `n`.

A terminal expression consisting of a value evaluates to true if it is either `y` or `"y"` (or `m` or `"m"` and modules are enabled). For example See External Kconfig Macro Variables for a more realistic example:

    ENABLE_FANCY := y

    config IO
            bool "IO support"

    config FANCY
            bool "Fancy options"
            depends on IO
            depends on $(ENABLE_FANCY)

Terminals (symbol or value) can be compared for being equal/unequal less/greater, and less-or-equal/greater-or-equal. Finally, sub-expression can be grouped with parenthesis, negated, and combined with logical AND and OR. For example:

    FALLBACK_NAME := ...

    config IO
            bool "IO support"

    config RETRY
            int "Max times to retry"

    config NAME_ASK
            bool "Ask for name"
            depends on IO && (RETRY != 0 || "$(FALLBACK_NAME)" = "")

## 3.2 Menu (`menu`)

`menu prompt
visible if expr
depends on expr
...
endmenu
menuconfig symbol
...`

Menus are used to organize options into a tree-like hierarchy as an aid to the user. Normally a menu would contain related options. If a menu contains a large number of options, then some of them can be organized into sub-menus and so on.

The menu definition starts with the `menu` keyword followed by the menu prompt. Similar to an option, a menu may specify a number of attributes on the following lines. After the menu definition and before the matching `endmenu` keyword, any option, sub-menu, etc., all belong to this menu and are collectively called menu entries. For example:

    menu "Basic options"

    config IO
            bool "IO support"
            help
              Enable stdin/stdout input/output. Note that if this option
              is disabled, then you won't see any output.

    config PUNCT
            string "End of greeting punctuation"
            default "!"
            help
              Character for punctuating the end of the greeting sentence.

    endmenu

Similar to option prompts, menu prompts are presented to the user during option customization. For example:

    $ b configure
    *
    * Basic options
    *
    IO support (IO) [N/y/?] (NEW) y
    End of greeting punctuation (PUNCT) [!] (NEW) !!!

The menu visibility can be controlled with the `visible if` attribute. If its expression evaluates to false, then neither the menu itself nor any of its entries are presented to the user. For example:

    menu "Fancy options"
            visible if IO

    ...

    endmenu

Menu visibility is the extension of the option prompt visibility in that an option that belongs to an invisible menu has the same semantics as if it had an invisible prompt (Prompt and Help).

Another attribute of a menu definition is `depends on`. Specifying this attribute is equivalent to specifying it for every option that belongs to this menu, recursively (Dependencies).

The Kconfig menu hierarchy always starts with an implicitly-defined main menu. While it is possible to customize its prompt in the `Kconfig` file using the `mainmenu` definition, customarily it is set to the project name and version which the `kconfig` module does automatically. It can also be customized by setting the `kconfig.kconfig.title` variable in `root.build` before loading the `kconfig` module.

Specifying `mainmenu` in the `Kconfig` file is not recommended when used with `build2` because there can only be one such definition thus making the result non-composable. And there are plans for the `kconfig` module to automatically aggregate Kconfig configurations of multiple projects into a single configurator invocation.

When organizing options into menus we often encounter a pattern where a configuration option enables a menu, for example:

    config FANCY
            bool "Fancy options"
            help
              Enable more fancy configuration options.

    menu "Fancy options"
      depends on FANCY

    config GREETING
            string "Custom greeting"
            help
              Custom string to use as a greeting.

    config NAME_ASK
            bool "Ask for name"
            help
              Ask for the name to greet if it is unspecified on the
              command line.
    endmenu

Regardless of how we structure this (option outside or inside the menu), the user interface will have a separate entry for the option and the menu while what we want here is to combine them. To achieve this we use the `menuconfig` hybrid menu/option. For example:

    menuconfig FANCY
            bool "Fancy options"
            help
              Enable more fancy configuration options.

    if FANCY

    config GREETING
            string "Custom greeting"
            ...

    config NAME_ASK
            bool "Ask for name"
            ...

    endif

The `menuconfig` definition has the same semantics and attributes as `config` but additionally establishes a sub-menu and treats all the following entries (options, menus) that have a dependency on its symbols as sub-menu entries until encountering the first entry without such a dependency. The common approach to establish such a dependency is to use the `if`-block as in the example above.

If you are wondering why `menuconfig` does not use an explicit end marker similar to `endmenu`, you are not alone. It is probably a remnant of the automatic menu generation described next.

Even if we didn't use `menuconfig` in the above example, Kconfig would analyze the dependency relationship and generate a menu-like structure automatically. Specifically, all the immediately following entries that have a dependency on the preceding option are treated as its sub-entries and displayed as belonging to this option. What "displayed as belonging" means, exactly, depends on the configurator and in some it may be indistinguishable from `menuconfig`.

## 3.3 Choice (`choice`)

`choice [symbol]
optional
default symbol [if expr]
...
...
endchoice`

Choices are used to restrict the selection to the at most one option from a set. In a way, they can be viewed as a variant of the menu concept but where instead of all the options the user can select only one.

The choice definition starts with the `choice` keyword optionally followed by the choice name. Similar to options and menus, a choice may specify a number of attributes on the following lines. After the choice definition and before the matching `endchoice` keyword comes a number of options (normally two or more) collectively called choice options. Choice options can only be of type `bool` and `tristate`. For example:

    choice
            prompt "Greeting"
            default GREETING_HELLO
            help
              String to use as a greeting.

    config GREETING_HELLO
            bool "\"Hello\""
            select GREETING_BUILTIN

    config GREETING_HI
            bool "\"Hi\""
            select GREETING_BUILTIN

    config GREETING_HOWDY
            bool "\"Howdy\""
            select GREETING_BUILTIN

    config GREETING_CUSTOM
            bool "Custom greeting"

    endchoice

Given the above choice, the user could be presented with the following interface:

    $ b configure
    Greeting
    > 1. "Hello" (GREETING_HELLO) (NEW)
      2. "Hi" (GREETING_HI) (NEW)
      3. "Howdy" (GREETING_HOWDY) (NEW)
      4. Custom greeting (GREETING_CUSTOM) (NEW)
    choice[1-4?]:

Choices with `tristate` options allow selecting multiple options provided they are all set to `m`. See Modularity Support for details.

Two commonly used choice attributes are `default` and `optional`. The `default` attribute is used to specify the default selection as shown in the example above. The `optional` attribute makes the choice optional allowing the user not to select any of the choice options.

A non-optional choice without a default value will currently result in an invalid configuration if configuring non-interactively using the default values (`config.kconfig=def`). As a result, it is recommended to always specify default values for non-optional choices.

A choice definition can specify any of the other configuration option attributes, however, not all of them make sense in all situations. In practice, there are two common patterns of choice usage: a simple choice without a name and an optional choice with a name. Here is the overall structure of the first pattern (which is also used in the above example):

    choice
            prompt "Prompt text"
            default DEFAULT_OPTION

    ...

    endchoice

In the second pattern, the optional choice is given a name that is used as a helper (Helper Options) to determine whether any of the choice options were selected. Such a choice may or may not have the default value. Here is its overall structure:

    choice CHOICE_NAME
           bool "Prompt text"
           optional
           default DEFAULT_OPTION

    ...

    endchoice

And here is a concrete example of such a choice:

    choice NAME_FALLBACK
           bool "Name fallback"
           optional
           help
             Fallback name to use if it is unspecified on the command
             line.

    config NAME_ASK
            bool "Ask for name"
            help
              Ask for the name to greet if it is unspecified on the
              command line.

    config NAME_DEF
            bool "Use default name"
            help
              Use the default name to greet if it is unspecified on the
              command line.

    endchoice

At the Buildfile level we can then use `kconfig.<project>.name_fallback` to determine if any of the choice options were selected, for example:

    if $kconfig.hello.name_fallback
    {
      if $kconfig.hello.name_ask
        ...

      if $kconfig.hello.name_def
        ...
    }

## 3.4 Comment (`comment`)

`comment prompt
depends on expr`

A comment is used to add a notice to the user during configuration. It is also written into the resulting configuration file.

The comment definition starts with the `comment` keyword followed by the comment prompt (text). For example:

    comment "IO disabled, no output will be shown"
            depends on !IO

Similar to other entries, a comment may specify a number of attributes on the following lines. Currently the only valid comment attribute is `depends on` which can be used to make a comment conditional, as shown in the example above.

## 3.5 Source (`source`)

`source path
path = string`

The source definition is used to source (include) one `Kconfig` file into another. It starts with the `source` keyword followed by the path string.

For example, if you would like your `Kconfig` file to reside in the root directory of your project (which is customary in several projects that use Kconfig, including the Linux kernel), then you can place the following line in your `build/Kconfig` and then write the rest of the definitions in the root `Kconfig`:

    source "$(SRC_ROOT)/Kconfig"

As mentioned in External Kconfig Macro Variables, `SRC_ROOT` is the pre-defined variable that contains the project's source root directory (the same as `src_root` in `buildfiles`). It should normally be used as a base for all your source definitions.

While we can specify a relative path to source, the historic Kconfig semantics is to first try to open such a path relative to the current working directory. Since `build2` does not assume any particular current working directory, the use of absolute paths based on `SRC_ROOT` is strongly recommended.

Note also that on Windows all Kconfig paths use forward slashes as directory separators, including the `SRC_ROOT` macro variable. You should also use the forward slashes when forming paths based on `SRC_ROOT`, as in the above example.

As another example, consider the following `Kconfig` fragment which is commonly misunderstood:

    if IO
    source "$(SRC_ROOT)/build/Kconfig-io"
    endif

This is not a conditional inclusion. Rather, it is an unconditional inclusion with all the definitions inside `Kconfig-io` now depending on `IO` (Dependencies).

There is no conditional inclusion in Kconfig nor, more generally, any ability to conditionally exclude a fragment of the `Kconfig` file. The closest we can get is probably a conditional selection of the file to source based on the external macro variable. For example, in our `root.build` we could have the following fragment:

    using cxx

    Kconfig.PLATFORM = $cxx.target.class

    using kconfig

And then in the `Kconfig` file write the following which would include `Kconfig-linux`, `Kconfig-windows`, etc., depending on the platform we are targeting:

    source "$(SRC_ROOT)/build/Kconfig-$(PLATFORM)"

Note also that if you are using this technique, then you will need to explicitly mention such `Kconfig-*` files as prerequsites in a `buildfile` in order for them to be included into the distribution. For example, in your root `buildfile` you could have:

    ./: ... build/file{Kconfig-*}

## 3.6 Macro Language

The Kconfig language provides support for `make`-like macro substitution. Conceptually, there are two languages layered one on top of the other: the bottom layer is the macro language that performs plain textual substitutions. The result is then used as input to the top layer, which is the Kconfig definition language. For example:

    DEFAULT_GREETING := Hey there

    config GREETING
            string "Custom greeting"
            default "$(DEFAULT_GREETING)"

After the macro substitution, the top layer will see:

    config GREETING
            string "Custom greeting"
            default "Hey there"

Macro substitutions can appear in pretty much any context, including prompts, default values, expressions, and so on. It is, however, important to keep in mind that macro variable names and option names/symbols operate in different languages. In particular, while a macro variable can contain an option name (symbol) it cannot contain an "expansion" (that is, a value) of an option. For example, the following does not make sense:

    GREETING_VALUE = $(GREETING)

    config GREETING
            string "Custom greeting"
            default "Hello"

While this conceptual model is helpful as an understanding aid, this is not exactly how the implementation works and there are some restrictions. Specifically, Kconfig keywords cannot be the result of the macro substitution nor can substitutions span multiple Kconfig tokens. Refer to the official Kconfig Macro Language documentation for details.

Macro variables can only be assigned at the beginning of a `Kconfig` file before any Kconfig definitions (options, menus, etc). Similar to `make`, there is no need to quote values in a macro variable assignment unless we want the value to contain literal quotes. For example, this version is equivalent to the above:

    DEFAULT_GREETING := "Hey there"

    config GREETING
            string "Custom greeting"
            default $(DEFAULT_GREETING)

During substitution, the corresponding value is first looked up in the variable assignments of the `Kconfig` file. If not found, then the value is looked up in the `Kconfig.*` Buildfile variables with `SRC_ROOT` being the only pre-defined variable (see External Kconfig Macro Variables for details). An undefined variable substitution is an error.

For example, instead of setting `DEFAULT_GREETING` in the `Kconfig` file as above, we could set it from `root.build`:

    Kconfig.DEFAULT_GREETING = '"Hey there"'

    using kconfig

As another example, we can pass the platform we are targeting as a macro variable:

    using cxx

    Kconfig.PLATFORM = $cxx.target.class

    using kconfig

And then use it in `Kconfig` to conditionally enable options, choose their default values, and so on:

    config IO
            bool "IO support"
            depends on "$(PLATFORM)" != "windows"

    config GREETING
            string "Custom greeting"
            default "Hey" if "$(PLATFORM)" = "linux"
            default "Hello"

    comment "Targeting $(PLATFORM)"

Note also that due to the two-layer textual substitution semantics all variable references are always substituted. For example:

    config GREETING
            string "Custom greeting"
            default $(DEFAULT_GREETING_IO) if IO
            default $(DEFAULT_GREETING) if !IO

In this example, both `DEFAULT_GREETING` and `DEFAULT_GREETING_IO` must always be defined regardless of which default value is (later) used.

Similar to `make`, Kconfig supports both simple and recursively-expanding variables with the latter used as a building block to support functions. For details, refer to the official Kconfig Macro Language documentation.

The use of the builtin `shell` function in the context of `build2` is not recommended since it will most likely result in portability issues and poor performance.

## 3.7 Helper Options

An option without a prompt or with a prompt that is disabled by `if expr` is invisible to the user. However, such an option can still take on a default value or be set by `select` and `imply` (Reverse Dependencies) with the result still usable inside the `Kconfig` file, for example, for other option's dependencies, as well as accessible outside through the `kconfig.*` Buildfile variables. Such options are called helper options. For example:

    choice
            prompt "Greeting"
            default GREETING_HELLO

    config GREETING_HELLO
            bool "\"Hello\""
            select GREETING_BUILTIN

    config GREETING_HI
            bool "\"Hi\""
            select GREETING_BUILTIN

    config GREETING_HOWDY
            bool "\"Howdy\""
            select GREETING_BUILTIN

    config GREETING_CUSTOM
            bool "Custom greeting"

    endchoice

    config GREETING_BUILTIN
            bool

In this example `GREETING_BUILTIN` is a helper option that is set to true when one of the builtin greeting strings is selected. It can then be used as a dependency for another option, for example:

    config PUNCT
            string "End of greeting punctuation"
            default "!"
            depends on !GREETING_BUILTIN
            help
              Character for punctuating the end of the custom greeting
              sentence.

Continuing with the above example, here is another option that becomes a helper if we are using one of the builtin greeting strings:

    config GREETING_TEXT
            string "Custom greeting" if GREETING_CUSTOM
            default "Hello" if GREETING_HELLO
            default "Hi"    if GREETING_HI
            default "Howdy" if GREETING_HOWDY
            help
              Custom string to use as a greeting.

The idea here is that now we have an option that contains the greeting string in both the builtin and custom cases. As a result, instead of having to write something like this in our `buildfile`:

    if $kconfig.hello.greeting_builtin
    {
      if $kconfig.hello.greeting_hello
        greeting = 'Hello'
      elif $kconfig.hello.greeting_hi
        greeting = 'Hi'
      elif $kconfig.hello.greeting_howdy
        greeting = 'Howdy'
      else
        fail 'unhandled builtin greeting'
    }
    else
      greeting = $kconfig.hello.greeting_text

We can just have:

    greeting = $kconfig.hello.greeting_text

## 3.8 Modularity Support

The Kconfig language provides support for configuration options that besides being selected (`y`) or not (`n`) can also be selected as a module (`m`).

While it may be tempting to try to re-purpose this support for something similar but not quite the same, modularity in Kconfig is fairly purpose-built for the Linux kernel needs and straying too far from its intended semantics will likely result in a poor fit.

The central part of this functionality is the `tristate` type which, in addition to the `bool`'s `y` and `n` states, has the third `m` state. When converted to the `kconfig.*` variables, `tristate` is mapped to the `string` Buildfile type with the `true`, `false`, and `module` possible values.

The availability of this third state is also gated by the specially-designated `bool` option that determines whether overall modules support is enabled. Similarly, in expressions (Expressions) `m` is equivalent to `y` only if modules are enabled. For example:

    config MODULES
           bool "Modules support"
           modules

    config IO
           tristate "IO support"

In the above example, `MODULES` is designated as the modules option with the `modules` attribute. If we answer `y` to `MODULES`, then for `IO` we will be able to choose between `y`, `m`, and `n`. However, if `MODULES` is `n`, then our choice for `IO` will be between `y` and `n`:

    $ b configure
    Modules support (MODULES) [Y/n/?] (NEW) y
    IO support (IO) [N/m/y/?] (NEW)

    $ b configure
    Modules support (MODULES) [Y/n/?] (NEW) n
    IO support (IO) [N/y/?] (NEW)

If we want to unconditionally enable modules in our project, then we can make the `MODULES` option prompt-less with `y` default, for example:

    config MODULES
           bool
           default y
           modules

Only one configuration option can be designated as the module option. This makes it difficult to compose project configuration that use this functionality.

Besides normal options, `tristate` can also be used in choices. Such a choice allows the user to select only one option as `y` but more than one as `m` (again, provided modules are enabled). For example:

    choice
            prompt "Name fallback"

    config NAME_ASK
            tristate "Ask for name"
            help
              Ask for the name to greet if it is unspecified on the
              command line.

    config NAME_DEF
            tristate "Use default name"
            help
              Use the default name to greet if it is unspecified on the
              command line.

    endchoice

## 3.9 Backwards Compatibility

It is typical and well supported by Kconfig to reuse an old configuration when upgrading to a new version of the project (see Configuration Methods for details). As a result, when evolving a project that uses Kconfig, it makes sense to keep backwards compatibility in mind.

Besides a full old configuration, users of our project can also keep minimal default configurations produced with `kconfig-conf --savedefconfig`. Unlike the full configuration which contains all the values, default configurations only contain values that differ from the defaults. Based on this understanding, these changes normally lead to reasonable backwards compatibility:

- Adding new or removing/renaming existing options.
- Moving options around or organizing them into sub-menus.
- Changing dependencies and visibility of existing options, menus, etc.
- Changing prompt or help of existing options, menus, etc.

In contrast, these changes should normally be avoided:

- Changing type of existing options.
- Changing default value or range of existing options.
- Removing existing options from non-optional choices that do not specify a default value.