blob: 918297e0e71f878c88905bc01246c0192f68ed7c [file] [log] [blame]
# Copyright (C) 2022 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""A central location for the list of [config settings](https://bazel.build/extending/config) that
affects the following:
- kernel_build
- kernel_config
This is important for non-sandboxed actions because they may cause clashing in the out/cache
directory.
Only *_flag / *_settings / attributes that affects the content of the cached $OUT_DIR should be
mentioned here. In particular:
- --config=stamp is not in these lists because we don't have two parallel builds
with and without --config=stamp, and we should reuse the same cache for stamped / un-stamped
builds.
- --allow_undeclared_modules is not listed because it only affects artifact collection.
- --preserve_cmd is not listed because it only affects artifact collection.
- The following is not listed because it is already handled by defconfig_fragments. See
kernel_env.bzl, _handle_config_tags:
- btf_debug_info
- gcov
- kcov
- lto (b/257288175)
- trim_nonlisted_kmi
"""
load("@bazel_skylib//lib:dicts.bzl", "dicts")
load("@bazel_skylib//lib:sets.bzl", "sets")
load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
load(":abi/base_kernel_utils.bzl", "base_kernel_utils")
load(":abi/force_add_vmlinux_utils.bzl", "force_add_vmlinux_utils")
load(":compile_commands_utils.bzl", "compile_commands_utils")
load(":kernel_toolchains_utils.bzl", "kernel_toolchains_utils")
load(":kgdb.bzl", "kgdb")
visibility("//build/kernel/kleaf/...")
def _kernel_build_config_settings_raw():
return dicts.add(
force_add_vmlinux_utils.config_settings_raw(),
base_kernel_utils.config_settings_raw(),
kgdb.config_settings_raw(),
compile_commands_utils.config_settings_raw(),
{
"_use_kmi_symbol_list_strict_mode": "//build/kernel/kleaf:kmi_symbol_list_strict_mode",
"_debug": "//build/kernel/kleaf:debug",
"_kasan": "//build/kernel/kleaf:kasan",
"_kasan_sw_tags": "//build/kernel/kleaf:kasan_sw_tags",
"_kasan_generic": "//build/kernel/kleaf:kasan_generic",
"_kcov": "//build/kernel/kleaf:kcov",
"_kcsan": "//build/kernel/kleaf:kcsan",
"_preserve_kbuild_output": "//build/kernel/kleaf:preserve_kbuild_output",
},
)
def _kernel_build_config_settings():
return {
attr_name: attr.label(default = label)
for attr_name, label in _kernel_build_config_settings_raw().items()
}
def _kernel_config_config_settings_raw():
return kgdb.config_settings_raw()
def _kernel_config_config_settings():
return {
attr_name: attr.label(default = label)
for attr_name, label in _kernel_config_config_settings_raw().items()
}
def _kernel_env_config_settings_raw():
return dicts.add(
_kernel_build_config_settings_raw(),
_kernel_config_config_settings_raw(),
force_add_vmlinux_utils.config_settings_raw(),
kgdb.config_settings_raw(),
compile_commands_utils.config_settings_raw(),
{
"_kbuild_symtypes_flag": "//build/kernel/kleaf:kbuild_symtypes",
"_kconfig_werror": "//build/kernel/kleaf:kconfig_werror",
},
)
def _kernel_env_config_settings():
return {
attr_name: attr.label(default = label)
for attr_name, label in _kernel_env_config_settings_raw().items()
}
def _kernel_env_get_config_tags(
ctx,
mnemonic_prefix,
pre_defconfig_fragments,
post_defconfig_fragments):
"""Return necessary files for KernelEnvAttrInfo's fields related to "config tags"
config_tags is the mechanism to isolate --cache_dir.
Requires `ctx.attr._cache_dir_config_tags`.
Args:
ctx: ctx
mnemonic_prefix: prefix to mnemonics for actions created within this function.
pre_defconfig_fragments: a `list[File]` of pre defconfig fragments.
post_defconfig_fragments: a `list[File]` of post defconfig fragments.
Returns:
A struct with two fields:
- common: A File that contains a JSON object containing build configurations
and defconfig fragments.
- env: A File that contains comments about build configurations
defconfig fragments, and the target name, for `kernel_env` output.
"""
# base: just all the different config settings
base_config_tags = _kernel_env_get_base_config_tags(ctx)
base_config_tags_file = ctx.actions.declare_file("{}/base_config_tags.json".format(ctx.label.name))
ctx.actions.write(base_config_tags_file, json.encode_indent(base_config_tags, indent = " "))
# common: base + post_defconfig_fragments
common_config_tags_file = ctx.actions.declare_file("{}/common_config_tags.json".format(ctx.label.name))
args = ctx.actions.args()
args.add("--base", base_config_tags_file)
if pre_defconfig_fragments:
args.add_all("--pre_defconfig_fragments", pre_defconfig_fragments)
if post_defconfig_fragments:
args.add_all("--post_defconfig_fragments", post_defconfig_fragments)
args.add("--dest", common_config_tags_file)
ctx.actions.run(
outputs = [common_config_tags_file],
inputs = depset([base_config_tags_file], transitive = [depset(post_defconfig_fragments)]),
executable = ctx.executable._cache_dir_config_tags,
arguments = [args],
mnemonic = "{}CommonConfigTags".format(mnemonic_prefix),
progress_message = "Creating common_config_tags %{label}",
)
# env: common + label of this kernel_env, prefixed with #
env_config_tags_file = ctx.actions.declare_file("{}/config_tags.txt".format(ctx.label.name))
args = ctx.actions.args()
args.add("--base", common_config_tags_file)
args.add("--target", str(ctx.label))
args.add("--dest", env_config_tags_file)
args.add("--comment")
ctx.actions.run(
outputs = [env_config_tags_file],
inputs = [common_config_tags_file],
executable = ctx.executable._cache_dir_config_tags,
arguments = [args],
mnemonic = "{}ConfigTags".format(mnemonic_prefix),
progress_message = "Creating config_tags %{label}",
)
return struct(
common = common_config_tags_file,
env = env_config_tags_file,
)
def _kernel_env_get_base_config_tags(ctx):
"""Returns dict to compute `OUT_DIR_SUFFIX` for `kernel_env`."""
attr_to_label = _kernel_env_config_settings_raw()
ret = {}
for attr_name in attr_to_label:
attr_target = getattr(ctx.attr, attr_name)
attr_val = attr_target[BuildSettingInfo].value
ret[str(attr_target.label)] = attr_val
toolchains = kernel_toolchains_utils.get(ctx)
ret["toolchain_host_sysroot"] = toolchains.host_sysroot
return ret
# Map of config settings to shortened names
_PROGRESS_MESSAGE_SETTINGS_MAP = {
"force_add_vmlinux": "with_vmlinux",
"force_ignore_base_kernel": "", # already covered by with_vmlinux or build_compile_commands
"kmi_symbol_list_strict_mode": "", # Hide because not interesting
}
def _create_progress_message_item(attr_key, attr_val, map):
print_attr_key = map.get(attr_key, attr_key)
# In _SETTINGS_MAP but value is set to empty to ignore it
if not print_attr_key:
return None
# Empty values that are not interesting enough are dropped
if not attr_val:
return None
if attr_val == True:
return print_attr_key
elif attr_val == False:
return "no{}".format(print_attr_key)
else:
return "{}={}".format(print_attr_key, attr_val)
def _get_progress_message_note(
ctx,
pre_defconfig_fragments,
post_defconfig_fragments):
"""Returns a description text for progress message.
This is a shortened and human-readable version of `kernel_env_get_config_tags`.
Args:
ctx: ctx
pre_defconfig_fragments: a `list[File]` of pre defconfig fragments.
post_defconfig_fragments: a `list[File]` of post defconfig fragments.
Returns:
A string to be added to the end of `progress_message`
"""
attr_to_label = _kernel_env_config_settings_raw()
ret = []
for attr_name in attr_to_label:
attr_target = getattr(ctx.attr, attr_name)
attr_label_name = attr_target.label.name
attr_val = attr_target[BuildSettingInfo].value
item = _create_progress_message_item(
attr_label_name,
attr_val,
_PROGRESS_MESSAGE_SETTINGS_MAP,
)
if not item:
continue
ret.append(item)
# Files under build/kernel/kleaf/impl/defconfig are named as *_defconfig.
# For progress_messsage, we only care about the part before _defconfig.
# See kernel_build.pre_defconfig_fragments and
# kernel_build.post_defconfig_fragments documentation.
for file in pre_defconfig_fragments + post_defconfig_fragments:
ret.append(file.basename.removesuffix("_defconfig"))
ret = sorted(sets.to_list(sets.make(ret)))
ret = ";".join(ret)
if ret:
ret = " ({})".format(ret)
return ret
kernel_config_settings = struct(
of_kernel_build = _kernel_build_config_settings,
of_kernel_config = _kernel_config_config_settings,
of_kernel_env = _kernel_env_config_settings,
kernel_env_get_config_tags = _kernel_env_get_config_tags,
get_progress_message_note = _get_progress_message_note,
)