blob: 9dd544cd8c3736fe3ebfdd1bbf56b103b348be88 [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)
Jan Schär58bbc852025-07-09 10:13:21 +0000120 # All source files have the same timestamp, take it from an arbitrary file.
121 build_timestamp=$(date -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 \
129 CC="$CC" CXX="$CXX" LD="$LD" AR="$AR" NM="$NM" STRIP="$STRIP" \
130 OBJCOPY="$OBJCOPY" OBJDUMP="$OBJDUMP" READELF="$READELF" \
131 CFLAGS="$CFLAGS" LDFLAGS="$LDFLAGS" \
132 \
133 HOSTCC="$HOSTCC" HOSTCXX="$HOSTCXX" HOSTLD="$HOSTLD" \
134 HOSTAR="$HOSTAR" HOSTNM="$HOSTNM" HOSTSTRIP="$HOSTSTRIP" \
135 HOSTOBJCOPY="$HOSTOBJCOPY" HOSTOBJDUMP="$HOSTOBJDUMP" \
136 HOSTREADELF="$HOSTREADELF" HOSTCFLAGS="$HOSTCFLAGS" \
137 HOSTLDFLAGS="$HOSTLDFLAGS" \
138 \
Jan Schär58bbc852025-07-09 10:13:21 +0000139 KBUILD_BUILD_USER=builder \
140 KBUILD_BUILD_HOST=monogon \
141 KBUILD_BUILD_TIMESTAMP="$build_timestamp" \
Tim Windelschmidt6cca9322025-04-15 21:13:32 +0200142 KBUILD_OUTPUT="$builddir" \
143 ARCH="{target_arch}" \
144 olddefconfig {target}
145 ) > /dev/null
146
147 cp "$builddir"/{image_source} {image}
148 cp "$builddir"/modules.builtin.modinfo {modinfo}
Lorenz Brun6c454342023-06-01 12:23:38 +0200149 # Not using modules_install as it tries to run depmod and friends
Tim Windelschmidt6cca9322025-04-15 21:13:32 +0200150 for f in $(find "$builddir" -name '*.ko' -type f -printf "%P\n" ); do
151 install -D "$builddir/$f" "{modules}/$f"
Lorenz Brun6c454342023-06-01 12:23:38 +0200152 done
153 rm -Rf "$builddir"
Tim Windelschmidt6cca9322025-04-15 21:13:32 +0200154 """.format(
155 kconfig = ctx.file.kernel_config.path,
156 target = target,
157 image_source = image_source,
158 kernel_src = detect_root(ctx.attr.kernel_src.files.to_list()),
159 image = image.path,
160 modinfo = modinfo.path,
161 modules = modules.path,
162 target_arch = ctx.attr._target_arch[TargetInfo].value,
163 ),
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200164 use_default_shell_env = True,
165 )
166
Mateusz Zalega9a66b182021-12-22 20:33:12 +0100167 return [
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100168 DefaultInfo(
169 files = depset([image]),
170 runfiles = ctx.runfiles(files = [image]),
171 ),
172 OutputGroupInfo(
173 modinfo = depset([modinfo]),
174 modules = depset([modules]),
175 ),
Mateusz Zalega9a66b182021-12-22 20:33:12 +0100176 ]
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200177
178linux_image = rule(
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100179 doc = """
Tim Windelschmidt6cca9322025-04-15 21:13:32 +0200180 Build Linux kernel image hermetically in a given format.
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100181 """,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200182 implementation = _linux_image_impl,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200183 attrs = {
184 "kernel_config": attr.label(
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100185 doc = """
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200186 Linux kernel configuration file to build this kernel image with.
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100187 """,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200188 allow_single_file = True,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200189 ),
190 "kernel_src": attr.label(
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100191 doc = """
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200192 Filegroup containing Linux kernel sources.
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100193 """,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200194 ),
195 "image_format": attr.string(
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100196 doc = """
Lorenz Brun6df40aa2025-05-22 15:35:44 +0200197 Format of generated Linux image, one of 'vmlinux' or 'Image',
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100198 """,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200199 values = [
Tim Windelschmidt156248b2025-01-10 00:27:45 +0100200 "vmlinux",
Lorenz Brun6df40aa2025-05-22 15:35:44 +0200201 "Image",
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200202 ],
Lorenz Brun6df40aa2025-05-22 15:35:44 +0200203 default = "Image",
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200204 ),
Tim Windelschmidt6cca9322025-04-15 21:13:32 +0200205 "_libelf": attr.label(
206 default = "//third_party:libelf_elf",
207 cfg = "exec",
208 ),
209 "_zstd": attr.label(
210 default = "//third_party:zstd_zstd",
211 cfg = "exec",
212 ),
213 "_zlib": attr.label(
214 default = "//third_party:zlib_z",
215 cfg = "exec",
216 ),
217 "_ssl": attr.label(
218 default = "//third_party:openssl_ssl",
219 cfg = "exec",
220 ),
221 "_crypto": attr.label(
222 default = "//third_party:openssl_crypto",
223 cfg = "exec",
224 ),
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)