blob: 386004657395366a03a229ab7f23394619a6e38d [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.
"""Source-able build environment for kernel build."""
load("@bazel_skylib//lib:dicts.bzl", "dicts")
load("@bazel_skylib//lib:paths.bzl", "paths")
load("@bazel_skylib//lib:shell.bzl", "shell")
load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
load("@kernel_toolchain_info//:dict.bzl", "VARS")
load(":abi/force_add_vmlinux_utils.bzl", "force_add_vmlinux_utils")
load(
":common_providers.bzl",
"KernelBuildConfigInfo",
"KernelEnvAttrInfo",
"KernelEnvInfo",
"KernelEnvMakeGoalsInfo",
"KernelToolchainInfo",
)
load(":compile_commands_utils.bzl", "compile_commands_utils")
load(":debug.bzl", "debug")
load(":hermetic_toolchain.bzl", "hermetic_toolchain")
load(":kernel_config_settings.bzl", "kernel_config_settings")
load(":kernel_dtstree.bzl", "DtstreeInfo")
load(":kernel_toolchains_utils.bzl", "kernel_toolchains_utils")
load(":kgdb.bzl", "kgdb")
load(":set_kernel_dir.bzl", "set_kernel_dir")
load(":stamp.bzl", "stamp")
load(":status.bzl", "status")
load(":utils.bzl", "utils")
visibility("//build/kernel/kleaf/...")
def _get_kbuild_symtypes(ctx):
if ctx.attr.kbuild_symtypes == "auto":
return ctx.attr._kbuild_symtypes_flag[BuildSettingInfo].value
elif ctx.attr.kbuild_symtypes == "true":
return True
elif ctx.attr.kbuild_symtypes == "false":
return False
# Should not reach
fail("{}: kernel_env has unknown value for kbuild_symtypes: {}".format(ctx.attr.label, ctx.attr.kbuild_symtypes))
def _get_set_arch_cmd(ctx):
"""Returns command that sets ARCH.
This is called before `source _setup_env.sh` so that it can be overridden by build configs.
"""
toolchains = kernel_toolchains_utils.get(ctx)
inferred_arch = toolchains.target_arch
if inferred_arch == "riscv64":
inferred_arch = "riscv"
return """
export ARCH="{inferred_arch}"
""".format(
inferred_arch = inferred_arch,
)
def _get_check_arch_cmd(ctx):
toolchains = kernel_toolchains_utils.get(ctx)
declared_arch = toolchains.target_arch
level = "WARNING"
exit_cmd = ""
if ctx.attr._kernel_use_resolved_toolchains[BuildSettingInfo].value:
level = "ERROR"
exit_cmd = "exit 1"
return """
if [[ "${{ARCH/riscv/riscv64}}" != "{declared_arch}" ]]; then
echo '{level}: {label} must specify arch = '"${{ARCH/riscv/riscv64}}"', but is {declared_arch}.' >&2
{exit_cmd}
fi
""".format(
level = level,
label = ctx.label,
declared_arch = declared_arch,
exit_cmd = exit_cmd,
)
def _get_set_ndk_triple_cmd():
"""Returns command that sets NDK_TRIPLE."""
return """
if [[ "${ARCH}" == "arm64" ]]; then
export NDK_TRIPLE="${AARCH64_NDK_TRIPLE}"
elif [[ "${ARCH}" == "x86_64" ]]; then
export NDK_TRIPLE="${X86_64_NDK_TRIPLE}"
elif [[ "${ARCH}" == "arm" ]]; then
export NDK_TRIPLE="${ARM_NDK_TRIPLE}"
fi
"""
def _get_make_goals(ctx):
# Fallback to goals from build.config
make_goals = ["${MAKE_GOALS}"]
if ctx.attr.make_goals:
# This is a basic sanitization of the input.
for goal in ctx.attr.make_goals:
if " " in goal or ";" in goal:
fail("ERROR {}: '{}' is not a valid item of make_goals.".format(ctx.label, goal))
make_goals = list(ctx.attr.make_goals)
make_goals += force_add_vmlinux_utils.additional_make_goals(ctx)
make_goals += kgdb.additional_make_goals(ctx)
make_goals += compile_commands_utils.additional_make_goals(ctx)
return make_goals
def _get_make_goals_deprecation_warning(ctx):
# Omit the warning if the goals have been set
if ctx.attr.make_goals:
return ""
msg = """
# Warning about MAKE_GOALS deprecation.
if [[ -n ${{MAKE_GOALS}} ]] ; then
KLEAF_MAKE_TARGETS=$(echo "${{MAKE_GOALS% }}" | sed '/^$/d' | sed 's/\\S*/ "&",/g')
# Omit when empty.
if [[ -z ${{KLEAF_MAKE_TARGETS}} ]]; then
echo "WARNING: Empty MAKE_GOALS detected. Ensure all targets are listed explicitly."
else
echo "WARNING: MAKE_GOALS from build.config is being deprecated, use make_goals in kernel_build;" >&2
echo "Consider adding:\n\nmake_goals = [\n${{KLEAF_MAKE_TARGETS}}" >&2
echo "],\n\nto {build_target} kernel." >&2
fi
unset KLEAF_MAKE_TARGETS
fi
""".format(
build_target = str(ctx.label).removesuffix("_env"),
)
return msg
def _get_kconfig_werror_setup(ctx):
if not ctx.attr._kconfig_werror[BuildSettingInfo].value:
return ""
return "export KCONFIG_WERROR=1"
def _get_build_config_inputs_impl(_subrule_ctx, *, srcs, build_config):
"""Gets the list of build config files needed for the build config step.
This can be an overestimate."""
# If kernel_build.build_config is not set (build config-less builds), we shouldn't
# need any build configs. Return early to avoid the big depset expansion in srcs.
if not build_config or not build_config.files:
return depset()
# The depset expansion is unavoidable to reduce the list of inputs fed
# into the action. This reduces incremental build times by increasing time in the analysis
# phase.
inputs = [
s
for s in depset(transitive = [target.files for target in srcs]).to_list()
if "/build.config" in s.path or s.path.startswith("build.config")
]
transitive_inputs = [build_config.files]
if KernelBuildConfigInfo in build_config:
transitive_inputs.append(build_config[KernelBuildConfigInfo].deps)
for target in srcs:
if KernelBuildConfigInfo in target:
transitive_inputs.append(target[KernelBuildConfigInfo].deps)
return depset(inputs, transitive = transitive_inputs)
_get_build_config_inputs = subrule(implementation = _get_build_config_inputs_impl)
def _kernel_env_impl(ctx):
kconfig_ext = ctx.file.kconfig_ext
dtstree_makefile = None
dtstree_srcs = []
if ctx.attr.dtstree != None:
dtstree_makefile = ctx.attr.dtstree[DtstreeInfo].makefile
dtstree_srcs = ctx.attr.dtstree[DtstreeInfo].srcs
setup_env = ctx.file.setup_env
out_file = ctx.actions.declare_file("%s.sh" % ctx.attr.name)
hermetic_tools = hermetic_toolchain.get(ctx)
inputs = []
transitive_inputs = [_get_build_config_inputs(
srcs = ctx.attr.srcs,
build_config = ctx.attr.build_config,
)]
tools = [
setup_env,
ctx.file._build_utils_sh,
]
transitive_tools = [hermetic_tools.deps]
toolchains = kernel_toolchains_utils.get(ctx)
set_kernel_dir_ret = set_kernel_dir(makefile = ctx.file.makefile)
command = hermetic_tools.setup
if ctx.attr._debug_annotate_scripts[BuildSettingInfo].value:
command += debug.trap()
if kconfig_ext:
command += """
export KCONFIG_EXT={kconfig_ext}
""".format(
kconfig_ext = kconfig_ext.path,
)
if dtstree_makefile:
command += """
export DTSTREE_MAKEFILE={dtstree}
""".format(
dtstree = dtstree_makefile.short_path,
)
command += _get_make_verbosity_command(ctx)
kbuild_symtypes = _get_kbuild_symtypes(ctx)
command += """
export KBUILD_SYMTYPES={}
""".format("1" if kbuild_symtypes else "")
# If multiple targets have the same KERNEL_DIR are built simultaneously
# with --spawn_strategy=local, try to isolate their OUT_DIRs.
pre_defconfig_fragments = ctx.files.pre_defconfig_fragments
post_defconfig_fragments = ctx.files.post_defconfig_fragments
config_tags_out = kernel_config_settings.kernel_env_get_config_tags(
ctx = ctx,
mnemonic_prefix = "KernelEnv",
pre_defconfig_fragments = pre_defconfig_fragments,
post_defconfig_fragments = post_defconfig_fragments,
)
inputs.append(config_tags_out.env)
# For actions using cache_dir, OUT_DIR_SUFFIX is handled by cache_dir.bzl.
# For actions that do not use cache_dir, OUT_DIR_SUFFIX is useless because
# the action is already in a sandbox. Hence unset it.
command += """
export OUT_DIR_SUFFIX=
"""
set_source_date_epoch_ret = stamp.set_source_date_epoch(ctx)
command += set_source_date_epoch_ret.cmd
inputs += set_source_date_epoch_ret.deps
make_goals = _get_make_goals(ctx)
make_goals_deprecation_warning = _get_make_goals_deprecation_warning(ctx)
kconfig_werror_setup = _get_kconfig_werror_setup(ctx)
env_setup_cmds = _get_env_setup_cmds(ctx)
pre_env_script = ctx.actions.declare_file("{}/pre_env.sh".format(ctx.attr.name))
ctx.actions.write(pre_env_script, env_setup_cmds.pre_env)
post_env_script = ctx.actions.declare_file("{}/post_env.sh".format(ctx.attr.name))
ctx.actions.write(post_env_script, env_setup_cmds.post_env)
inputs += [pre_env_script, post_env_script]
kleaf_repo_workspace_root = Label(":kernel_env.bzl").workspace_root
if kleaf_repo_workspace_root:
bin_dir_and_workspace_root = paths.join(ctx.bin_dir.path, kleaf_repo_workspace_root)
else:
bin_dir_and_workspace_root = ctx.bin_dir.path
quoted_space_and_extra_kcflags = ""
if ctx.attr.kcflags:
quoted_space_and_extra_kcflags = shell.quote(" " + (" ".join(ctx.attr.kcflags)))
command += """
export DEPMOD=depmod
export DTC=$(command -v dtc)
export LLVM=1
# create a build environment
source {build_utils_sh}
""".format(
build_utils_sh = ctx.file._build_utils_sh.path,
)
if ctx.attr.build_config and ctx.attr.build_config.files:
command += """
export BUILD_CONFIG={build_config}
""".format(
build_config = utils.optional_single_path(ctx.files.build_config),
)
else:
command += """
export KLEAF_INTERNAL_NO_BUILD_CONFIG=1
"""
# Set branch specific constants.
for key, value in VARS.items():
command += """
export {quoted_key}={quoted_value}
""".format(
quoted_key = shell.quote(key),
quoted_value = shell.quote(value),
)
if ctx.file.clang_autofdo_profile:
set_clang_autofdo_profile_cmd = "export CLANG_AUTOFDO_PROFILE=${ROOT_DIR}/" + ctx.file.clang_autofdo_profile.path
else:
set_clang_autofdo_profile_cmd = ""
command += """
export KCFLAGS="${{KCFLAGS}}"{quoted_space_and_extra_kcflags}
{set_kernel_dir_cmd}
{set_localversion_cmd}
{set_arch_cmd}
source {setup_env}
{check_arch_cmd}
{set_ndk_triple_cmd}
# Variables from resolved toolchain
{toolchains_setup_env_var_cmd}
{set_clang_autofdo_profile_cmd}
# TODO(b/236012223) Remove the warning after deprecation.
{make_goals_deprecation_warning}
# Enforce check configs.
{kconfig_werror_setup}
# Identify the build user as 'kleaf' to recognize a kleaf-built kernel
export KBUILD_BUILD_USER=kleaf
# Make it so that Rust symbol names do not change when the version
# string of rustc changes. Note that since the version string includes
# the date and commit hash from the build environment, even a respin of
# rustc could cause symbol names to change without this option.
#
# https://github.com/rust-lang/rust/blob/617aad8c2e8783f6df8e5d1f8bb1e4bcdc70aa7b/compiler/rustc_span/src/def_id.rs#L179-L189
export RUSTC_FORCE_RUSTC_VERSION=rustc-android
# Add a comment with config_tags for debugging
cp -p {config_tags_comment_file} {out}
chmod +w {out}
echo >> {out}
cat {pre_env_script} >> {out}
echo >> {out}
# capture it as a file to be sourced in downstream rules
( export -p; export -f ) | \\
# Remove TMPDIR, set by build bots. Other targets built by the
# current `bazel` command are affected by the same TMPDIR env var.
# However, we do not want kernel_filegroup to inherit TMPDIR.
sed '/^declare -x TMPDIR=/d' | \\
# Remove the reference to PWD itself
sed '/^declare -x PWD=/d' | \\
# Now ensure, new PWD gets expanded
sed "s|${{PWD}}|\\$PWD|g" | \\
# Drop reference to bin_dir and replace with variable;
# Replace $PWD/<not out> with $KLEAF_REPO_DIR/$1
sed "s|\\$PWD/{hermetic_base}|\\$PWD/\\$KLEAF_HERMETIC_BASE|g" | \\
sed "s|\\$PWD/{bin_dir_and_workspace_root}|\\$PWD/\\$KLEAF_BIN_DIR_AND_WORKSPACE_ROOT|g" | \\
sed "s|{bin_dir_and_workspace_root}|\\$KLEAF_BIN_DIR_AND_WORKSPACE_ROOT|g" | \\
# List of packages that //build/kernel/... depends on. This excludes
# external/ because they are in different Bazel repositories.
sed "s|\\$PWD/build|\\$KLEAF_REPO_DIR/build|g" | \\
sed "s|\\$PWD/prebuilts|\\$KLEAF_REPO_DIR/prebuilts|g" \\
>> {out}
echo >> {out}
cat {post_env_script} >> {out}
""".format(
quoted_space_and_extra_kcflags = quoted_space_and_extra_kcflags,
set_kernel_dir_cmd = set_kernel_dir_ret.cmd,
set_localversion_cmd = stamp.set_localversion_cmd(ctx),
set_arch_cmd = _get_set_arch_cmd(ctx),
setup_env = setup_env.path,
check_arch_cmd = _get_check_arch_cmd(ctx),
set_ndk_triple_cmd = _get_set_ndk_triple_cmd(),
toolchains_setup_env_var_cmd = toolchains.kernel_setup_env_var_cmd,
set_clang_autofdo_profile_cmd = set_clang_autofdo_profile_cmd,
make_goals_deprecation_warning = make_goals_deprecation_warning,
kconfig_werror_setup = kconfig_werror_setup,
out = out_file.path,
config_tags_comment_file = config_tags_out.env.path,
pre_env_script = pre_env_script.path,
post_env_script = post_env_script.path,
hermetic_base = hermetic_tools.internal_hermetic_base,
bin_dir_and_workspace_root = bin_dir_and_workspace_root,
)
progress_message_note = kernel_config_settings.get_progress_message_note(
ctx,
pre_defconfig_fragments,
post_defconfig_fragments,
)
debug.print_scripts(ctx, command)
ctx.actions.run_shell(
mnemonic = "KernelEnv",
inputs = depset(inputs, transitive = transitive_inputs),
outputs = [out_file],
tools = depset(tools, transitive = transitive_tools),
progress_message = "Creating build environment{} %{{label}}".format(progress_message_note),
command = command,
)
setup = get_env_info_setup_command(
hermetic_tools_setup = hermetic_tools.setup,
build_utils_sh = ctx.file._build_utils_sh,
env_setup_script = out_file,
)
setup_tools = [
ctx.file._build_utils_sh,
]
setup_transitive_tools = [
toolchains.all_files,
hermetic_tools.deps,
]
setup_inputs = [
out_file,
ctx.version_file,
]
if kconfig_ext:
setup_inputs.append(kconfig_ext)
if ctx.file.clang_autofdo_profile:
setup_inputs.append(ctx.file.clang_autofdo_profile)
setup_inputs += dtstree_srcs
env_info = KernelEnvInfo(
inputs = depset(setup_inputs),
tools = depset(setup_tools, transitive = setup_transitive_tools),
setup = setup,
toolchains = toolchains,
)
return [
env_info,
KernelEnvAttrInfo(
kbuild_symtypes = kbuild_symtypes,
progress_message_note = progress_message_note,
common_config_tags = config_tags_out.common,
),
KernelEnvMakeGoalsInfo(
make_goals = make_goals,
),
KernelToolchainInfo(
toolchain_version = toolchains.compiler_version,
),
DefaultInfo(files = depset([out_file])),
]
def get_env_info_setup_command(
hermetic_tools_setup,
build_utils_sh,
env_setup_script):
"""Returns text for KernelEnvInfo.setup"""
return """{hermetic_tools_setup}
if [ -n "${{BUILD_WORKSPACE_DIRECTORY}}" ] || [ "${{BAZEL_TEST}}" = "1" ]; then
source {build_utils_sh_short}
# source the build environment
source {env_setup_script_short}
else
source {build_utils_sh}
# source the build environment
source {env_setup_script}
fi
""".format(
hermetic_tools_setup = hermetic_tools_setup,
build_utils_sh_short = build_utils_sh.short_path,
build_utils_sh = build_utils_sh.path,
env_setup_script_short = env_setup_script.short_path,
env_setup_script = env_setup_script.path,
)
def _get_env_setup_cmds(ctx):
hermetic_tools = hermetic_toolchain.get(ctx)
pre_env = ""
if ctx.attr._debug_annotate_scripts[BuildSettingInfo].value:
pre_env += debug.trap()
kleaf_repo_workspace_root = Label(":kernel_env.bzl").workspace_root
pre_env += """
# KLEAF_REPO_WORKSPACE_ROOT: workspace_root of the Kleaf repository. See Label.workspace_root.
# This should be:
# - Either an empty string if @kleaf is the root module;
# - or external/kleaf (or some variations of it) if @kleaf is a dependent module
# This may be overridden by kernel_filegroup.
KLEAF_REPO_WORKSPACE_ROOT=${{KLEAF_REPO_WORKSPACE_ROOT:-{kleaf_repo_workspace_root}}}
# hermetic_base for hermetic tools, relative to execroot. This is
# handled separately from bin_dir because hermetic_tools has a transition
# attached to it.
if [ -n "${{BUILD_WORKSPACE_DIRECTORY}}" ] || [ "${{BAZEL_TEST}}" = "1" ]; then
KLEAF_HERMETIC_BASE=${{KLEAF_HERMETIC_BASE:-{run_hermetic_base}}}
else
KLEAF_HERMETIC_BASE=${{KLEAF_HERMETIC_BASE:-{hermetic_base}}}
fi
# bin_dir for Kleaf repository, relative to execroot
# This is:
# For `bazel build`:
# - either bazel-out/k8-fastbuild/bin if @kleaf is the root module;
# - or bazel-out/k8-fastbuild/bin/external/kleaf (or some variations of it)
# if @kleaf is a dependent module
# For `bazel run`:
# - either . if @kleaf is the root module
# - or external/kleaf (or some variations of it) if @kleaf is a dependent module
if [ -n "${{BUILD_WORKSPACE_DIRECTORY}}" ] || [ "${{BAZEL_TEST}}" = "1" ]; then
KLEAF_BIN_DIR_AND_WORKSPACE_ROOT="${{KLEAF_REPO_WORKSPACE_ROOT:-.}}"
else
KLEAF_BIN_DIR_AND_WORKSPACE_ROOT="{bin_dir}${{KLEAF_REPO_WORKSPACE_ROOT:+/$KLEAF_REPO_WORKSPACE_ROOT}}"
fi
# Root of Kleaf repository (under execroot aka PWD)
# This is:
# - either $PWD if @kleaf is the root module
# - or $PWD/external/kleaf (or some variations of it) if @kleaf is a dependent module
KLEAF_REPO_DIR="$PWD${{KLEAF_REPO_WORKSPACE_ROOT:+/$KLEAF_REPO_WORKSPACE_ROOT}}"
""".format(
hermetic_base = hermetic_tools.internal_hermetic_base,
run_hermetic_base = hermetic_tools.internal_run_hermetic_base,
bin_dir = ctx.bin_dir.path,
kleaf_repo_workspace_root = kleaf_repo_workspace_root,
)
post_env = """
# Increase parallelism # TODO(b/192655643): do not use -j anymore
export MAKEFLAGS="${{MAKEFLAGS}} -j$(
make_jobs="$({get_make_jobs_cmd})"
if [[ -n "$make_jobs" ]]; then
echo "$make_jobs"
else
nproc
fi
) $(
keep_going="$({get_make_keep_going_cmd})"
if [[ "$keep_going" == "true" ]]; then
echo "--keep_going"
fi
)"
# Set up KCONFIG_EXT
if [ -n "${{KCONFIG_EXT}}" ]; then
export KCONFIG_EXT_PREFIX=$(realpath $(dirname ${{KCONFIG_EXT}}) --relative-to ${{ROOT_DIR}}/${{KERNEL_DIR}})/
fi
if [ -n "${{DTSTREE_MAKEFILE}}" ]; then
export dtstree=$(realpath -s $(dirname ${{DTSTREE_MAKEFILE}}) --relative-to ${{ROOT_DIR}}/${{KERNEL_DIR}})
fi
# Redeclare KERNEL_DIR to be under $KLEAF_REPO_WORKSPACE_ROOT.
# Only do that if all of the following is true:
# - We are setting up the variables for a kernel_filegroup with prebuilt scripts
# (KLEAF_FIX_KERNEL_DIR == 1)
# - The kernel_build() that originally built these prebuilts was declared at the
# root Bazel module in its workspace (we may relax this requirement in the future if
# there's a use case)
# A typical use case for this is that KERNEL_DIR=common in prebuilt scripts, but if @kleaf
# is a dependent module and common/ is below @kleaf, then kernel_filegroup need to fix
# the value so that KERNEL_DIR=external/kleaf~/common.
if [ "${{KLEAF_FIX_KERNEL_DIR}}" = 1 ]; then
if [ -n "{kernel_build_workspace_root}" ]; then
echo "ERROR: The original kernel_build() that built these prebuilts was " >&2
echo " {kernel_build_label}" >&2
echo " It is currently not supported to use these prebuilts within a kernel_filegroup." >&2
echo " Instead, the kernel_build() should have been built at the root Bazel module." >&2
echo " Please contact the provider for these prebuilts to resolve this error." >&2
exit 1
fi
export KERNEL_DIR=${{KLEAF_REPO_WORKSPACE_ROOT:+$KLEAF_REPO_WORKSPACE_ROOT/}}${{KERNEL_DIR}}
fi
## Set up KCPPFLAGS, KCPPFLAGS_COMPAT, and KRUSTFLAGS
# Replace ${{ROOT_DIR}} with "/proc/self/cwd" in the file name
# references in the binaries (e.g. debug info).
# "/proc/self/cwd" is an absolute path that resolves to a directory
# where debugger runs. And ${{ROOT_DIR}} layout should be the same as
# layout on the top of the repo, so if you start a debugger from the
# top directory, all paths should resolve correctly even on another
# machine.
export KCPPFLAGS="-ffile-prefix-map=${{ROOT_DIR}}=/proc/self/cwd"
export KRUSTFLAGS="--remap-path-prefix=${{ROOT_DIR}}=/proc/self/cwd"
# For Kleaf local (non-sandbox) builds, $ROOT_DIR is under execroot but
# $ROOT_DIR/$KERNEL_DIR is a symlink to the real source tree under
# workspace root, making $abs_srctree not under $ROOT_DIR.
# Because compiler puts a real path to a binary, it should be a real
# path in -ffile-prefix-map. Also we would like to leave
# ${{KERNEL_DIR}} part in the path to be able to run debugger from the
# top directory, so we go one directory up from
# ${{ROOT_DIR}}/${{KERNEL_DIR}} before calling realpath.
if [[ "$(realpath ${{ROOT_DIR}}/${{KERNEL_DIR}})" != "${{ROOT_DIR}}/${{KERNEL_DIR}}" ]]; then
export KCPPFLAGS="$KCPPFLAGS -ffile-prefix-map=$(realpath ${{ROOT_DIR}}/${{KERNEL_DIR}}/..)=/proc/self/cwd"
export KRUSTFLAGS="$KRUSTFLAGS --remap-path-prefix=$(realpath ${{ROOT_DIR}}/${{KERNEL_DIR}}/..)=/proc/self/cwd"
fi
export KCPPFLAGS_COMPAT="$KCPPFLAGS"
# Set libclang.so location for use by bindgen for Rust
LIBCLANG_PATH=$(dirname $(which clang))/../lib
export LIBCLANG_PATH
""".format(
get_make_jobs_cmd = status.get_volatile_status_cmd(ctx, "MAKE_JOBS"),
get_make_keep_going_cmd = status.get_volatile_status_cmd(ctx, "MAKE_KEEP_GOING"),
kernel_build_workspace_root = ctx.label.workspace_root,
kernel_build_label = str(ctx.label).removesuffix("_env"),
)
return struct(
pre_env = pre_env,
post_env = post_env,
)
def _get_make_verbosity_command(ctx):
command = """
# error on failures
set -e
set -o pipefail
"""
if ctx.attr._debug_annotate_scripts[BuildSettingInfo].value:
command += """
export MAKEFLAGS="${MAKEFLAGS} V=1"
"""
else:
if ctx.attr._debug_make_verbosity[BuildSettingInfo].value == "E":
command += """
# Run Make in silence mode to suppress most of the info output
export MAKEFLAGS="${MAKEFLAGS} -s"
"""
if ctx.attr._debug_make_verbosity[BuildSettingInfo].value == "D":
command += """
# Similar to --debug_annotate_scripts without additional traps.
set -x
export MAKEFLAGS="${MAKEFLAGS} V=1"
"""
if ctx.attr._debug_make_verbosity[BuildSettingInfo].value == "V":
command += """
# Similar to D but even more verbsose
set -x
export MAKEFLAGS="${MAKEFLAGS} V=2"
"""
return command
def _kernel_env_additional_attrs():
return dicts.add(
kernel_config_settings.of_kernel_env(),
kernel_toolchains_utils.attrs(),
)
kernel_env = rule(
implementation = _kernel_env_impl,
doc = """Generates a rule that generates a source-able build environment.
A build environment is defined by a single entry build config file
that can refer to further build config files.
Example:
```
kernel_env(
name = "kernel_aarch64_env,
srcs = glob(["build.config.*"]),
)
```
""",
attrs = {
"build_config": attr.label(
# Allow filegroup with 0 or 1 files.
allow_files = True,
doc = "label referring to the main build config",
),
"makefile": attr.label(doc = "Makefile below KERNEL_DIR", allow_single_file = True),
"srcs": attr.label_list(
mandatory = True,
allow_files = True,
doc = """labels that this build config refers to, including itself.
E.g. ["build.config.gki.aarch64", "build.config.gki"]""",
),
"pre_defconfig_fragments": attr.label_list(
doc = "**pre** defconfig fragments",
allow_files = True,
),
"post_defconfig_fragments": attr.label_list(
doc = "**post** defconfig fragments",
allow_files = True,
),
"setup_env": attr.label(
allow_single_file = True,
default = Label("//build/kernel:_setup_env"),
doc = "label referring to _setup_env.sh",
cfg = "exec",
),
"kconfig_ext": attr.label(
allow_single_file = True,
doc = "an external Kconfig.ext file sourced by the base kernel",
),
"dtstree": attr.label(
providers = [DtstreeInfo],
doc = "Device tree",
),
"kbuild_symtypes": attr.string(
doc = "`KBUILD_SYMTYPES`",
default = "auto",
values = ["true", "false", "auto"],
),
"make_goals": attr.string_list(doc = "`MAKE_GOALS`"),
"kcflags": attr.string_list(),
"clang_autofdo_profile": attr.label(allow_single_file = True),
"_build_utils_sh": attr.label(
allow_single_file = True,
default = Label("//build/kernel:build_utils"),
cfg = "exec",
),
"_debug_annotate_scripts": attr.label(
default = "//build/kernel/kleaf:debug_annotate_scripts",
),
"_debug_make_verbosity": attr.label(default = "//build/kernel/kleaf:debug_make_verbosity"),
"_config_is_local": attr.label(default = "//build/kernel/kleaf:config_local"),
"_config_is_stamp": attr.label(default = "//build/kernel/kleaf:config_stamp"),
"_debug_print_scripts": attr.label(default = "//build/kernel/kleaf:debug_print_scripts"),
"_kernel_use_resolved_toolchains": attr.label(
default = "//build/kernel/kleaf:incompatible_kernel_use_resolved_toolchains",
),
"_cache_dir_config_tags": attr.label(
default = "//build/kernel/kleaf/impl:cache_dir_config_tags",
executable = True,
cfg = "exec",
),
} | _kernel_env_additional_attrs(),
toolchains = [hermetic_toolchain.type],
subrules = [
set_kernel_dir,
_get_build_config_inputs,
],
)