blob: 5e320bdc7baf289f56c63798fd60d9506675ec9d [file] [log] [blame]
Tim Windelschmidt6cca9322025-04-15 21:13:32 +02001# Copyright The Monogon Project Authors.
2# SPDX-License-Identifier: Apache-2.0
Serge Bazanskif055a7f2021-04-13 16:22:33 +02003
4"""
5Rules for building Linux kernel images.
6
Tim Windelschmidt6cca9322025-04-15 21:13:32 +02007This currently performs the build in a fully hermetic manner, using
8make/gcc/... from the toolchain bundle, and is only slightly better than a genrule. This
9should be replaced by a hermetic build that just uses cc_library targets.
Serge Bazanskif055a7f2021-04-13 16:22:33 +020010"""
11
Lorenz Brun6df40aa2025-05-22 15:35:44 +020012load("@rules_cc//cc:find_cc_toolchain.bzl", "CC_TOOLCHAIN_ATTRS", "find_cpp_toolchain", "use_cc_toolchain")
Tim Windelschmidtd4817492025-06-16 15:03:12 +020013load("@rules_cc//cc/common:cc_common.bzl", "cc_common")
Tim Windelschmidt6cca9322025-04-15 21:13:32 +020014load("@rules_cc//cc/common:cc_info.bzl", "CcInfo")
15load("//build/utils:detect_root.bzl", "detect_root", "detect_roots")
16load("//build/utils:foreign_build.bzl", "generate_foreign_build_env", "merge_env")
17load("//build/utils:target_info.bzl", "TargetInfo")
Tim Windelschmidt08054ca2025-04-04 01:11:56 +020018load("//osbase/build:def.bzl", "ignore_unused_configuration")
Serge Bazanskif055a7f2021-04-13 16:22:33 +020019
Serge Bazanskif9c82492024-09-16 16:50:39 +020020def _linux_image_impl_resources(_os, _ninputs):
21 """
22 Configures linux build resources.
23
24 See `resource_set` documentation in builtins.actions Bazel docs.
25 """
Tim Windelschmidt156248b2025-01-10 00:27:45 +010026
Serge Bazanskif9c82492024-09-16 16:50:39 +020027 # 16 threads seems about right - this fits well in both our build machines and
28 # development machines.
29 cpu = 16
Tim Windelschmidt156248b2025-01-10 00:27:45 +010030
Serge Bazanskif9c82492024-09-16 16:50:39 +020031 # In MB. Picked based on observing build in htop.
32 mb_per_cpu = 256
33 return {
Tim Windelschmidt156248b2025-01-10 00:27:45 +010034 "cpu": cpu,
35 "memory": cpu * mb_per_cpu,
36 "local_test": 0,
Serge Bazanskif9c82492024-09-16 16:50:39 +020037 }
Serge Bazanskif055a7f2021-04-13 16:22:33 +020038
Tim Windelschmidt6cca9322025-04-15 21:13:32 +020039TOOLCHAINS = [
40 "//build/toolchain/toolchain-bundle:make_toolchain",
41 "//build/toolchain/toolchain-bundle:flex_toolchain",
42 "//build/toolchain/toolchain-bundle:bison_toolchain",
43 "//build/toolchain/toolchain-bundle:m4_toolchain",
44 "//build/toolchain/toolchain-bundle:busybox_toolchain",
45 "//build/toolchain/toolchain-bundle:bc_toolchain",
46 "//build/toolchain/toolchain-bundle:diff_toolchain",
47 "//build/toolchain/toolchain-bundle:perl_toolchain",
48 "//build/toolchain/toolchain-bundle:lz4_toolchain",
49]
Lorenz Brun6df40aa2025-05-22 15:35:44 +020050
Serge Bazanskif055a7f2021-04-13 16:22:33 +020051def _linux_image_impl(ctx):
Serge Bazanskif055a7f2021-04-13 16:22:33 +020052 # Tuple containing information about how to build and access the resulting
53 # image.
54 # The first element (target) is the make target to build, the second
Mateusz Zalega9a66b182021-12-22 20:33:12 +010055 # (image_source) is the resulting file to be copied and the last
56 # (image_name) is the name of the image that will be generated by this
Serge Bazanskif055a7f2021-04-13 16:22:33 +020057 # rule.
Mateusz Zalega9a66b182021-12-22 20:33:12 +010058 (target, image_source, image_name) = {
Tim Windelschmidt156248b2025-01-10 00:27:45 +010059 "vmlinux": ("vmlinux modules", "vmlinux", "vmlinux"),
Tim Windelschmidt6cca9322025-04-15 21:13:32 +020060 "Image": ("all modules", "arch/" + ctx.attr._target_arch[TargetInfo].value + "/boot/" + ctx.attr._image_name[TargetInfo].value, "Image"),
61 }[ctx.attr.image_format]
62
63 ssl_src, ssl_gen = detect_roots(ctx.attr._ssl[CcInfo].compilation_context.direct_public_headers)
64 crypto_src, crypto_gen = detect_roots(ctx.attr._crypto[CcInfo].compilation_context.direct_public_headers)
65 extra_env = {
66 "HOSTLDFLAGS": " -L ".join(
67 [
68 "", # First element empty, for force a the join prefix
69 detect_root(ctx.attr._zstd.files.to_list()).rsplit("/", 1)[0],
70 detect_root(ctx.attr._zlib.files.to_list()).rsplit("/", 1)[0],
71 detect_root(ctx.attr._libelf.files.to_list()).rsplit("/", 1)[0],
72 detect_root(ctx.attr._ssl.files.to_list()).rsplit("/", 1)[0],
73 detect_root(ctx.attr._crypto.files.to_list()).rsplit("/", 1)[0],
74 ],
75 ),
76 "HOSTCFLAGS": " -I ".join(
77 [
78 "", # First element empty, for force a the join prefix
79 detect_root(ctx.attr._libelf[CcInfo].compilation_context.direct_public_headers),
80 ssl_src + "/../",
81 ssl_gen + "/../include/",
82 crypto_src + "/../",
83 crypto_gen + "/../include/",
84 ],
85 ),
86 }
87
88 inputs = depset(
89 ctx.files.kernel_config +
90 ctx.files.kernel_src +
91 ctx.files._libelf +
92 ctx.attr._libelf[CcInfo].compilation_context.direct_public_headers +
93 ctx.files._zlib +
94 ctx.files._ssl +
95 ctx.attr._ssl[CcInfo].compilation_context.direct_public_headers +
96 ctx.files._crypto +
97 ctx.attr._crypto[CcInfo].compilation_context.direct_public_headers,
98 )
99
100 # Setup the environment for the foreign build.
101 toolchain_env, toolchain_inputs, toolchain_cmd = generate_foreign_build_env(
102 ctx = ctx,
103 target_toolchain = find_cpp_toolchain(ctx),
104 exec_toolchain = ctx.attr._exec_toolchain[cc_common.CcToolchainInfo],
105 toolchain_bundle_tools = TOOLCHAINS,
106 )
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200107
Mateusz Zalega9a66b182021-12-22 20:33:12 +0100108 image = ctx.actions.declare_file(image_name)
109 modinfo = ctx.actions.declare_file("modules.builtin.modinfo")
Lorenz Brun6c454342023-06-01 12:23:38 +0200110 modules = ctx.actions.declare_directory("modules")
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200111 ctx.actions.run_shell(
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100112 outputs = [image, modinfo, modules],
Tim Windelschmidt6cca9322025-04-15 21:13:32 +0200113 inputs = depset(transitive = [inputs, toolchain_inputs]),
Serge Bazanskif9c82492024-09-16 16:50:39 +0200114 resource_set = _linux_image_impl_resources,
Tim Windelschmidt6cca9322025-04-15 21:13:32 +0200115 env = merge_env(toolchain_env, extra_env),
116 progress_message = "Building Linux Kernel: {}".format(ctx.label.name),
117 mnemonic = "BuildLinux",
118 command = toolchain_cmd + """
119 export BISON_PKGDATADIR=$(realpath $(dirname $BISON))/../share/bison
Lorenz Brun6c454342023-06-01 12:23:38 +0200120 builddir=$(mktemp -d)
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200121
Tim Windelschmidt6cca9322025-04-15 21:13:32 +0200122 mkdir {kernel_src}/.bin
123 cp {kconfig} $builddir/.config
124 (
125 cd {kernel_src} &&
126 make -j 16 \
127 \
128 CC="$CC" CXX="$CXX" LD="$LD" AR="$AR" NM="$NM" STRIP="$STRIP" \
129 OBJCOPY="$OBJCOPY" OBJDUMP="$OBJDUMP" READELF="$READELF" \
130 CFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS" \
131 \
132 HOSTCC="$HOSTCC" HOSTCXX="$HOSTCXX" HOSTLD="$HOSTLD" \
133 HOSTAR="$HOSTAR" HOSTNM="$HOSTNM" HOSTSTRIP="$HOSTSTRIP" \
134 HOSTOBJCOPY="$HOSTOBJCOPY" HOSTOBJDUMP="$HOSTOBJDUMP" \
135 HOSTREADELF="$HOSTREADELF" HOSTCFLAGS="$HOSTCFLAGS" \
136 HOSTLDFLAGS="$HOSTLDFLAGS" \
137 \
138 KBUILD_OUTPUT="$builddir" \
139 ARCH="{target_arch}" \
140 olddefconfig {target}
141 ) > /dev/null
142
143 cp "$builddir"/{image_source} {image}
144 cp "$builddir"/modules.builtin.modinfo {modinfo}
Lorenz Brun6c454342023-06-01 12:23:38 +0200145 # Not using modules_install as it tries to run depmod and friends
Tim Windelschmidt6cca9322025-04-15 21:13:32 +0200146 for f in $(find "$builddir" -name '*.ko' -type f -printf "%P\n" ); do
147 install -D "$builddir/$f" "{modules}/$f"
Lorenz Brun6c454342023-06-01 12:23:38 +0200148 done
149 rm -Rf "$builddir"
Tim Windelschmidt6cca9322025-04-15 21:13:32 +0200150 """.format(
151 kconfig = ctx.file.kernel_config.path,
152 target = target,
153 image_source = image_source,
154 kernel_src = detect_root(ctx.attr.kernel_src.files.to_list()),
155 image = image.path,
156 modinfo = modinfo.path,
157 modules = modules.path,
158 target_arch = ctx.attr._target_arch[TargetInfo].value,
159 ),
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200160 use_default_shell_env = True,
161 )
162
Mateusz Zalega9a66b182021-12-22 20:33:12 +0100163 return [
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100164 DefaultInfo(
165 files = depset([image]),
166 runfiles = ctx.runfiles(files = [image]),
167 ),
168 OutputGroupInfo(
169 modinfo = depset([modinfo]),
170 modules = depset([modules]),
171 ),
Mateusz Zalega9a66b182021-12-22 20:33:12 +0100172 ]
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200173
174linux_image = rule(
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100175 doc = """
Tim Windelschmidt6cca9322025-04-15 21:13:32 +0200176 Build Linux kernel image hermetically in a given format.
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100177 """,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200178 implementation = _linux_image_impl,
179 cfg = ignore_unused_configuration,
180 attrs = {
181 "kernel_config": attr.label(
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100182 doc = """
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200183 Linux kernel configuration file to build this kernel image with.
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100184 """,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200185 allow_single_file = True,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200186 ),
187 "kernel_src": attr.label(
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100188 doc = """
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200189 Filegroup containing Linux kernel sources.
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100190 """,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200191 ),
192 "image_format": attr.string(
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100193 doc = """
Lorenz Brun6df40aa2025-05-22 15:35:44 +0200194 Format of generated Linux image, one of 'vmlinux' or 'Image',
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100195 """,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200196 values = [
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100197 "vmlinux",
Lorenz Brun6df40aa2025-05-22 15:35:44 +0200198 "Image",
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200199 ],
Lorenz Brun6df40aa2025-05-22 15:35:44 +0200200 default = "Image",
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200201 ),
Tim Windelschmidt6cca9322025-04-15 21:13:32 +0200202 "_libelf": attr.label(
203 default = "//third_party:libelf_elf",
204 cfg = "exec",
205 ),
206 "_zstd": attr.label(
207 default = "//third_party:zstd_zstd",
208 cfg = "exec",
209 ),
210 "_zlib": attr.label(
211 default = "//third_party:zlib_z",
212 cfg = "exec",
213 ),
214 "_ssl": attr.label(
215 default = "//third_party:openssl_ssl",
216 cfg = "exec",
217 ),
218 "_crypto": attr.label(
219 default = "//third_party:openssl_crypto",
220 cfg = "exec",
221 ),
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200222 "_allowlist_function_transition": attr.label(
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100223 default = "@bazel_tools//tools/allowlists/function_transition_allowlist",
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200224 ),
Tim Windelschmidt6cca9322025-04-15 21:13:32 +0200225 "_exec_toolchain": attr.label(
226 default = "@rules_cc//cc:current_cc_toolchain",
227 cfg = "exec",
Lorenz Brun6df40aa2025-05-22 15:35:44 +0200228 ),
Tim Windelschmidt6cca9322025-04-15 21:13:32 +0200229 "_image_name": attr.label(
230 default = "//third_party/linux:image_name",
Lorenz Brun6df40aa2025-05-22 15:35:44 +0200231 ),
Tim Windelschmidt6cca9322025-04-15 21:13:32 +0200232 "_target_arch": attr.label(
233 default = "//third_party/linux:target_arch",
Lorenz Brun6df40aa2025-05-22 15:35:44 +0200234 ),
235 } | CC_TOOLCHAIN_ATTRS,
Lorenz Brun6df40aa2025-05-22 15:35:44 +0200236 fragments = ["cpp"],
Tim Windelschmidt6cca9322025-04-15 21:13:32 +0200237 toolchains = TOOLCHAINS + use_cc_toolchain(),
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200238)