blob: aa190b87995635d4c09b95b883cb3d5c64c3c503 [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.
"""
Common utilities for working with kernel images.
"""
load("@bazel_skylib//lib:shell.bzl", "shell")
load("@bazel_skylib//rules:common_settings.bzl", "BuildSettingInfo")
load("//build/kernel/kleaf:directory_with_structure.bzl", dws = "directory_with_structure")
load(
":common_providers.bzl",
"KernelModuleInfo",
)
load(":debug.bzl", "debug")
load(":utils.bzl", "kernel_utils", "utils")
visibility("//build/kernel/kleaf/...")
SYSTEM_DLKM_STAGING_ARCHIVE_NAME = "system_dlkm_staging_archive.tar.gz"
SYSTEM_DLKM_MODULES_LOAD_NAME = "system_dlkm.modules.load"
VENDOR_DLKM_STAGING_ARCHIVE_NAME = "vendor_dlkm_staging_archive.tar.gz"
def _build_modules_image_impl(
subrule_ctx,
kernel_modules_install,
deps,
create_modules_order,
what,
outputs,
build_command,
modules_staging_dir,
*,
_set_ext_modules,
restore_modules_install = None,
set_ext_modules = None,
implicit_outputs = None,
additional_inputs = None,
mnemonic = None):
"""Command implementation for building images that directly contain modules.
Args:
subrule_ctx: subrule_ctx.
kernel_modules_install: `kernel_modules_install`
deps: List of dependencies provided to the image building process,
create_modules_order: Whether to create and keep a modules.order file generated
by a postorder traversal of the `kernel_modules_install` sources.
what: what is being built, for logging.
outputs: list of `ctx.actions.declare_file`
build_command: the command to build `outputs` and `implicit_outputs`.
modules_staging_dir: a staging directory for module installation.
restore_modules_install: If `True`, restore `kernel_modules_install`.
Default is `True`.
set_ext_modules: If `True`, set variable `EXT_MODULES` before invoking script
in `build_utils.sh`
implicit_outputs: like `outputs`, but not installed to `DIST_DIR` (not
returned in `DefaultInfo`).
additional_inputs: Additional files to be included.
mnemonic: string to reference the build operation.
_set_ext_modules: bool_flag that specifies whether to set EXT_MODULES.
"""
if restore_modules_install == None:
restore_modules_install = True
kernel_build_infos = kernel_modules_install[KernelModuleInfo].kernel_build_infos
kernel_build_outs = depset(
transitive = [
# Prefer device kernel_build, then base kernel_build
kernel_build_infos.images_info.outs,
kernel_build_infos.images_info.base_kernel_files,
],
order = "preorder",
)
# depset.to_list() required for find_file.
# TODO(b/256688440): providers should provide System.map directly
kernel_build_outs = kernel_build_outs.to_list()
system_map = utils.find_file(
name = "System.map",
files = kernel_build_outs,
required = True,
what = "{}: outs of dependent kernel_build {}".format(subrule_ctx.label, kernel_build_infos.label),
)
modules_install_staging_dws = None
if restore_modules_install:
modules_install_staging_dws_list = kernel_modules_install[KernelModuleInfo].modules_staging_dws_depset.to_list()
if len(modules_install_staging_dws_list) != 1:
fail("{}: {} is not a `kernel_modules_install`.".format(
subrule_ctx.label,
kernel_modules_install.label,
))
modules_install_staging_dws = modules_install_staging_dws_list[0]
inputs = []
if additional_inputs != None:
inputs += additional_inputs
inputs.append(system_map)
if restore_modules_install:
inputs += dws.files(modules_install_staging_dws)
transitive_inputs = [kernel_build_infos.serialized_env_info.inputs]
transitive_inputs += [target.files for target in deps]
tools = kernel_build_infos.serialized_env_info.tools
command_outputs = []
command_outputs += outputs
if implicit_outputs != None:
command_outputs += implicit_outputs
command = kernel_utils.setup_serialized_env_cmd(
serialized_env_info = kernel_build_infos.serialized_env_info,
restore_out_dir_cmd = utils.get_check_sandbox_cmd(),
)
# Allow writing to files because create_modules_staging wants to overwrite modules.order.
if restore_modules_install:
command += dws.restore(
modules_install_staging_dws,
dst = modules_staging_dir,
options = "-aL --chmod=F+w --exclude=source --exclude=build",
)
# source/ and build/ are symlinks to the source tree and $OUT_DIR, respectively,
# so they are copied as links.
command += dws.restore(
modules_install_staging_dws,
dst = modules_staging_dir,
options = "-al --chmod=F+w --include=source --include=build --exclude='*'",
)
modules_order_cmd = ""
if create_modules_order:
modules_order_depset = kernel_modules_install[KernelModuleInfo].modules_order
modules_order_depset_list = modules_order_depset.to_list()
inputs += modules_order_depset_list
modules_order_cmd = """
cat {modules_order} > kleaf_modules.order
KLEAF_MODULES_ORDER=kleaf_modules.order
""".format(
modules_order = " ".join([modules_order.path for modules_order in modules_order_depset_list]),
)
if set_ext_modules and _set_ext_modules[BuildSettingInfo].value:
ext_modules = kernel_modules_install[KernelModuleInfo].packages.to_list()
command += """EXT_MODULES={quoted_ext_modules}""".format(
quoted_ext_modules = shell.quote(" ".join(ext_modules)),
)
if not _set_ext_modules[BuildSettingInfo].value:
# buildifier: disable=print
print("""\nWARNING: This is a temporary flag to mitigate issues on migrating away from
setting EXT_MODULES in build.config. If you need --noset_ext_modules, please
file a bug.""")
command += """
# Restore System.map to DIST_DIR for run_depmod in create_modules_staging
mkdir -p ${{DIST_DIR}}
cp {system_map} ${{DIST_DIR}}/System.map
{modules_order_cmd}
{build_command}
""".format(
system_map = system_map.path,
modules_order_cmd = modules_order_cmd,
build_command = build_command,
)
debug.print_scripts_subrule(command)
subrule_ctx.actions.run_shell(
mnemonic = mnemonic,
inputs = depset(inputs, transitive = transitive_inputs),
tools = tools,
outputs = command_outputs,
progress_message = "Building {} %{{label}}".format(what),
command = command,
)
return DefaultInfo(files = depset(outputs))
_build_modules_image = subrule(
implementation = _build_modules_image_impl,
attrs = {
"_set_ext_modules": attr.label(
default = "//build/kernel/kleaf:set_ext_modules",
),
},
subrules = [debug.print_scripts_subrule],
)
def _ramdisk_options(ramdisk_compression, ramdisk_compression_args):
"""Options for how to treat ramdisk images.
Args:
ramdisk_compression: If provided it specfies the format used for any ramdisks generated.
If not provided a fallback value from build.config is used.
Possible values are `lz4`, `gzip`, None.
ramdisk_compression_args: Command line arguments passed to lz4 command
to control compression level (defaults to `-12 --favor-decSpeed`).
For iterative kernel development where faster compression is more
desirable than a high compression ratio, it can be useful to control
the compression ratio.
"""
# Initially fallback to values from build.config.* files.
_ramdisk_compress = "${RAMDISK_COMPRESS}"
_ramdisk_decompress = "${RAMDISK_DECOMPRESS}"
_ramdisk_ext = "lz4"
if ramdisk_compression == "lz4":
_ramdisk_compress = "lz4 -c -l "
if ramdisk_compression_args:
_ramdisk_compress += ramdisk_compression_args
else:
_ramdisk_compress += "-12 --favor-decSpeed"
_ramdisk_decompress = "lz4 -c -d -l"
if ramdisk_compression == "gzip":
_ramdisk_compress = "gzip -c -f"
_ramdisk_decompress = "gzip -c -d"
_ramdisk_ext = "gz"
return struct(
ramdisk_compress = _ramdisk_compress,
ramdisk_decompress = _ramdisk_decompress,
ramdisk_ext = _ramdisk_ext,
)
image_utils = struct(
build_modules_image = _build_modules_image,
ramdisk_options = _ramdisk_options,
)