| # 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", |
| "KernelBuildInfo", |
| "KernelEnvAndOutputsInfo", |
| "KernelModuleInfo", |
| ) |
| load(":debug.bzl", "debug") |
| load(":utils.bzl", "utils") |
| |
| SYSTEM_DLKM_STAGING_ARCHIVE_NAME = "system_dlkm_staging_archive.tar.gz" |
| SYSTEM_DLKM_MODULES_LOAD_NAME = "system_dlkm.modules.load" |
| |
| def _build_modules_image_impl_common( |
| ctx, |
| what, |
| outputs, |
| build_command, |
| modules_staging_dir, |
| 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: |
| ctx: ctx. |
| 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 `ctx.attr.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. |
| """ |
| |
| if restore_modules_install == None: |
| restore_modules_install = True |
| |
| kernel_build = ctx.attr.kernel_modules_install[KernelModuleInfo].kernel_build |
| kernel_build_outs = kernel_build[KernelBuildInfo].outs + kernel_build[KernelBuildInfo].base_kernel_files.to_list() |
| system_map = utils.find_file( |
| name = "System.map", |
| files = kernel_build_outs, |
| required = True, |
| what = "{}: outs of dependent kernel_build {}".format(ctx.label, kernel_build), |
| ) |
| |
| modules_install_staging_dws = None |
| if restore_modules_install: |
| modules_install_staging_dws_list = ctx.attr.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( |
| ctx.label, |
| ctx.attr.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) |
| inputs += ctx.files.deps |
| transitive_inputs = [kernel_build[KernelEnvAndOutputsInfo].inputs] |
| tools = kernel_build[KernelEnvAndOutputsInfo].tools |
| |
| command_outputs = [] |
| command_outputs += outputs |
| if implicit_outputs != None: |
| command_outputs += implicit_outputs |
| |
| command = kernel_build[KernelEnvAndOutputsInfo].get_setup_script( |
| data = kernel_build[KernelEnvAndOutputsInfo].data, |
| restore_out_dir_cmd = utils.get_check_sandbox_cmd(), |
| ) |
| |
| for attr_name in ( |
| "modules_list", |
| "modules_blocklist", |
| "vendor_dlkm_fs_type", |
| "vendor_dlkm_modules_list", |
| "vendor_dlkm_modules_blocklist", |
| "vendor_dlkm_props", |
| "system_dlkm_fs_type", |
| "system_dlkm_modules_list", |
| "system_dlkm_modules_blocklist", |
| "system_dlkm_props", |
| ): |
| # Checks if attr_name is a valid attribute name in the current rule. |
| # If not, do not touch its value. |
| if not hasattr(ctx.file, attr_name): |
| continue |
| |
| # If it is a valid attribute name, set environment variable to the path if the argument is |
| # supplied, otherwise set environment variable to empty. |
| file = getattr(ctx.file, attr_name) |
| path = "" |
| if file != None: |
| path = file.path |
| inputs.append(file) |
| command += """ |
| {name}={path} |
| """.format( |
| name = attr_name.upper(), |
| path = path, |
| ) |
| |
| # 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='*'", |
| ) |
| |
| if set_ext_modules and ctx.attr._set_ext_modules[BuildSettingInfo].value: |
| ext_modules = ctx.attr.kernel_modules_install[KernelModuleInfo].packages.to_list() |
| command += """EXT_MODULES={quoted_ext_modules}""".format( |
| quoted_ext_modules = shell.quote(" ".join(ext_modules)), |
| ) |
| |
| if not ctx.attr._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 |
| |
| {build_command} |
| """.format( |
| system_map = system_map.path, |
| build_command = build_command, |
| ) |
| |
| debug.print_scripts(ctx, command) |
| ctx.actions.run_shell( |
| mnemonic = mnemonic, |
| inputs = depset(inputs, transitive = transitive_inputs), |
| tools = tools, |
| outputs = command_outputs, |
| progress_message = "Building {} {}".format(what, ctx.label), |
| command = command, |
| ) |
| return DefaultInfo(files = depset(outputs)) |
| |
| def _build_modules_image_attrs_common(additional = None): |
| """Common attrs for rules that builds images that directly contain modules.""" |
| ret = { |
| "kernel_modules_install": attr.label( |
| mandatory = True, |
| providers = [KernelModuleInfo], |
| ), |
| "deps": attr.label_list( |
| allow_files = True, |
| ), |
| "_debug_print_scripts": attr.label( |
| default = "//build/kernel/kleaf:debug_print_scripts", |
| ), |
| "_set_ext_modules": attr.label( |
| default = "//build/kernel/kleaf:set_ext_modules", |
| ), |
| } |
| if additional != None: |
| ret.update(additional) |
| return ret |
| |
| 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_impl_common = _build_modules_image_impl_common, |
| build_modules_image_attrs_common = _build_modules_image_attrs_common, |
| ramdisk_options = _ramdisk_options, |
| ) |