blob: 8e5878dd9042605939b16b3343f393d9bf993763 [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")
Serge Bazanskif055a7f2021-04-13 16:22:33 +020018
Serge Bazanskif9c82492024-09-16 16:50:39 +020019def _linux_image_impl_resources(_os, _ninputs):
20 """
21 Configures linux build resources.
22
23 See `resource_set` documentation in builtins.actions Bazel docs.
24 """
Tim Windelschmidt156248b2025-01-10 00:27:45 +010025
Serge Bazanskif9c82492024-09-16 16:50:39 +020026 # 16 threads seems about right - this fits well in both our build machines and
27 # development machines.
28 cpu = 16
Tim Windelschmidt156248b2025-01-10 00:27:45 +010029
Serge Bazanskif9c82492024-09-16 16:50:39 +020030 # In MB. Picked based on observing build in htop.
31 mb_per_cpu = 256
32 return {
Tim Windelschmidt156248b2025-01-10 00:27:45 +010033 "cpu": cpu,
34 "memory": cpu * mb_per_cpu,
35 "local_test": 0,
Serge Bazanskif9c82492024-09-16 16:50:39 +020036 }
Serge Bazanskif055a7f2021-04-13 16:22:33 +020037
Tim Windelschmidt6cca9322025-04-15 21:13:32 +020038TOOLCHAINS = [
39 "//build/toolchain/toolchain-bundle:make_toolchain",
40 "//build/toolchain/toolchain-bundle:flex_toolchain",
41 "//build/toolchain/toolchain-bundle:bison_toolchain",
42 "//build/toolchain/toolchain-bundle:m4_toolchain",
43 "//build/toolchain/toolchain-bundle:busybox_toolchain",
44 "//build/toolchain/toolchain-bundle:bc_toolchain",
45 "//build/toolchain/toolchain-bundle:diff_toolchain",
46 "//build/toolchain/toolchain-bundle:perl_toolchain",
47 "//build/toolchain/toolchain-bundle:lz4_toolchain",
48]
Lorenz Brun6df40aa2025-05-22 15:35:44 +020049
Serge Bazanskif055a7f2021-04-13 16:22:33 +020050def _linux_image_impl(ctx):
Serge Bazanskif055a7f2021-04-13 16:22:33 +020051 # Tuple containing information about how to build and access the resulting
52 # image.
53 # The first element (target) is the make target to build, the second
Mateusz Zalega9a66b182021-12-22 20:33:12 +010054 # (image_source) is the resulting file to be copied and the last
55 # (image_name) is the name of the image that will be generated by this
Serge Bazanskif055a7f2021-04-13 16:22:33 +020056 # rule.
Mateusz Zalega9a66b182021-12-22 20:33:12 +010057 (target, image_source, image_name) = {
Tim Windelschmidt156248b2025-01-10 00:27:45 +010058 "vmlinux": ("vmlinux modules", "vmlinux", "vmlinux"),
Tim Windelschmidt6cca9322025-04-15 21:13:32 +020059 "Image": ("all modules", "arch/" + ctx.attr._target_arch[TargetInfo].value + "/boot/" + ctx.attr._image_name[TargetInfo].value, "Image"),
60 }[ctx.attr.image_format]
61
62 ssl_src, ssl_gen = detect_roots(ctx.attr._ssl[CcInfo].compilation_context.direct_public_headers)
63 crypto_src, crypto_gen = detect_roots(ctx.attr._crypto[CcInfo].compilation_context.direct_public_headers)
64 extra_env = {
65 "HOSTLDFLAGS": " -L ".join(
66 [
67 "", # First element empty, for force a the join prefix
68 detect_root(ctx.attr._zstd.files.to_list()).rsplit("/", 1)[0],
69 detect_root(ctx.attr._zlib.files.to_list()).rsplit("/", 1)[0],
70 detect_root(ctx.attr._libelf.files.to_list()).rsplit("/", 1)[0],
71 detect_root(ctx.attr._ssl.files.to_list()).rsplit("/", 1)[0],
72 detect_root(ctx.attr._crypto.files.to_list()).rsplit("/", 1)[0],
73 ],
74 ),
75 "HOSTCFLAGS": " -I ".join(
76 [
77 "", # First element empty, for force a the join prefix
78 detect_root(ctx.attr._libelf[CcInfo].compilation_context.direct_public_headers),
79 ssl_src + "/../",
80 ssl_gen + "/../include/",
81 crypto_src + "/../",
82 crypto_gen + "/../include/",
83 ],
84 ),
85 }
86
87 inputs = depset(
88 ctx.files.kernel_config +
89 ctx.files.kernel_src +
90 ctx.files._libelf +
91 ctx.attr._libelf[CcInfo].compilation_context.direct_public_headers +
92 ctx.files._zlib +
93 ctx.files._ssl +
94 ctx.attr._ssl[CcInfo].compilation_context.direct_public_headers +
95 ctx.files._crypto +
96 ctx.attr._crypto[CcInfo].compilation_context.direct_public_headers,
97 )
98
99 # Setup the environment for the foreign build.
100 toolchain_env, toolchain_inputs, toolchain_cmd = generate_foreign_build_env(
101 ctx = ctx,
102 target_toolchain = find_cpp_toolchain(ctx),
103 exec_toolchain = ctx.attr._exec_toolchain[cc_common.CcToolchainInfo],
104 toolchain_bundle_tools = TOOLCHAINS,
105 )
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200106
Mateusz Zalega9a66b182021-12-22 20:33:12 +0100107 image = ctx.actions.declare_file(image_name)
108 modinfo = ctx.actions.declare_file("modules.builtin.modinfo")
Lorenz Brun6c454342023-06-01 12:23:38 +0200109 modules = ctx.actions.declare_directory("modules")
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200110 ctx.actions.run_shell(
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100111 outputs = [image, modinfo, modules],
Tim Windelschmidt6cca9322025-04-15 21:13:32 +0200112 inputs = depset(transitive = [inputs, toolchain_inputs]),
Serge Bazanskif9c82492024-09-16 16:50:39 +0200113 resource_set = _linux_image_impl_resources,
Tim Windelschmidt6cca9322025-04-15 21:13:32 +0200114 env = merge_env(toolchain_env, extra_env),
115 progress_message = "Building Linux Kernel: {}".format(ctx.label.name),
116 mnemonic = "BuildLinux",
117 command = toolchain_cmd + """
118 export BISON_PKGDATADIR=$(realpath $(dirname $BISON))/../share/bison
Lorenz Brun6c454342023-06-01 12:23:38 +0200119 builddir=$(mktemp -d)
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200120
Tim Windelschmidt6cca9322025-04-15 21:13:32 +0200121 mkdir {kernel_src}/.bin
122 cp {kconfig} $builddir/.config
123 (
124 cd {kernel_src} &&
125 make -j 16 \
126 \
127 CC="$CC" CXX="$CXX" LD="$LD" AR="$AR" NM="$NM" STRIP="$STRIP" \
128 OBJCOPY="$OBJCOPY" OBJDUMP="$OBJDUMP" READELF="$READELF" \
129 CFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS" \
130 \
131 HOSTCC="$HOSTCC" HOSTCXX="$HOSTCXX" HOSTLD="$HOSTLD" \
132 HOSTAR="$HOSTAR" HOSTNM="$HOSTNM" HOSTSTRIP="$HOSTSTRIP" \
133 HOSTOBJCOPY="$HOSTOBJCOPY" HOSTOBJDUMP="$HOSTOBJDUMP" \
134 HOSTREADELF="$HOSTREADELF" HOSTCFLAGS="$HOSTCFLAGS" \
135 HOSTLDFLAGS="$HOSTLDFLAGS" \
136 \
137 KBUILD_OUTPUT="$builddir" \
138 ARCH="{target_arch}" \
139 olddefconfig {target}
140 ) > /dev/null
141
142 cp "$builddir"/{image_source} {image}
143 cp "$builddir"/modules.builtin.modinfo {modinfo}
Lorenz Brun6c454342023-06-01 12:23:38 +0200144 # Not using modules_install as it tries to run depmod and friends
Tim Windelschmidt6cca9322025-04-15 21:13:32 +0200145 for f in $(find "$builddir" -name '*.ko' -type f -printf "%P\n" ); do
146 install -D "$builddir/$f" "{modules}/$f"
Lorenz Brun6c454342023-06-01 12:23:38 +0200147 done
148 rm -Rf "$builddir"
Tim Windelschmidt6cca9322025-04-15 21:13:32 +0200149 """.format(
150 kconfig = ctx.file.kernel_config.path,
151 target = target,
152 image_source = image_source,
153 kernel_src = detect_root(ctx.attr.kernel_src.files.to_list()),
154 image = image.path,
155 modinfo = modinfo.path,
156 modules = modules.path,
157 target_arch = ctx.attr._target_arch[TargetInfo].value,
158 ),
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200159 use_default_shell_env = True,
160 )
161
Mateusz Zalega9a66b182021-12-22 20:33:12 +0100162 return [
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100163 DefaultInfo(
164 files = depset([image]),
165 runfiles = ctx.runfiles(files = [image]),
166 ),
167 OutputGroupInfo(
168 modinfo = depset([modinfo]),
169 modules = depset([modules]),
170 ),
Mateusz Zalega9a66b182021-12-22 20:33:12 +0100171 ]
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200172
173linux_image = rule(
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100174 doc = """
Tim Windelschmidt6cca9322025-04-15 21:13:32 +0200175 Build Linux kernel image hermetically in a given format.
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100176 """,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200177 implementation = _linux_image_impl,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200178 attrs = {
179 "kernel_config": attr.label(
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100180 doc = """
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200181 Linux kernel configuration file to build this kernel image with.
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100182 """,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200183 allow_single_file = True,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200184 ),
185 "kernel_src": attr.label(
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100186 doc = """
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200187 Filegroup containing Linux kernel sources.
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100188 """,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200189 ),
190 "image_format": attr.string(
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100191 doc = """
Lorenz Brun6df40aa2025-05-22 15:35:44 +0200192 Format of generated Linux image, one of 'vmlinux' or 'Image',
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100193 """,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200194 values = [
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100195 "vmlinux",
Lorenz Brun6df40aa2025-05-22 15:35:44 +0200196 "Image",
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200197 ],
Lorenz Brun6df40aa2025-05-22 15:35:44 +0200198 default = "Image",
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200199 ),
Tim Windelschmidt6cca9322025-04-15 21:13:32 +0200200 "_libelf": attr.label(
201 default = "//third_party:libelf_elf",
202 cfg = "exec",
203 ),
204 "_zstd": attr.label(
205 default = "//third_party:zstd_zstd",
206 cfg = "exec",
207 ),
208 "_zlib": attr.label(
209 default = "//third_party:zlib_z",
210 cfg = "exec",
211 ),
212 "_ssl": attr.label(
213 default = "//third_party:openssl_ssl",
214 cfg = "exec",
215 ),
216 "_crypto": attr.label(
217 default = "//third_party:openssl_crypto",
218 cfg = "exec",
219 ),
Tim Windelschmidt6cca9322025-04-15 21:13:32 +0200220 "_exec_toolchain": attr.label(
221 default = "@rules_cc//cc:current_cc_toolchain",
222 cfg = "exec",
Lorenz Brun6df40aa2025-05-22 15:35:44 +0200223 ),
Tim Windelschmidt6cca9322025-04-15 21:13:32 +0200224 "_image_name": attr.label(
225 default = "//third_party/linux:image_name",
Lorenz Brun6df40aa2025-05-22 15:35:44 +0200226 ),
Tim Windelschmidt6cca9322025-04-15 21:13:32 +0200227 "_target_arch": attr.label(
228 default = "//third_party/linux:target_arch",
Lorenz Brun6df40aa2025-05-22 15:35:44 +0200229 ),
230 } | CC_TOOLCHAIN_ATTRS,
Lorenz Brun6df40aa2025-05-22 15:35:44 +0200231 fragments = ["cpp"],
Tim Windelschmidt6cca9322025-04-15 21:13:32 +0200232 toolchains = TOOLCHAINS + use_cc_toolchain(),
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200233)