blob: 885e3290b8650c4a0a6648014b84edb76c928c6d [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
26load("//build/utils:detect_root.bzl", "detect_root")
27
28
Serge Bazanski5b13d812023-06-20 13:22:23 +020029_new_settings = {
30 # This list should be expanded with any configuration options that end
31 # up reaching this rule with different values across different build
32 # graph paths, but that do not actually influence the kernel build.
33 # Force-setting them to a stable value forces the build configuration
34 # to a stable hash.
35 # See the transition's comment block for more information.
36 "@io_bazel_rules_go//go/config:pure": True,
37 "@io_bazel_rules_go//go/config:static": True,
38
39 "@io_bazel_rules_docker//platforms:image_transition_cpu": "@platforms//cpu:x86_64",
40 "@io_bazel_rules_docker//platforms:image_transition_os": "@platforms//os:linux",
41
42 # Note: this toolchain is not actually used to perform the build.
43 "//command_line_option:platforms": "//build/platforms:linux_amd64_static",
44}
45
46
Serge Bazanskif055a7f2021-04-13 16:22:33 +020047def _ignore_unused_configuration_impl(settings, attr):
Serge Bazanski5b13d812023-06-20 13:22:23 +020048 return _new_settings
Serge Bazanskif055a7f2021-04-13 16:22:33 +020049
50# Transition to flip all known-unimportant but varying configuration options to
51# a known, stable value.
52# This is to prevent Bazel from creating extra configurations for possible
53# combinations of options in case the linux_image rule is pulled through build
54# graph fragments that have different options set.
55#
56# Ideally, Bazel would let us mark in a list that we only care about some set
57# of options (or at least let us mark those that we explicitly don't care
58# about, instead of manually setting them to some value). However, this doesn't
59# seem to be possible, thus this transition is a bit of a hack.
60ignore_unused_configuration = transition(
61 implementation = _ignore_unused_configuration_impl,
62 inputs = [],
Serge Bazanski5b13d812023-06-20 13:22:23 +020063 outputs = list(_new_settings.keys()),
Serge Bazanskif055a7f2021-04-13 16:22:33 +020064)
65
66
67def _linux_image_impl(ctx):
68 kernel_config = ctx.file.kernel_config
69 kernel_src = ctx.files.kernel_src
70 image_format = ctx.attr.image_format
71
72 # Tuple containing information about how to build and access the resulting
73 # image.
74 # The first element (target) is the make target to build, the second
Mateusz Zalega9a66b182021-12-22 20:33:12 +010075 # (image_source) is the resulting file to be copied and the last
76 # (image_name) is the name of the image that will be generated by this
Serge Bazanskif055a7f2021-04-13 16:22:33 +020077 # rule.
Mateusz Zalega9a66b182021-12-22 20:33:12 +010078 (target, image_source, image_name) = {
Lorenz Brun6c454342023-06-01 12:23:38 +020079 'vmlinux': ('vmlinux modules', 'vmlinux', 'vmlinux'),
80 'bzImage': ('all modules', 'arch/x86/boot/bzImage', 'bzImage'),
Serge Bazanskif055a7f2021-04-13 16:22:33 +020081 }[image_format]
82
83 # Root of the given Linux sources.
84 root = detect_root(ctx.attr.kernel_src)
85
Mateusz Zalega9a66b182021-12-22 20:33:12 +010086 image = ctx.actions.declare_file(image_name)
87 modinfo = ctx.actions.declare_file("modules.builtin.modinfo")
Lorenz Brun6c454342023-06-01 12:23:38 +020088 modules = ctx.actions.declare_directory("modules")
Serge Bazanskif055a7f2021-04-13 16:22:33 +020089 ctx.actions.run_shell(
Lorenz Brun6c454342023-06-01 12:23:38 +020090 outputs = [ image, modinfo, modules ],
Serge Bazanskif055a7f2021-04-13 16:22:33 +020091 inputs = [ kernel_config ] + kernel_src,
92 command = '''
93 kconfig=$1
94 target=$2
Mateusz Zalega9a66b182021-12-22 20:33:12 +010095 image_source=$3
96 image=$4
Serge Bazanskif055a7f2021-04-13 16:22:33 +020097 root=$5
Mateusz Zalega9a66b182021-12-22 20:33:12 +010098 modinfo=$6
Lorenz Brun6c454342023-06-01 12:23:38 +020099 modules=$7
100
101 builddir=$(mktemp -d)
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200102
103 mkdir ${root}/.bin
Lorenz Brun6c454342023-06-01 12:23:38 +0200104 cp ${kconfig} ${builddir}/.config
105 (cd ${root} && KBUILD_OUTPUT="${builddir}" make -j $(nproc) ${target} >/dev/null)
106 cp "${builddir}"/${image_source} ${image}
107 cp "${builddir}"/modules.builtin.modinfo ${modinfo}
108 # Not using modules_install as it tries to run depmod and friends
109 for f in $(find "${builddir}" -name '*.ko' -type f -printf "%P\n" ); do
110 install -D "${builddir}/$f" "${modules}/$f"
111 done
112 rm -Rf "$builddir"
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200113 ''',
114 arguments = [
115 kernel_config.path,
116 target,
Mateusz Zalega9a66b182021-12-22 20:33:12 +0100117 image_source,
118 image.path,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200119 root,
Lorenz Brun6c454342023-06-01 12:23:38 +0200120 modinfo.path,
121 modules.path,
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200122 ],
123 use_default_shell_env = True,
124 )
125
Mateusz Zalega9a66b182021-12-22 20:33:12 +0100126 return [
127 DefaultInfo(
128 files=depset([image]),
129 runfiles=ctx.runfiles(files=[image])
130 ),
131 OutputGroupInfo(
Lorenz Brun6c454342023-06-01 12:23:38 +0200132 modinfo = depset([modinfo]),
133 modules = depset([modules])
Mateusz Zalega9a66b182021-12-22 20:33:12 +0100134 )
135 ]
Serge Bazanskif055a7f2021-04-13 16:22:33 +0200136
137linux_image = rule(
138 doc = '''
139 Build Linux kernel image unhermetically in a given format.
140 ''',
141 implementation = _linux_image_impl,
142 cfg = ignore_unused_configuration,
143 attrs = {
144 "kernel_config": attr.label(
145 doc = '''
146 Linux kernel configuration file to build this kernel image with.
147 ''',
148 allow_single_file = True,
149 default = ":linux-metropolis.config",
150 ),
151 "kernel_src": attr.label(
152 doc = '''
153 Filegroup containing Linux kernel sources.
154 ''',
155 default = "@linux//:all",
156 ),
157 "image_format": attr.string(
158 doc = '''
159 Format of generated Linux image, one of 'vmlinux' or 'bzImage',
160 ''',
161 values = [
162 'vmlinux', 'bzImage',
163 ],
164 default = 'bzImage',
165 ),
166 "_allowlist_function_transition": attr.label(
167 default = "@bazel_tools//tools/allowlists/function_transition_allowlist"
168 ),
169 },
170)