| # 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 sandbox sysroot, 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:platforms": "//build/platforms:linux_amd64_static", |
| } |
| |
| # 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:platforms", |
| ], |
| ) |
| |
| |
| 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" |
| ), |
| }, |
| ) |