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 .config
kernel_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
--kasan
--kasan_sw_tags
--kasan_generic
--kcsan
--page_size
--rust
/ --norust
--rust_ashmem
/ --norust_ashmem
NOTE: 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
, --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