|  | #  Copyright 2020 The Monogon Project Authors. | 
|  | # | 
|  | #  SPDX-License-Identifier: Apache-2.0 | 
|  | # | 
|  | #  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. | 
|  |  | 
|  | """ | 
|  | Rules for building Linux kernel images. | 
|  |  | 
|  | This currently performs the build in a fully unhermetic manner, using | 
|  | make/gcc/... from the host, and is only slightly better than a genrule. This | 
|  | should be replaced by a hermetic build that at least uses rules_cc toolchain | 
|  | information, or even better, just uses cc_library targets. | 
|  | """ | 
|  |  | 
|  | load("//build/utils:detect_root.bzl", "detect_root") | 
|  |  | 
|  |  | 
|  | def _ignore_unused_configuration_impl(settings, attr): | 
|  | return { | 
|  | # This list should be expanded with any configuration options that end | 
|  | # up reaching this rule with different values across different build | 
|  | # graph paths, but that do not actually influence the kernel build. | 
|  | # Force-setting them to a stable value forces the build configuration | 
|  | # to a stable hash. | 
|  | # See the transition's comment block for more information. | 
|  | "@io_bazel_rules_go//go/config:pure": True, | 
|  | "@io_bazel_rules_go//go/config:static": True, | 
|  | # Note: this toolchain is not actually used to perform the build. | 
|  | "//command_line_option:crosstool_top": "//build/toolchain/musl-host-gcc:musl_host_cc_suite", | 
|  | } | 
|  |  | 
|  | # Transition to flip all known-unimportant but varying configuration options to | 
|  | # a known, stable value. | 
|  | # This is to prevent Bazel from creating extra configurations for possible | 
|  | # combinations of options in case the linux_image rule is pulled through build | 
|  | # graph fragments that have different options set. | 
|  | # | 
|  | # Ideally, Bazel would let us mark in a list that we only care about some set | 
|  | # of options (or at least let us mark those that we explicitly don't care | 
|  | # about, instead of manually setting them to some value). However, this doesn't | 
|  | # seem to be possible, thus this transition is a bit of a hack. | 
|  | ignore_unused_configuration = transition( | 
|  | implementation = _ignore_unused_configuration_impl, | 
|  | inputs = [], | 
|  | outputs = [ | 
|  | "@io_bazel_rules_go//go/config:pure", | 
|  | "@io_bazel_rules_go//go/config:static", | 
|  | "//command_line_option:crosstool_top", | 
|  | ], | 
|  | ) | 
|  |  | 
|  |  | 
|  | def _linux_image_impl(ctx): | 
|  | kernel_config = ctx.file.kernel_config | 
|  | kernel_src = ctx.files.kernel_src | 
|  | image_format = ctx.attr.image_format | 
|  |  | 
|  | # Tuple containing information about how to build and access the resulting | 
|  | # image. | 
|  | # The first element (target) is the make target to build, the second | 
|  | # (image_source) is the resulting file to be copied and the last | 
|  | # (image_name) is the name of the image that will be generated by this | 
|  | # rule. | 
|  | (target, image_source, image_name) = { | 
|  | 'vmlinux': ('vmlinux', 'vmlinux', 'vmlinux'), | 
|  | 'bzImage': ('all', 'arch/x86/boot/bzImage', 'bzImage'), | 
|  | }[image_format] | 
|  |  | 
|  | # Root of the given Linux sources. | 
|  | root = detect_root(ctx.attr.kernel_src) | 
|  |  | 
|  | image = ctx.actions.declare_file(image_name) | 
|  | modinfo = ctx.actions.declare_file("modules.builtin.modinfo") | 
|  | ctx.actions.run_shell( | 
|  | outputs = [ image, modinfo ], | 
|  | inputs = [ kernel_config ] + kernel_src, | 
|  | command = ''' | 
|  | kconfig=$1 | 
|  | target=$2 | 
|  | image_source=$3 | 
|  | image=$4 | 
|  | root=$5 | 
|  | modinfo=$6 | 
|  |  | 
|  | mkdir ${root}/.bin | 
|  | cp ${kconfig} ${root}/.config | 
|  | (cd ${root} && make -j $(nproc) ${target} >/dev/null) | 
|  | cp ${root}/${image_source} ${image} | 
|  | cp ${root}/modules.builtin.modinfo ${modinfo} | 
|  | ''', | 
|  | arguments = [ | 
|  | kernel_config.path, | 
|  | target, | 
|  | image_source, | 
|  | image.path, | 
|  | root, | 
|  | modinfo.path | 
|  | ], | 
|  | use_default_shell_env = True, | 
|  | ) | 
|  |  | 
|  | return [ | 
|  | DefaultInfo( | 
|  | files=depset([image]), | 
|  | runfiles=ctx.runfiles(files=[image]) | 
|  | ), | 
|  | OutputGroupInfo( | 
|  | modinfo = depset([modinfo]) | 
|  | ) | 
|  | ] | 
|  |  | 
|  | linux_image = rule( | 
|  | doc = ''' | 
|  | Build Linux kernel image unhermetically in a given format. | 
|  | ''', | 
|  | implementation = _linux_image_impl, | 
|  | cfg = ignore_unused_configuration, | 
|  | attrs = { | 
|  | "kernel_config": attr.label( | 
|  | doc = ''' | 
|  | Linux kernel configuration file to build this kernel image with. | 
|  | ''', | 
|  | allow_single_file = True, | 
|  | default = ":linux-metropolis.config", | 
|  | ), | 
|  | "kernel_src": attr.label( | 
|  | doc = ''' | 
|  | Filegroup containing Linux kernel sources. | 
|  | ''', | 
|  | default = "@linux//:all", | 
|  | ), | 
|  | "image_format": attr.string( | 
|  | doc = ''' | 
|  | Format of generated Linux image, one of 'vmlinux' or 'bzImage', | 
|  | ''', | 
|  | values = [ | 
|  | 'vmlinux', 'bzImage', | 
|  | ], | 
|  | default = 'bzImage', | 
|  | ), | 
|  | "_allowlist_function_transition": attr.label( | 
|  | default = "@bazel_tools//tools/allowlists/function_transition_allowlist" | 
|  | ), | 
|  | }, | 
|  | ) |