blob: 1f16d2eb7dd5e1457a025fc96ca22f9c086d048b [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 + """
Tim Windelschmidt9c8f2532025-07-09 23:09:06 +0200118 export BISON_PKGDATADIR=$(realpath $(dirname $BISON)/../share/bison)
Lorenz Brun6c454342023-06-01 12:23:38 +0200119 builddir=$(mktemp -d)
Jan Schär58bbc852025-07-09 10:13:21 +0000120 # All source files have the same timestamp, take it from an arbitrary file.
Jan Schäre10570c2025-07-17 19:36:10 +0200121 build_timestamp=$(date --utc -r {kernel_src}/README)
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200122
Tim Windelschmidt6cca9322025-04-15 21:13:32 +0200123 mkdir {kernel_src}/.bin
124 cp {kconfig} $builddir/.config
125 (
126 cd {kernel_src} &&
127 make -j 16 \
128 \
Tim Windelschmidt9c8f2532025-07-09 23:09:06 +0200129 YACC="$BISON" LEX="$FLEX" \
130 \
Tim Windelschmidt6cca9322025-04-15 21:13:32 +0200131 CC="$CC" CXX="$CXX" LD="$LD" AR="$AR" NM="$NM" STRIP="$STRIP" \
132 OBJCOPY="$OBJCOPY" OBJDUMP="$OBJDUMP" READELF="$READELF" \
133 CFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS" \
134 \
135 HOSTCC="$HOSTCC" HOSTCXX="$HOSTCXX" HOSTLD="$HOSTLD" \
136 HOSTAR="$HOSTAR" HOSTNM="$HOSTNM" HOSTSTRIP="$HOSTSTRIP" \
137 HOSTOBJCOPY="$HOSTOBJCOPY" HOSTOBJDUMP="$HOSTOBJDUMP" \
138 HOSTREADELF="$HOSTREADELF" HOSTCFLAGS="$HOSTCFLAGS" \
139 HOSTLDFLAGS="$HOSTLDFLAGS" \
140 \
Jan Schär58bbc852025-07-09 10:13:21 +0000141 KBUILD_BUILD_USER=builder \
142 KBUILD_BUILD_HOST=monogon \
143 KBUILD_BUILD_TIMESTAMP="$build_timestamp" \
Tim Windelschmidt6cca9322025-04-15 21:13:32 +0200144 KBUILD_OUTPUT="$builddir" \
145 ARCH="{target_arch}" \
146 olddefconfig {target}
147 ) > /dev/null
148
149 cp "$builddir"/{image_source} {image}
150 cp "$builddir"/modules.builtin.modinfo {modinfo}
Lorenz Brun6c454342023-06-01 12:23:38 +0200151 # Not using modules_install as it tries to run depmod and friends
Tim Windelschmidt6cca9322025-04-15 21:13:32 +0200152 for f in $(find "$builddir" -name '*.ko' -type f -printf "%P\n" ); do
153 install -D "$builddir/$f" "{modules}/$f"
Lorenz Brun6c454342023-06-01 12:23:38 +0200154 done
155 rm -Rf "$builddir"
Tim Windelschmidt6cca9322025-04-15 21:13:32 +0200156 """.format(
157 kconfig = ctx.file.kernel_config.path,
158 target = target,
159 image_source = image_source,
160 kernel_src = detect_root(ctx.attr.kernel_src.files.to_list()),
161 image = image.path,
162 modinfo = modinfo.path,
163 modules = modules.path,
164 target_arch = ctx.attr._target_arch[TargetInfo].value,
165 ),
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200166 use_default_shell_env = True,
167 )
168
Mateusz Zalega9a66b182021-12-22 20:33:12 +0100169 return [
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100170 DefaultInfo(
171 files = depset([image]),
172 runfiles = ctx.runfiles(files = [image]),
173 ),
174 OutputGroupInfo(
175 modinfo = depset([modinfo]),
176 modules = depset([modules]),
177 ),
Mateusz Zalega9a66b182021-12-22 20:33:12 +0100178 ]
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200179
180linux_image = rule(
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100181 doc = """
Tim Windelschmidt6cca9322025-04-15 21:13:32 +0200182 Build Linux kernel image hermetically in a given format.
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100183 """,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200184 implementation = _linux_image_impl,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200185 attrs = {
186 "kernel_config": attr.label(
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100187 doc = """
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200188 Linux kernel configuration file to build this kernel image with.
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100189 """,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200190 allow_single_file = True,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200191 ),
192 "kernel_src": attr.label(
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100193 doc = """
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200194 Filegroup containing Linux kernel sources.
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100195 """,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200196 ),
197 "image_format": attr.string(
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100198 doc = """
Lorenz Brun6df40aa2025-05-22 15:35:44 +0200199 Format of generated Linux image, one of 'vmlinux' or 'Image',
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100200 """,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200201 values = [
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100202 "vmlinux",
Lorenz Brun6df40aa2025-05-22 15:35:44 +0200203 "Image",
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200204 ],
Lorenz Brun6df40aa2025-05-22 15:35:44 +0200205 default = "Image",
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200206 ),
Tim Windelschmidt6cca9322025-04-15 21:13:32 +0200207 "_libelf": attr.label(
208 default = "//third_party:libelf_elf",
209 cfg = "exec",
210 ),
211 "_zstd": attr.label(
212 default = "//third_party:zstd_zstd",
213 cfg = "exec",
214 ),
215 "_zlib": attr.label(
216 default = "//third_party:zlib_z",
217 cfg = "exec",
218 ),
219 "_ssl": attr.label(
220 default = "//third_party:openssl_ssl",
221 cfg = "exec",
222 ),
223 "_crypto": attr.label(
224 default = "//third_party:openssl_crypto",
225 cfg = "exec",
226 ),
Tim Windelschmidt6cca9322025-04-15 21:13:32 +0200227 "_exec_toolchain": attr.label(
228 default = "@rules_cc//cc:current_cc_toolchain",
229 cfg = "exec",
Lorenz Brun6df40aa2025-05-22 15:35:44 +0200230 ),
Tim Windelschmidt6cca9322025-04-15 21:13:32 +0200231 "_image_name": attr.label(
232 default = "//third_party/linux:image_name",
Lorenz Brun6df40aa2025-05-22 15:35:44 +0200233 ),
Tim Windelschmidt6cca9322025-04-15 21:13:32 +0200234 "_target_arch": attr.label(
235 default = "//third_party/linux:target_arch",
Lorenz Brun6df40aa2025-05-22 15:35:44 +0200236 ),
237 } | CC_TOOLCHAIN_ATTRS,
Lorenz Brun6df40aa2025-05-22 15:35:44 +0200238 fragments = ["cpp"],
Tim Windelschmidt6cca9322025-04-15 21:13:32 +0200239 toolchains = TOOLCHAINS + use_cc_toolchain(),
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200240)