To run make *config or config.sh in Kleaf, run
$ tools/bazel run <name_of_kernel_build>_config [-- [menuconfig|nconfig|savedefconfig...]]
... where <name_of_kernel_build> is the name of the kernel_build target with the requested build config.
The menu command (menuconfig, xconfig, etc.) must be provided to the underlying executable, so they need to be provided after --. See Running executables. If nothing is provided, the default is savedefconfig.
Example:
$ tools/bazel run //common:kernel_aarch64_config $ tools/bazel run //common:kernel_x86_64_config -- nconfig
The above command works if the following conditions are satisified:
kernel_build.defconfig is setkernel_build.pre_defconfig_fragments has at most one element.For nconfig etc. to work, ncurses may also be required on the host machine.
If these conditions are not satisified, the command may or may not work.
If kernel_build.pre_defconfig_fragments contains more than one element, the above command prints the path to the generated configs. You may need to apply the generated configs on pre_defconfig_fragments manually.
After the developer goes through the menuconfig / nconfig / xconfig etc. to configure the the kernel, Kleaf does the following:
If kernel_build.pre_defconfig_fragments is empty, Kleaf calls make savedefconfig and copies the minimized defconfig to the source file pointed by kernel_build.defconfig. The path to the updated file is printed.
If kernel_build.pre_defconfig_fragments has a single element, the difference of the .config after and before the developer invokes menuconfig is calculated, and then applied to the pre defconfig fragment. The path to the updated file is printed.
If kernel_build.pre_defconfig_fragments has more than one element, the difference of the .config after and before the developer invokes menuconfig is calculated. Then, the command cowardly fails, with the path to the temporary difference file printed. The developer is expected to move the differences to the correct pre_defconfig_fragments.
NOTE: post_defconfig_fragments does not participate in any of these calculations.
When a kernel_build is built, Kleaf configures the kernel by applying the following steps:
kernel_build.defconfig file is used as a base.kernel_build.pre_defconfig_fragments are applied.make ..._defconfig to build .configkernel_build.check_defconfig is set, calls make savedefconfig and compares it with kernel_build.defconfig. (Note: check_defconfig requires pre_defconfig_fragments to be empty).config contains all configurations in defconfig and pre_defconfig_fragments; see Checks. Otherwise skip.kernel_build.post_defconfig_fragments, --defconfig_fragment and other command line flags (e.g. --kasan) are applied on .config. If anything is applied, calls make olddefconfig..config contains all configurations in post_defconfig_fragments; see Checks.See kernel_build in documentation for all rules for details.
This is the base defconfig.
For GKI and mixed device builds that sets base_kernel to GKI, this is usually the gki_defconfig for the architecture, e.g. //common:arch/arm64/configs/gki_defconfig.
This usually contains a single item so that tools/bazel run XXX_config works. see Modify defconfig: Conditions.
This usually contains configs to build in-tree modules that are not built in the base kernel, e.g. CONFIG_SOME_MODULE=m.
At step 2, When pre defconfig fragments are applied, items in defconfig are overridden. In addition, order matters; items appearing later in the pre_defconfig_fragments list overrides items appearing earlier.
At step 7, Checks are applied with the above in consideration, so you don't have to manually add # nocheck for conflicting items.
Example:
# foo_defconfig CONFIG_A=y
# set_a_defconfig CONFIG_A=y
# unset_a_defconfig # CONFIG_A is not set
# CONFIG_A=y
kernel_build(
defconfig = "foo_defconfig",
pre_defconfig_fragments = [],
# ...
)
# CONFIG_A is not set
kernel_build(
defconfig = "foo_defconfig",
pre_defconfig_fragments = ["unset_a_defconfig"],
# ...
)
# CONFIG_A=y
kernel_build(
defconfig = "foo_defconfig",
pre_defconfig_fragments = ["unset_a_defconfig", "set_a_defconfig"],
# ...
)
This usually contains debug configs to build a variant of the kernel and modules.
Post defconfig fragments consist of the following, in this order:
kernel_build.post_defconfig_fragments--defconfig_fragment--kasan, in an unspecified order.At step 6, When pre defconfig fragments are applied, items in defconfig and pre_defconfig_fragments are overridden by these post defconfig fragments. Then at step 7, Checks are applied with the above in consideration, so you don't have to manually add # nocheck on defconfig and pre_defconfig_fragments even if their values are overridden by post defconfig fragments later.
At step 6, order matters when post defconfig fragments are applied. Items appearing later in the post defconfig fragments list overrides items appearing earlier. However, at step 7, the order in post defconfig fragments does not matter in Checks; all items must exist in the final .config file. As a result, unless you have # nocheck that suppresses conflicts, order usually does not matter.
Example (using foo_defconfig and other files from the previous example):
# CONFIG_A is not set
kernel_build(
defconfig = "foo_defconfig",
post_defconfig_fragments = ["unset_a_defconfig"],
# ...
)
# Build error
# Because unset_a_defconfig conflicts with set_defconfig
kernel_build(
post_defconfig_fragments = ["unset_a_defconfig", "set_defconfig"],
# ...
)
The convention is that the files should be named X_defconfig, where X describes what the defconfig fragment does.
Example:
# path/to/tuna/BUILD.bazel kernel_build( name = "tuna", post_defconfig_fragments = ["tuna_defconfig"], ... )
# path/to/tuna/tuna_defconfig # Precondition: # CONFIG_TUNA_GRAPHICS must already be declared in kernel_build.kconfig_ext CONFIG_TUNA_GRAPHICS=y
You may specify a single target in the --defconfig_fragment flag to add defconfig fragment(s) via the command line. To refer to a file in the source tree, the file must already be exported via exports_files or included in a filegroup.
NOTE: If multiple --defconfig_fragment are supplied, only the last one takes effect.
The convention is that the files should be named X_defconfig, where X describes what the defconfig fragment does.
Example:
# path/to/tuna/BUILD.bazel exports_files([ "kasan_hw_tags_defconfig", ]) kernel_build(name = "tuna", ...)
# kasan_hw_tags_defconfig CONFIG_KASAN=y CONFIG_KASAN_HW_TAGS=y # CONFIG_KASAN_SW_TAGS is not set # etc. Add your configs!
$ tools/bazel build \ --defconfig_fragment=//path/to/tuna:kasan_hw_tags_defconfig \ //path/to/tuna:tuna
To specify multiple fragments in the flag, use a filegroup.
Example:
# path/to/tuna/BUILD.bazel filegroup( name = "all_kasan_defconfigs", srcs = ["kasan_defconfig", "lto_none_defconfig"] ) kernel_build(name = "tuna", ...)
$ tools/bazel build \ --defconfig_fragment=//path/to/tuna:all_kasan_defconfigs \ //path/to/tuna:tuna
There are a few pre-defined command-line flags and attributes on kernel_build that are commonly used. When these flags and/or attributes are set, additional defconfig fragments are applied on .config, and checked after .config is built. It is recommended to use these common flags instead of defining your own defconfig fragments to avoid fragmentation in the ecosystem (pun intended).
--btf_debug_info--debug--gcov--kcov--kasan--kasan_sw_tags--kasan_generic--kcsan--page_size--rust / --norust--rust_ashmem / --norust_ashmemNOTE: w.r.t. to KMI, the following flags will disable both TRIM_UNUSED_KSYMS (by not setting it) and MODULE_SIG_PROTECT(by explicitly turning it off): (--notrim, --debug, --gcov, --kcov, --k*san, --kgdb).
To control kernel_build.post_defconfig_fragments with command line flags, you may use configurable build attributes (sometimes referred to as select()).
Example:
bool_flag( name = "khwasan", build_setting_default = False, ) config_setting( name = "khwasan_is_set", flag_values = {":khwasan": "true"}, ) kernel_build( name = "tuna", post_defconfig_fragments = select({ ":khwasan_is_set": ["khwasan_defconfig"], "//conditions:default": [] }) + [...], ... )
$ tools/bazel build --//path/to/tuna:khwasan //path/to/tuna:tuna
Use device.bazelrc to shorten flags:
# device.bazelrc build --flag_alias=khwasan=--//path/to/tuna:khwasan
$ tools/bazel build --khwasan //path/to/tuna:tuna
To shorten --defconfig_fragment flags, you may use --config in device.bazelrc:
# device.bazelrc build:kasan_hw_tags --defconfig_fragment=//path/to/tuna:kasan_hw_tags_defconfig
$ tools/bazel build --config=kasan_hw_tags //path/to/tuna:tuna
All requirements in defconfig and pre_defconfig_fragments must be present in the intermediate .config before post defconfig fragments are applied, unless:
CONFIG_ in defconfig is overridden by pre_defconfig_fragments.CONFIG_ in pre_defconfig_fragments is overridden by a later value in pre_defconfig_fragments.defconfig, pre_defconfig_fragments has a # nocheck comment appended to it.All post_defconfig_fragments must be present in the final .config, unless the line in post_defconfig_fragments has a # nocheck comment appended to it.
The checks are in place to prevent typos and mistakes. For example, if an item is not declared in Kconfig, then make ..._defconfig silently drops it, but these checks properly flags potential issues.
Example:
# bar_defconfig CONFIG_BASE=y CONFIG_BASE_MODULE=m # CONFIG_MODULE_1 is not set # CONFIG_MODULE_2 is not set # CONFIG_DEBUG_1 is not set # CONFIG_DEBUG_2 is not set
# pre_defconfig CONFIG_MODULE_2=m
# post_1_defconfig CONFIG_DEBUG_1=y CONFIG_DEBUG_2=y # nocheck: (b/12345678) a device does not support this
# post_2_defconfig # CONFIG_DEBUG_2 is not set
kernel_build(
name = "bar",
defconfig = "bar_defconfig",
pre_defconfig_fragments = ["pre_defconfig"],
post_defconfig_fragments = ["post_1_defconfig", "post_2_defconfig"],
)
The resulting .config contains the following, and the check passes:
CONFIG_BASE=y CONFIG_BASE_MODULE=m # CONFIG_MODULE_1 is not set CONFIG_MODULE_2=m CONFIG_DEBUG_1=y # CONFIG_DEBUG_2 is not set