blob: 4c6798c6f9d8f65de873434d6d2587e8b95a1aec [file] [log] [blame]
Serge Bazanskif055a7f2021-04-13 16:22:33 +02001# Copyright 2020 The Monogon Project Authors.
2#
3# SPDX-License-Identifier: Apache-2.0
4#
5# Licensed under the Apache License, Version 2.0 (the "License");
6# you may not use this file except in compliance with the License.
7# You may obtain a copy of the License at
8#
9# http://www.apache.org/licenses/LICENSE-2.0
10#
11# Unless required by applicable law or agreed to in writing, software
12# distributed under the License is distributed on an "AS IS" BASIS,
13# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17"""
18Rules for building Linux kernel images.
19
20This currently performs the build in a fully unhermetic manner, using
Leopoldbc93c2b2023-01-14 13:12:23 +010021make/gcc/... from the sandbox sysroot, and is only slightly better than a genrule. This
Serge Bazanskif055a7f2021-04-13 16:22:33 +020022should be replaced by a hermetic build that at least uses rules_cc toolchain
23information, or even better, just uses cc_library targets.
24"""
25
26load("//build/utils:detect_root.bzl", "detect_root")
27
Serge Bazanski5b13d812023-06-20 13:22:23 +020028_new_settings = {
29 # This list should be expanded with any configuration options that end
30 # up reaching this rule with different values across different build
31 # graph paths, but that do not actually influence the kernel build.
32 # Force-setting them to a stable value forces the build configuration
33 # to a stable hash.
34 # See the transition's comment block for more information.
Tim Windelschmidt117006e2024-12-09 22:53:52 +010035 "@io_bazel_rules_go//go/config:pure": False,
36 "@io_bazel_rules_go//go/config:static": False,
Serge Bazanski5b13d812023-06-20 13:22:23 +020037
Serge Bazanski5b13d812023-06-20 13:22:23 +020038 # Note: this toolchain is not actually used to perform the build.
39 "//command_line_option:platforms": "//build/platforms:linux_amd64_static",
40}
41
Tim Windelschmidt156248b2025-01-10 00:27:45 +010042def _ignore_unused_configuration_impl(_settings, _attr):
Serge Bazanski5b13d812023-06-20 13:22:23 +020043 return _new_settings
Serge Bazanskif055a7f2021-04-13 16:22:33 +020044
45# Transition to flip all known-unimportant but varying configuration options to
46# a known, stable value.
47# This is to prevent Bazel from creating extra configurations for possible
48# combinations of options in case the linux_image rule is pulled through build
49# graph fragments that have different options set.
50#
51# Ideally, Bazel would let us mark in a list that we only care about some set
52# of options (or at least let us mark those that we explicitly don't care
53# about, instead of manually setting them to some value). However, this doesn't
54# seem to be possible, thus this transition is a bit of a hack.
55ignore_unused_configuration = transition(
56 implementation = _ignore_unused_configuration_impl,
57 inputs = [],
Serge Bazanski5b13d812023-06-20 13:22:23 +020058 outputs = list(_new_settings.keys()),
Serge Bazanskif055a7f2021-04-13 16:22:33 +020059)
60
Serge Bazanskif9c82492024-09-16 16:50:39 +020061def _linux_image_impl_resources(_os, _ninputs):
62 """
63 Configures linux build resources.
64
65 See `resource_set` documentation in builtins.actions Bazel docs.
66 """
Tim Windelschmidt156248b2025-01-10 00:27:45 +010067
Serge Bazanskif9c82492024-09-16 16:50:39 +020068 # 16 threads seems about right - this fits well in both our build machines and
69 # development machines.
70 cpu = 16
Tim Windelschmidt156248b2025-01-10 00:27:45 +010071
Serge Bazanskif9c82492024-09-16 16:50:39 +020072 # In MB. Picked based on observing build in htop.
73 mb_per_cpu = 256
74 return {
Tim Windelschmidt156248b2025-01-10 00:27:45 +010075 "cpu": cpu,
76 "memory": cpu * mb_per_cpu,
77 "local_test": 0,
Serge Bazanskif9c82492024-09-16 16:50:39 +020078 }
Serge Bazanskif055a7f2021-04-13 16:22:33 +020079
80def _linux_image_impl(ctx):
81 kernel_config = ctx.file.kernel_config
82 kernel_src = ctx.files.kernel_src
83 image_format = ctx.attr.image_format
84
85 # Tuple containing information about how to build and access the resulting
86 # image.
87 # The first element (target) is the make target to build, the second
Mateusz Zalega9a66b182021-12-22 20:33:12 +010088 # (image_source) is the resulting file to be copied and the last
89 # (image_name) is the name of the image that will be generated by this
Serge Bazanskif055a7f2021-04-13 16:22:33 +020090 # rule.
Mateusz Zalega9a66b182021-12-22 20:33:12 +010091 (target, image_source, image_name) = {
Tim Windelschmidt156248b2025-01-10 00:27:45 +010092 "vmlinux": ("vmlinux modules", "vmlinux", "vmlinux"),
93 "bzImage": ("all modules", "arch/x86/boot/bzImage", "bzImage"),
Serge Bazanskif055a7f2021-04-13 16:22:33 +020094 }[image_format]
95
96 # Root of the given Linux sources.
97 root = detect_root(ctx.attr.kernel_src)
98
Mateusz Zalega9a66b182021-12-22 20:33:12 +010099 image = ctx.actions.declare_file(image_name)
100 modinfo = ctx.actions.declare_file("modules.builtin.modinfo")
Lorenz Brun6c454342023-06-01 12:23:38 +0200101 modules = ctx.actions.declare_directory("modules")
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200102 ctx.actions.run_shell(
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100103 outputs = [image, modinfo, modules],
104 inputs = [kernel_config] + kernel_src,
Serge Bazanskif9c82492024-09-16 16:50:39 +0200105 resource_set = _linux_image_impl_resources,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200106 command = '''
107 kconfig=$1
108 target=$2
Mateusz Zalega9a66b182021-12-22 20:33:12 +0100109 image_source=$3
110 image=$4
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200111 root=$5
Mateusz Zalega9a66b182021-12-22 20:33:12 +0100112 modinfo=$6
Lorenz Brun6c454342023-06-01 12:23:38 +0200113 modules=$7
114
115 builddir=$(mktemp -d)
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200116
117 mkdir ${root}/.bin
Lorenz Brun6c454342023-06-01 12:23:38 +0200118 cp ${kconfig} ${builddir}/.config
Serge Bazanskif9c82492024-09-16 16:50:39 +0200119 (cd ${root} && KBUILD_OUTPUT="${builddir}" make -j 16 ${target} >/dev/null)
Lorenz Brun6c454342023-06-01 12:23:38 +0200120 cp "${builddir}"/${image_source} ${image}
121 cp "${builddir}"/modules.builtin.modinfo ${modinfo}
122 # Not using modules_install as it tries to run depmod and friends
123 for f in $(find "${builddir}" -name '*.ko' -type f -printf "%P\n" ); do
124 install -D "${builddir}/$f" "${modules}/$f"
125 done
126 rm -Rf "$builddir"
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200127 ''',
128 arguments = [
129 kernel_config.path,
130 target,
Mateusz Zalega9a66b182021-12-22 20:33:12 +0100131 image_source,
132 image.path,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200133 root,
Lorenz Brun6c454342023-06-01 12:23:38 +0200134 modinfo.path,
135 modules.path,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200136 ],
137 use_default_shell_env = True,
138 )
139
Mateusz Zalega9a66b182021-12-22 20:33:12 +0100140 return [
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100141 DefaultInfo(
142 files = depset([image]),
143 runfiles = ctx.runfiles(files = [image]),
144 ),
145 OutputGroupInfo(
146 modinfo = depset([modinfo]),
147 modules = depset([modules]),
148 ),
Mateusz Zalega9a66b182021-12-22 20:33:12 +0100149 ]
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200150
151linux_image = rule(
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100152 doc = """
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200153 Build Linux kernel image unhermetically in a given format.
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100154 """,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200155 implementation = _linux_image_impl,
156 cfg = ignore_unused_configuration,
157 attrs = {
158 "kernel_config": attr.label(
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100159 doc = """
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200160 Linux kernel configuration file to build this kernel image with.
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100161 """,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200162 allow_single_file = True,
163 default = ":linux-metropolis.config",
164 ),
165 "kernel_src": attr.label(
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100166 doc = """
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200167 Filegroup containing Linux kernel sources.
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100168 """,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200169 default = "@linux//:all",
170 ),
171 "image_format": attr.string(
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100172 doc = """
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200173 Format of generated Linux image, one of 'vmlinux' or 'bzImage',
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100174 """,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200175 values = [
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100176 "vmlinux",
177 "bzImage",
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200178 ],
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100179 default = "bzImage",
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200180 ),
181 "_allowlist_function_transition": attr.label(
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100182 default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200183 ),
184 },
185)