rules_kconfig

Bazel rules for parsing Kconfig files and generating equivalent Bazel build settings.

A kconfig repository exposes each config symbol as a Bazel build setting flag (bool_flag, int_flag, or string_flag) whose default matches the Kconfig-declared default. It also generates a config.h header (via rules_cc_autoconf) that reflects the active flag values, so C/C++ code can consume the configuration with #include "config.h".

Setup

Add the dependency to your MODULE.bazel:

bazel_dep(name = "rules_kconfig", version = "{version}")

Then register a kconfig repository via the module extension:

kconfig = use_extension("@rules_kconfig//kconfig:extensions.bzl", "kconfig")
kconfig.repo(
    name = "my_kconfig",
    kconfig = "//:Kconfig",
    interpreter = "@python_3_14_host//:python",
)
use_repo(kconfig, "my_kconfig")

The Kconfig tree is parsed by kconfiglib in one of two ways; see Backends. The interpreter names a Python interpreter for the Python backend, configured with rules_python:

python = use_extension("@rules_python//python/extensions:python.bzl", "python")
python.toolchain(python_version = "3.14")
use_repo(python, "python_3_14_host")

It can be left out where only the WebAssembly backend is used.

Backends

A kconfig repository is generated by kconfiglib and this repository's generators, running either inside a WebAssembly module or on a host Python.

WebAssembly

Each release of rules_kconfig publishes kconfig.wasm: CPython with kconfiglib and the generators inside, built with rules_venv's py_wasm_module. The release bakes the module's URL and integrity into the rules, and the kconfig extension downloads it through Bazel's repository cache the first time a repository is generated with it. On Bazel 9.3 or newer with

common --experimental_repository_ctx_execute_wasm

in .bazelrc, the repository rules run it with repository_ctx.execute_wasm and no Python interpreter is needed: the module cannot touch the filesystem or run commands, so the rules read the Kconfig files, list directories for source globs and run $(shell,...) commands on its behalf, in rounds, and every file read is recorded as an input of the repository. With Bazel 10, --experimental_repository_ctx_wasm_compilation compiles the module to JVM bytecode, which is several times faster than interpreting it.

Python

Otherwise the generators run on the interpreter, with kconfiglib fetched as a wheel. This is the backend for Bazel 7 and 8.

Choosing

The WebAssembly backend is used whenever Bazel can run it and there is a module: a release has one, a source checkout of rules_kconfig does not. The interpreter is then ignored. Otherwise the Python backend runs, and a missing interpreter is an error that says which of the two conditions failed. There is no setting to choose; the Bazel flag is the switch.

For a source checkout, RULES_KCONFIG_WASM (through --repo_env) names a module to use, an absolute path or a URL, for instance the output of bazel build @rules_kconfig//kconfig/private/wasm:kconfig_wasm; RULES_KCONFIG_WASM_INTEGRITY may give the integrity (sha256-...) of a URL.

Both backends produce the same repository: the module runs the same Python code, and //kconfig/private/wasm:entry_test checks the two against each other.

Generated repository

For a Kconfig file such as:

config FOO
    bool "Enable FOO"
    default n

config COUNT
    int "Count"
    default 3

The generated repository @my_kconfig contains:

TargetDescription
@my_kconfig//:CONFIG_FOObool_flag (default False)
@my_kconfig//:CONFIG_COUNTint_flag (default 3)
@my_kconfig//:configcc_library providing config.h
@my_kconfig//settings.CONFIG_FOO_Yconfig_setting matching CONFIG_FOO = true
@my_kconfig//settings.CONFIG_FOO_Nconfig_setting matching CONFIG_FOO = false
@my_kconfig//settings.CONFIG_COUNT_3config_setting matching CONFIG_COUNT = 3

Usage

Setting flag values

Flags can be set on the command line or in .bazelrc:

build --@my_kconfig//:CONFIG_FOO=true
build --@my_kconfig//:CONFIG_COUNT=7

Consuming config.h

Depend on the generated cc_library to include the header:

cc_library(
    name = "mylib",
    srcs = ["mylib.c"],
    deps = ["@my_kconfig//:config"],
)
#include "config.h"

#if CONFIG_FOO
/* FOO is enabled */
#endif

The header follows the Kconfig tools' autoconf.h: bool and tristate symbols set to y define CONFIG_<name> as 1, a tristate set to m defines CONFIG_<name>_MODULE instead, int and hex values are unquoted, string values are quoted, and a symbol that is n or an empty string is left undefined.

Reacting to flags with config_setting

The generated repository includes a settings/ subpackage with config_setting targets for every flag. Bool flags produce two targets: CONFIG_<NAME>_Y (matching "true") and CONFIG_<NAME>_N (matching "false"). Int and string flags produce a target matching their Kconfig default value (named CONFIG_<NAME>_<value>).

Use these directly in select():

cc_library(
    name = "mylib",
    srcs = ["mylib.c"],
    deps = select({
        "@my_kconfig//settings:kconfig.CONFIG_FOO_Y": ["//extras:foo_support"],
        "//conditions:default": [],
    }),
)

Custom values with kconfig_config_settings

To match non-default values or multiple values for an int/string flag, load the generated settings.bzl macro and pass an options dict. The name parameter prefixes every generated target:

load("@my_kconfig//:settings.bzl", "kconfig_config_settings")

kconfig_config_settings(
    name = "settings",
    options = {
        "CONFIG_COUNT": ["1", "3", "5"],
    },
)

This produces settings.CONFIG_FOO (bool, auto), settings.CONFIG_COUNT_1, settings.CONFIG_COUNT_3, and settings.CONFIG_COUNT_5. Flags not listed in options fall back to their Kconfig default. Flags with neither are simply skipped.

Providing defaults via .config

You can supply a .config file to override Kconfig defaults. Pass the defaults attribute when declaring the repository:

kconfig.repo(
    name = "my_kconfig",
    kconfig = "//:Kconfig",
    defaults = "//:.config",
    interpreter = "@python3_host//:python",
)

If any Kconfig symbol uses $(shell,...) for its default and is not explicitly set in the .config file, the repository rule will fail with an actionable error message.

Interactive configuration with menuconfig

The menuconfig rule launches kconfiglib's terminal UI for interactive Kconfig editing. Add a target to your BUILD.bazel:

load("@rules_kconfig//kconfig:menuconfig.bzl", "menuconfig")

menuconfig(
    name = "menuconfig",
    kconfig = "//:Kconfig",
)

Then run:

bazel run //:menuconfig

The TUI reads and writes the .config file in your workspace root.

Build-time values with settings_labels

Some Kconfig symbols derive their default from the build environment using $(shell,...) macros — for example, a compiler version obtained from the active toolchain:

config CLANG_VERSION
    int
    default $(shell,$(srctree)/scripts/clang-version.sh $(CC))

These values cannot be resolved at repository-rule time. Use settings_labels to replace a generated flag with a user-provided rule that supplies the value during the build:

kconfig.repo(
    name = "my_kconfig",
    kconfig = "//:Kconfig",
    interpreter = "@python3_host//:python",
    settings_labels = {
        "//:clang_version": "CONFIG_CLANG_VERSION",
    },
)

The label must point to a target that provides BuildSettingInfo. Since Bazel does not allow build_setting rules to resolve toolchains (bazelbuild/bazel#21545), write a regular rule instead:

load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")

def _clang_version_impl(ctx):
    cc_toolchain = ctx.toolchains["@rules_cc//cc:toolchain_type"]
    # ... compute version from toolchain ...
    return [BuildSettingInfo(value = version)]

clang_version = rule(
    implementation = _clang_version_impl,
    toolchains = ["@rules_cc//cc:toolchain_type"],
)

Settings provided via settings_labels:

  • appear in the generated config.h with the correct value,
  • are excluded from config_setting generation (they are not flags, so flag_values cannot reference them),
  • cannot be set from the command line,
  • are skipped by kconfig.overrides transitions — the value always comes from the user-provided rule.

See examples/settings_labels/ for a complete working example including an overrides layer.

Overriding configuration on external repositories

When a kconfig repository is declared by an external dependency, use kconfig.overrides to overlay your own .config without modifying the external module. If the source repository was itself created with a .config, the overrides are stacked on top of those base values:

kconfig = use_extension("@rules_kconfig//kconfig:extensions.bzl", "kconfig")
kconfig.overrides(
    name = "my_board_config",
    kconfig = "@ext_kconfig//:ext_kconfig",
    config = "//:.config",
    interpreter = "@python3_host//:python",
)
use_repo(kconfig, "my_board_config")

Then wrap targets that depend on kconfig flags with the generated transition rule:

load("@my_board_config//:defs.bzl", "with_kconfig_overrides")

with_kconfig_overrides(
    name = "ext_config_customized",
    actual = "@ext_kconfig//:config",
)

Values explicitly set on the command line take precedence over the overlay.

rules_kconfig

Bazel rules for parsing Kconfig files and generating equivalent Bazel build settings and config.h headers.

Module extension

The primary interface is the kconfig module extension. Each kconfig.repo tag parses a Kconfig file tree and generates a repository containing:

  • A bool_flag, int_flag, or string_flag for every config symbol.
  • A cc_library target (:config) that provides config.h reflecting the active flag values.
kconfig = use_extension("@rules_kconfig//kconfig:extensions.bzl", "kconfig")
kconfig.repo(
    name = "my_kconfig",
    kconfig = "//:Kconfig",
    interpreter = "@python_3_14_host//:python",
)
use_repo(kconfig, "my_kconfig")

The interpreter is used by the Python backend. On Bazel 9.3 or newer with --experimental_repository_ctx_execute_wasm, a release of rules_kconfig parses with the WebAssembly module it publishes instead, and no interpreter is needed.

Use kconfig.overrides to overlay a .config file onto an external kconfig repository via a Starlark transition:

kconfig.overrides(
    name = "my_board_config",
    kconfig = "@ext_kconfig//:ext_kconfig",
    config = "//:.config",
    interpreter = "@python_3_14_host//:python",
)
use_repo(kconfig, "my_board_config")

See the Introduction for full setup and usage instructions.

Rules

Providers

Repository Rules

Module Extensions

kconfig_library

load("@rules_kconfig//kconfig:defs.bzl", "kconfig_library")

kconfig_library(name, deps, srcs, root)

Collect Kconfig source files into a single provider for use by menuconfig and repository rules.

All source files must be real (non-generated) files. If a single source is provided, it is automatically treated as the root. When multiple sources are present, set root explicitly to indicate the top-level Kconfig entry point. Transitive sources from deps are included in the provider.

ATTRIBUTES

NameDescriptionTypeMandatoryDefault
nameA unique name for this target.Namerequired
depsOther kconfig_library targets whose sources should be included transitively.List of labelsoptional[]
srcsKconfig source files. Must be real (non-generated) files.List of labelsoptional[]
rootThe top-level Kconfig file. Inferred automatically when srcs contains exactly one file.LabeloptionalNone

kconfig_toolchain

load("@rules_kconfig//kconfig:defs.bzl", "kconfig_toolchain")

kconfig_toolchain(name, kconfiglib)

Declares a kconfig toolchain backed by kconfiglib.

ATTRIBUTES

NameDescriptionTypeMandatoryDefault
nameA unique name for this target.Namerequired
kconfiglibA py_library providing kconfiglib.Labelrequired

load("@rules_kconfig//kconfig:defs.bzl", "menuconfig")

menuconfig(name, config, kconfig)

Launch kconfiglib's menuconfig TUI for interactive Kconfig editing.

Run with bazel run to interactively create or edit a .config file against a Kconfig tree. The TUI writes the resulting configuration to the path specified by config (relative to the workspace root).

ATTRIBUTES

NameDescriptionTypeMandatoryDefault
nameA unique name for this target.Namerequired
configWorkspace-relative path to the .config file to read/write.Stringrequired
kconfigA kconfig_library target providing the Kconfig source tree.Labelrequired

KConfigInfo

load("@rules_kconfig//kconfig:defs.bzl", "KConfigInfo")

KConfigInfo(root, srcs)

Encapsulates a Kconfig source tree: an optional root file and all source files (direct and transitive).

FIELDS

NameDescription
rootOptional[File]: The top-level Kconfig file that kconfiglib should parse. May be None when a library contributes sources but is not itself a root.
srcsdepset[File]: All Kconfig source files (direct and transitive) reachable from this library.

KconfigSettingsInfo

load("@rules_kconfig//kconfig:defs.bzl", "KconfigSettingsInfo")

KconfigSettingsInfo(settings)

Aggregates BuildSettingInfo from all CONFIG_* flags in a kconfig repository.

FIELDS

NameDescription
settingsdict[str, BuildSettingInfo]: Maps CONFIG_* names to their BuildSettingInfo.

kconfig_overrides_repository

load("@rules_kconfig//kconfig:defs.bzl", "kconfig_overrides_repository")

kconfig_overrides_repository(name, config, interpreter, kconfig, kconfiglib_anchor, wasm_module)

Overlay .config values onto an existing kconfig repository.

Reads the manifest from the source kconfig repository to locate the symlinked Kconfig source tree, then reparses with kconfiglib and a user-provided .config file. If the source repository was itself created with a .config, the overrides are stacked on top of those base values. Generates a defs.bzl containing a Starlark transition and wrapper rule that apply the overrides.

Values explicitly set on the command line take precedence over the overlay.

The generated defs.bzl creates the transition and rule:

ruledescription
kconfig_override_transitionA transition that applies transitions for each default in .config
with_kconfig_overridesA rule similar to alias that applies kconfig_override_transition to the target

Use with_kconfig_overrides to wrap a kconfig-dependent target:

load("@base_kconfig_override//:defs.bzl", "with_kconfig_overrides")

with_kconfig_overrides(
    name = "config",
    actual = ":consumer_of_base",
)

ATTRIBUTES

NameDescriptionTypeMandatoryDefault
nameA unique name for this repository.Namerequired
config.config file with override values.Labelrequired
interpreterA Python interpreter target used to run the generator when the WebAssembly backend is not available.LabeloptionalNone
kconfigLabel to the kconfig manifest from the source kconfig repository (e.g. @my_kconfig//:my_kconfig).Labelrequired
kconfiglib_anchorLabel used to locate the kconfiglib package. Managed by the module extension.Labelrequired
wasm_moduleThe WebAssembly backend (kconfig.wasm), used on Bazel 9.3 or newer with --experimental_repository_ctx_execute_wasm. The kconfig module extension provides the module of the release, or the one RULES_KCONFIG_WASM names; without one the Python interpreter is used.LabeloptionalNone

kconfig_repository

load("@rules_kconfig//kconfig:defs.bzl", "kconfig_repository")

kconfig_repository(name, apparent_name, defaults, interpreter, kconfig, kconfiglib_anchor,
                   settings_labels, settings_options, wasm_module)

Parse a Kconfig file tree and generate a Bazel repository with build settings.

The generated repository contains a bool_flag, int_flag, or string_flag for every config symbol found in the Kconfig tree, plus a cc_library target (:config) providing a config.h header that reflects the active flag values.

The Kconfig source tree is symlinked into kconfig_srcs/ and a kconfig.manifest.json records the root file and all visited files. A repo-named symlink (e.g. @my_kconfig//:my_kconfig) points to the manifest for downstream consumers.

The Kconfig tree is parsed by kconfiglib, either inside the WebAssembly module a release of rules_kconfig carries (Bazel 9.3 or newer with --experimental_repository_ctx_execute_wasm; no interpreter needed) or by the Python interpreter. The interpreter is ignored when the module is used.

Prefer using the kconfig module extension rather than calling this rule directly.

ATTRIBUTES

NameDescriptionTypeMandatoryDefault
nameA unique name for this repository.Namerequired
apparent_nameThe user-facing repository name (used for the repo-named symlink). Defaults to the canonical name.Stringoptional""
defaultsOptional .config file with explicit symbol values that override Kconfig defaults.LabeloptionalNone
interpreterA Python interpreter target used to run the Kconfig parser when the WebAssembly backend is not available.LabeloptionalNone
kconfigThe root Kconfig file to parse. All files referenced via source directives are followed automatically.Labelrequired
kconfiglib_anchorLabel used to locate the kconfiglib package. Managed by the module extension.Labelrequired
settings_labelsMap of CONFIG_* names to label strings for user-provided rules that replace generated flags. The label must point to a target that provides BuildSettingInfo. Use this for symbols whose values depend on the build configuration (e.g. toolchain-derived values like compiler version).Dictionary: String -> Stringoptional{}
settings_optionsOptional map of CONFIG_* names to lists of string values for generated config_settings.Dictionary: String -> List of stringsoptional{}
wasm_moduleThe WebAssembly backend (kconfig.wasm), used on Bazel 9.3 or newer with --experimental_repository_ctx_execute_wasm. The kconfig module extension provides the module of the release, or the one RULES_KCONFIG_WASM names; without one the Python interpreter is used.LabeloptionalNone

kconfig

kconfig = use_extension("@rules_kconfig//kconfig:defs.bzl", "kconfig")
kconfig.overrides(name, config, interpreter, kconfig)
kconfig.repo(name, defaults, interpreter, kconfig, settings_labels, settings_options)

Configure kconfig repositories.

TAG CLASSES

overrides

Overlay .config overrides onto an existing kconfig repository.

Attributes

NameDescriptionTypeMandatoryDefault
nameThe name of the generated overrides repository.Namerequired
config.config file with override values.Labelrequired
interpreterA Python interpreter target (e.g. @python_3_14_host//:python). See kconfig.repo.LabeloptionalNone
kconfigLabel to the kconfig manifest from the source repository (e.g. @ext_kconfig//:ext_kconfig).Labelrequired

repo

Declare a kconfig repository to be generated from a Kconfig file tree.

Attributes

NameDescriptionTypeMandatoryDefault
nameThe name of the generated repository. Symbols are accessible as @<name>//:CONFIG_<symbol>.Namerequired
defaultsOptional .config file providing default overrides for Kconfig symbols.LabeloptionalNone
interpreterA Python interpreter target used to run the Kconfig parser (e.g. @python_3_14_host//:python).

Not needed on Bazel 9.3 or newer with --experimental_repository_ctx_execute_wasm, where a release of rules_kconfig parses with its WebAssembly module instead; required otherwise.
LabeloptionalNone
kconfigThe root Kconfig file to parse. All files referenced via source directives are followed automatically.Labelrequired
settings_labelsMap of user-provided rule labels to CONFIG_* names they replace. Each label must point to a target that provides BuildSettingInfo. Use this for symbols whose values depend on the build configuration (e.g. toolchain-derived values like compiler version).Dictionary: Label -> Stringoptional{}
settings_optionsOptional map of CONFIG_* names to lists of string values for generated config_settings.Dictionary: String -> List of stringsoptional{}