blob: a9935aa1749b57730ae2b744c5a212216c2967fb [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
Lorenz Brun6df40aa2025-05-22 15:35:44 +020026load("@rules_cc//cc:action_names.bzl", "C_COMPILE_ACTION_NAME")
27load("@rules_cc//cc:find_cc_toolchain.bzl", "CC_TOOLCHAIN_ATTRS", "find_cpp_toolchain", "use_cc_toolchain")
Serge Bazanskif055a7f2021-04-13 16:22:33 +020028load("//build/utils:detect_root.bzl", "detect_root")
Tim Windelschmidt08054ca2025-04-04 01:11:56 +020029load("//osbase/build:def.bzl", "ignore_unused_configuration")
Serge Bazanskif055a7f2021-04-13 16:22:33 +020030
Serge Bazanskif9c82492024-09-16 16:50:39 +020031def _linux_image_impl_resources(_os, _ninputs):
32 """
33 Configures linux build resources.
34
35 See `resource_set` documentation in builtins.actions Bazel docs.
36 """
Tim Windelschmidt156248b2025-01-10 00:27:45 +010037
Serge Bazanskif9c82492024-09-16 16:50:39 +020038 # 16 threads seems about right - this fits well in both our build machines and
39 # development machines.
40 cpu = 16
Tim Windelschmidt156248b2025-01-10 00:27:45 +010041
Serge Bazanskif9c82492024-09-16 16:50:39 +020042 # In MB. Picked based on observing build in htop.
43 mb_per_cpu = 256
44 return {
Tim Windelschmidt156248b2025-01-10 00:27:45 +010045 "cpu": cpu,
46 "memory": cpu * mb_per_cpu,
47 "local_test": 0,
Serge Bazanskif9c82492024-09-16 16:50:39 +020048 }
Serge Bazanskif055a7f2021-04-13 16:22:33 +020049
Lorenz Brun6df40aa2025-05-22 15:35:44 +020050DISABLED_FEATURES = []
51
52# NOTE: Multicall tool is called as path/to/llvm clang to workaround bug in out-of-process execution where tool name is repeated and parsing breaks.
53
Serge Bazanskif055a7f2021-04-13 16:22:33 +020054def _linux_image_impl(ctx):
55 kernel_config = ctx.file.kernel_config
56 kernel_src = ctx.files.kernel_src
57 image_format = ctx.attr.image_format
58
Lorenz Brun6df40aa2025-05-22 15:35:44 +020059 # Root of the given Linux sources.
60 root = detect_root(ctx.attr.kernel_src)
61
62 # Figure out target CC toolchain
63 cc_toolchain = find_cpp_toolchain(ctx)
64 feature_configuration = cc_common.configure_features(
65 ctx = ctx,
66 cc_toolchain = cc_toolchain,
67 requested_features = ctx.features,
68 unsupported_features = DISABLED_FEATURES + ctx.disabled_features,
69 )
70 c_compiler_path = cc_common.get_tool_for_action(
71 feature_configuration = feature_configuration,
72 action_name = C_COMPILE_ACTION_NAME,
73 )
74
75 # Figure out Kbuild ARCH option
76 target_arch = None
77 compressed_image_name = None
78
79 if ctx.target_platform_has_constraint(ctx.attr._constraint_x86_64[platform_common.ConstraintValueInfo]):
80 target_arch = "x86"
81 compressed_image_name = "bzImage"
82
83 if ctx.target_platform_has_constraint(ctx.attr._constraint_aarch64[platform_common.ConstraintValueInfo]):
84 target_arch = "arm64"
85 compressed_image_name = "Image"
86
87 if ctx.target_platform_has_constraint(ctx.attr._constraint_riscv64[platform_common.ConstraintValueInfo]):
88 target_arch = "riscv"
89 compressed_image_name = "Image"
90
91 if not target_arch:
92 fail("Target platform does not match expected constraints: @platforms//cpu:x86_64, @platforms//cpu:aarch64, or @platforms//cpu:riscv64.")
93
Serge Bazanskif055a7f2021-04-13 16:22:33 +020094 # Tuple containing information about how to build and access the resulting
95 # image.
96 # The first element (target) is the make target to build, the second
Mateusz Zalega9a66b182021-12-22 20:33:12 +010097 # (image_source) is the resulting file to be copied and the last
98 # (image_name) is the name of the image that will be generated by this
Serge Bazanskif055a7f2021-04-13 16:22:33 +020099 # rule.
Mateusz Zalega9a66b182021-12-22 20:33:12 +0100100 (target, image_source, image_name) = {
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100101 "vmlinux": ("vmlinux modules", "vmlinux", "vmlinux"),
Lorenz Brun6df40aa2025-05-22 15:35:44 +0200102 "Image": ("all modules", "arch/" + target_arch + "/boot/" + compressed_image_name, "Image"),
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200103 }[image_format]
104
Mateusz Zalega9a66b182021-12-22 20:33:12 +0100105 image = ctx.actions.declare_file(image_name)
106 modinfo = ctx.actions.declare_file("modules.builtin.modinfo")
Lorenz Brun6c454342023-06-01 12:23:38 +0200107 modules = ctx.actions.declare_directory("modules")
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200108 ctx.actions.run_shell(
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100109 outputs = [image, modinfo, modules],
Lorenz Brun6df40aa2025-05-22 15:35:44 +0200110 inputs = depset([kernel_config] + kernel_src, transitive = [cc_toolchain.all_files]),
Serge Bazanskif9c82492024-09-16 16:50:39 +0200111 resource_set = _linux_image_impl_resources,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200112 command = '''
113 kconfig=$1
114 target=$2
Mateusz Zalega9a66b182021-12-22 20:33:12 +0100115 image_source=$3
116 image=$4
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200117 root=$5
Mateusz Zalega9a66b182021-12-22 20:33:12 +0100118 modinfo=$6
Lorenz Brun6c454342023-06-01 12:23:38 +0200119 modules=$7
Lorenz Brun6df40aa2025-05-22 15:35:44 +0200120 arch=$8
121 cc=$PWD/$9
Lorenz Brun6c454342023-06-01 12:23:38 +0200122
123 builddir=$(mktemp -d)
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200124
125 mkdir ${root}/.bin
Lorenz Brun6c454342023-06-01 12:23:38 +0200126 cp ${kconfig} ${builddir}/.config
Lorenz Brun6df40aa2025-05-22 15:35:44 +0200127 (cd ${root} && make -j 16 KBUILD_OUTPUT="${builddir}" ARCH="${arch}" CC="${cc//clang/llvm} clang" LD="${cc//clang/ld.lld}" OBJCOPY="${cc//clang/llvm-objcopy}" OBJDUMP="${cc//clang/llvm-objdump}" AR="${cc//clang/llvm-ar}" NM="${cc//clang/llvm-nm}" STRIP="${cc//clang/llvm-strip}" READELF="${cc//clang/llvm-readelf}" olddefconfig ${target} >/dev/null)
Lorenz Brun6c454342023-06-01 12:23:38 +0200128 cp "${builddir}"/${image_source} ${image}
129 cp "${builddir}"/modules.builtin.modinfo ${modinfo}
130 # Not using modules_install as it tries to run depmod and friends
131 for f in $(find "${builddir}" -name '*.ko' -type f -printf "%P\n" ); do
132 install -D "${builddir}/$f" "${modules}/$f"
133 done
134 rm -Rf "$builddir"
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200135 ''',
136 arguments = [
137 kernel_config.path,
138 target,
Mateusz Zalega9a66b182021-12-22 20:33:12 +0100139 image_source,
140 image.path,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200141 root,
Lorenz Brun6c454342023-06-01 12:23:38 +0200142 modinfo.path,
143 modules.path,
Lorenz Brun6df40aa2025-05-22 15:35:44 +0200144 target_arch,
145 c_compiler_path,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200146 ],
147 use_default_shell_env = True,
148 )
149
Mateusz Zalega9a66b182021-12-22 20:33:12 +0100150 return [
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100151 DefaultInfo(
152 files = depset([image]),
153 runfiles = ctx.runfiles(files = [image]),
154 ),
155 OutputGroupInfo(
156 modinfo = depset([modinfo]),
157 modules = depset([modules]),
158 ),
Mateusz Zalega9a66b182021-12-22 20:33:12 +0100159 ]
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200160
161linux_image = rule(
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100162 doc = """
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200163 Build Linux kernel image unhermetically in a given format.
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100164 """,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200165 implementation = _linux_image_impl,
166 cfg = ignore_unused_configuration,
167 attrs = {
168 "kernel_config": attr.label(
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100169 doc = """
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200170 Linux kernel configuration file to build this kernel image with.
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100171 """,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200172 allow_single_file = True,
173 default = ":linux-metropolis.config",
174 ),
175 "kernel_src": attr.label(
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100176 doc = """
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200177 Filegroup containing Linux kernel sources.
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100178 """,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200179 default = "@linux//:all",
180 ),
181 "image_format": attr.string(
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100182 doc = """
Lorenz Brun6df40aa2025-05-22 15:35:44 +0200183 Format of generated Linux image, one of 'vmlinux' or 'Image',
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100184 """,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200185 values = [
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100186 "vmlinux",
Lorenz Brun6df40aa2025-05-22 15:35:44 +0200187 "Image",
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200188 ],
Lorenz Brun6df40aa2025-05-22 15:35:44 +0200189 default = "Image",
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200190 ),
191 "_allowlist_function_transition": attr.label(
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100192 default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200193 ),
Lorenz Brun6df40aa2025-05-22 15:35:44 +0200194 # Bazel doesn't let you access the target platform directly, use these
195 "_constraint_x86_64": attr.label(
196 default = "@platforms//cpu:x86_64",
197 ),
198 "_constraint_aarch64": attr.label(
199 default = "@platforms//cpu:aarch64",
200 ),
201 "_constraint_riscv64": attr.label(
202 default = "@platforms//cpu:riscv64",
203 ),
204 } | CC_TOOLCHAIN_ATTRS,
205 toolchains = use_cc_toolchain(),
206 fragments = ["cpp"],
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200207)