osbase/build: move efi.bzl, split and move def.bzl to their corresponding action
This is a small reorganization to make the osbase/build less dependent on each other.
Change-Id: I8c12f04f3bdc98128c5424f142f452c2e094f2e8
Reviewed-on: https://review.monogon.dev/c/monogon/+/3903
Tested-by: Jenkins CI
Reviewed-by: Lorenz Brun <lorenz@monogon.tech>
diff --git a/osbase/bringup/test/BUILD.bazel b/osbase/bringup/test/BUILD.bazel
index a5f3768..103b2b4 100644
--- a/osbase/bringup/test/BUILD.bazel
+++ b/osbase/bringup/test/BUILD.bazel
@@ -1,6 +1,6 @@
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library", "go_test")
-load("//osbase/build:def.bzl", "node_initramfs")
-load("//osbase/build:efi.bzl", "efi_unified_kernel_image")
+load("//osbase/build/mkcpio:def.bzl", "node_initramfs")
+load("//osbase/build/mkpayload:def.bzl", "efi_unified_kernel_image")
go_test(
name = "test_test",
diff --git a/osbase/build/def.bzl b/osbase/build/def.bzl
index d4b497c..e88614b 100644
--- a/osbase/build/def.bzl
+++ b/osbase/build/def.bzl
@@ -40,277 +40,3 @@
"//command_line_option:platforms",
],
)
-
-FSSpecInfo = provider(
- "Provides parts of an FSSpec used to assemble filesystem images",
- fields = {
- "spec": "File containing the partial FSSpec as prototext",
- "referenced": "Files (potentially) referenced by the spec",
- },
-)
-
-def fsspec_core_impl(ctx, tool, output_file, extra_files = [], extra_fsspecs = []):
- """
- fsspec_core_impl implements the core of an fsspec-based rule. It takes
- input from the `files`,`files_cc`, `symlinks` and `fsspecs` attributes
- and calls `tool` with the `-out` parameter pointing to `output_file`
- and paths to all fsspecs as positional arguments.
- """
- fs_spec_name = ctx.label.name + ".prototxt"
- fs_spec = ctx.actions.declare_file(fs_spec_name)
-
- fs_files = []
- inputs = []
- for p, label in ctx.attr.files.items() + ctx.attr.files_cc.items() + extra_files:
- if not p.startswith("/"):
- fail("file {} invalid: must begin with /".format(p))
-
- # Figure out if this is an executable.
- is_executable = True
-
- di = label[DefaultInfo]
- if di.files_to_run.executable == None:
- # Generated non-executable files will have DefaultInfo.files_to_run.executable == None
- is_executable = False
- elif di.files_to_run.executable.is_source:
- # Source files will have executable.is_source == True
- is_executable = False
-
- # Ensure only single output is declared.
- # If you hit this error, figure out a better logic to find what file you need, maybe looking at providers other
- # than DefaultInfo.
- files = di.files.to_list()
- if len(files) > 1:
- fail("file {} has more than one output: {}", p, files)
- src = files[0]
- inputs.append(src)
-
- mode = 0o555 if is_executable else 0o444
- fs_files.append(struct(path = p, source_path = src.path, mode = mode, uid = 0, gid = 0))
-
- fs_symlinks = []
- for target, p in ctx.attr.symlinks.items():
- fs_symlinks.append(struct(path = p, target_path = target))
-
- fs_spec_content = struct(file = fs_files, directory = [], symbolic_link = fs_symlinks)
- ctx.actions.write(fs_spec, proto.encode_text(fs_spec_content))
-
- extra_specs = []
-
- for fsspec in ctx.attr.fsspecs + extra_fsspecs:
- if FSSpecInfo in fsspec:
- fsspec_info = fsspec[FSSpecInfo]
- extra_specs.append(fsspec_info.spec)
- for f in fsspec_info.referenced:
- inputs.append(f)
- else:
- # Raw .fsspec prototext. No referenced data allowed.
- di = fsspec[DefaultInfo]
- extra_specs += di.files.to_list()
-
- ctx.actions.run(
- outputs = [output_file],
- inputs = [fs_spec] + inputs + extra_specs,
- tools = [tool],
- executable = tool,
- arguments = ["-out", output_file.path, fs_spec.path] + [s.path for s in extra_specs],
- )
- return
-
-def _node_initramfs_impl(ctx):
- initramfs_name = ctx.label.name + ".cpio.zst"
- initramfs = ctx.actions.declare_file(initramfs_name)
-
- fsspec_core_impl(ctx, ctx.executable._mkcpio, initramfs)
-
- # TODO(q3k): Document why this is needed
- return [DefaultInfo(runfiles = ctx.runfiles(files = [initramfs]), files = depset([initramfs]))]
-
-node_initramfs = rule(
- implementation = _node_initramfs_impl,
- doc = """
- Build a node initramfs. The initramfs will contain a basic /dev directory and all the files specified by the
- `files` attribute. Executable files will have their permissions set to 0755, non-executable files will have
- their permissions set to 0444. All parent directories will be created with 0755 permissions.
- """,
- attrs = {
- "files": attr.string_keyed_label_dict(
- mandatory = True,
- allow_files = True,
- doc = """
- Dictionary of Labels to String, placing a given Label's output file in the initramfs at the location
- specified by the String value. The specified labels must only have a single output.
- """,
- # Attach pure transition to ensure all binaries added to the initramfs are pure/static binaries.
- cfg = build_pure_transition,
- ),
- "files_cc": attr.string_keyed_label_dict(
- allow_files = True,
- doc = """
- Special case of 'files' for compilation targets that need to be built with the musl toolchain like
- go_binary targets which need cgo or cc_binary targets.
- """,
- # Attach static transition to all files_cc inputs to ensure they are built with musl and static.
- cfg = build_static_transition,
- ),
- "symlinks": attr.string_dict(
- default = {},
- doc = """
- Symbolic links to create. Similar format as in files and files_cc, so the target of the symlink is the
- key and the value of it is the location of the symlink itself. Only raw strings are allowed as targets,
- labels are not permitted. Include the file using files or files_cc, then symlink to its location.
- """,
- ),
- "fsspecs": attr.label_list(
- default = [],
- doc = """
- List of file system specs (osbase.build.fsspec.FSSpec) to also include in the resulting image.
- These will be merged with all other given attributes.
- """,
- providers = [FSSpecInfo],
- allow_files = True,
- ),
-
- # Tool
- "_mkcpio": attr.label(
- default = Label("//osbase/build/mkcpio"),
- executable = True,
- cfg = "exec",
- ),
- },
-)
-
-def _erofs_image_impl(ctx):
- fs_name = ctx.label.name + ".img"
- fs_out = ctx.actions.declare_file(fs_name)
-
- fsspec_core_impl(ctx, ctx.executable._mkerofs, fs_out)
-
- return [DefaultInfo(files = depset([fs_out]))]
-
-erofs_image = rule(
- implementation = _erofs_image_impl,
- doc = """
- Build an EROFS. All files specified in files, files_cc and all specified symlinks will be contained.
- Executable files will have their permissions set to 0555, non-executable files will have
- their permissions set to 0444. All parent directories will be created with 0555 permissions.
- """,
- attrs = {
- "files": attr.string_keyed_label_dict(
- mandatory = True,
- allow_files = True,
- doc = """
- Dictionary of Labels to String, placing a given Label's output file in the EROFS at the location
- specified by the String value. The specified labels must only have a single output.
- """,
- # Attach pure transition to ensure all binaries added to the initramfs are pure/static binaries.
- cfg = build_pure_transition,
- ),
- "files_cc": attr.string_keyed_label_dict(
- allow_files = True,
- doc = """
- Special case of 'files' for compilation targets that need to be built with the musl toolchain like
- go_binary targets which need cgo or cc_binary targets.
- """,
- # Attach static transition to all files_cc inputs to ensure they are built with musl and static.
- cfg = build_static_transition,
- ),
- "symlinks": attr.string_dict(
- default = {},
- doc = """
- Symbolic links to create. Similar format as in files and files_cc, so the target of the symlink is the
- key and the value of it is the location of the symlink itself. Only raw strings are allowed as targets,
- labels are not permitted. Include the file using files or files_cc, then symlink to its location.
- """,
- ),
- "fsspecs": attr.label_list(
- default = [],
- doc = """
- List of file system specs (osbase.build.fsspec.FSSpec) to also include in the resulting image.
- These will be merged with all other given attributes.
- """,
- providers = [FSSpecInfo],
- allow_files = True,
- ),
-
- # Tools, implicit dependencies.
- "_mkerofs": attr.label(
- default = Label("//osbase/build/mkerofs"),
- executable = True,
- cfg = "exec",
- ),
- },
-)
-
-# VerityInfo is emitted by verity_image, and contains a file enclosing a
-# singular dm-verity target table.
-VerityInfo = provider(
- "Information necessary to mount a single dm-verity target.",
- fields = {
- "table": "A file containing the dm-verity target table. See: https://www.kernel.org/doc/html/latest/admin-guide/device-mapper/verity.html",
- },
-)
-
-def _verity_image_impl(ctx):
- """
- Create a new file containing the source image data together with the Verity
- metadata appended to it, and provide an associated DeviceMapper Verity target
- table in a separate file, through VerityInfo provider.
- """
-
- # Run mkverity.
- image = ctx.actions.declare_file(ctx.attr.name + ".img")
- table = ctx.actions.declare_file(ctx.attr.name + ".dmt")
- ctx.actions.run(
- mnemonic = "GenVerityImage",
- progress_message = "Generating a dm-verity image: {}".format(image.short_path),
- inputs = [ctx.file.source],
- outputs = [
- image,
- table,
- ],
- executable = ctx.file._mkverity,
- arguments = [
- "-input=" + ctx.file.source.path,
- "-output=" + image.path,
- "-table=" + table.path,
- "-data_alias=" + ctx.attr.rootfs_partlabel,
- "-hash_alias=" + ctx.attr.rootfs_partlabel,
- ],
- )
-
- return [
- DefaultInfo(
- files = depset([image]),
- runfiles = ctx.runfiles(files = [image]),
- ),
- VerityInfo(
- table = table,
- ),
- ]
-
-verity_image = rule(
- implementation = _verity_image_impl,
- doc = """
- Build a dm-verity target image by appending Verity metadata to the source
- image. A corresponding dm-verity target table will be made available
- through VerityInfo provider.
- """,
- attrs = {
- "source": attr.label(
- doc = "A source image.",
- allow_single_file = True,
- ),
- "rootfs_partlabel": attr.string(
- doc = "GPT partition label of the rootfs to be used with dm-mod.create.",
- default = "PARTLABEL=METROPOLIS-SYSTEM-X",
- ),
- "_mkverity": attr.label(
- doc = "The mkverity executable needed to generate the image.",
- default = "//osbase/build/mkverity",
- allow_single_file = True,
- executable = True,
- cfg = "exec",
- ),
- },
-)
diff --git a/osbase/build/fsspec/def.bzl b/osbase/build/fsspec/def.bzl
new file mode 100644
index 0000000..8e68069
--- /dev/null
+++ b/osbase/build/fsspec/def.bzl
@@ -0,0 +1,77 @@
+FSSpecInfo = provider(
+ "Provides parts of an FSSpec used to assemble filesystem images",
+ fields = {
+ "spec": "File containing the partial FSSpec as prototext",
+ "referenced": "Files (potentially) referenced by the spec",
+ },
+)
+
+def fsspec_core_impl(ctx, tool, output_file, extra_files = [], extra_fsspecs = []):
+ """
+ fsspec_core_impl implements the core of an fsspec-based rule. It takes
+ input from the `files`,`files_cc`, `symlinks` and `fsspecs` attributes
+ and calls `tool` with the `-out` parameter pointing to `output_file`
+ and paths to all fsspecs as positional arguments.
+ """
+ fs_spec_name = ctx.label.name + ".prototxt"
+ fs_spec = ctx.actions.declare_file(fs_spec_name)
+
+ fs_files = []
+ inputs = []
+ for p, label in ctx.attr.files.items() + ctx.attr.files_cc.items() + extra_files:
+ if not p.startswith("/"):
+ fail("file {} invalid: must begin with /".format(p))
+
+ # Figure out if this is an executable.
+ is_executable = True
+
+ di = label[DefaultInfo]
+ if di.files_to_run.executable == None:
+ # Generated non-executable files will have DefaultInfo.files_to_run.executable == None
+ is_executable = False
+ elif di.files_to_run.executable.is_source:
+ # Source files will have executable.is_source == True
+ is_executable = False
+
+ # Ensure only single output is declared.
+ # If you hit this error, figure out a better logic to find what file you need, maybe looking at providers other
+ # than DefaultInfo.
+ files = di.files.to_list()
+ if len(files) > 1:
+ fail("file {} has more than one output: {}", p, files)
+ src = files[0]
+ inputs.append(src)
+
+ mode = 0o555 if is_executable else 0o444
+ fs_files.append(struct(path = p, source_path = src.path, mode = mode, uid = 0, gid = 0))
+
+ fs_symlinks = []
+ for target, p in ctx.attr.symlinks.items():
+ fs_symlinks.append(struct(path = p, target_path = target))
+
+ fs_spec_content = struct(file = fs_files, directory = [], symbolic_link = fs_symlinks)
+ ctx.actions.write(fs_spec, proto.encode_text(fs_spec_content))
+
+ extra_specs = []
+
+ for fsspec in ctx.attr.fsspecs + extra_fsspecs:
+ if FSSpecInfo in fsspec:
+ fsspec_info = fsspec[FSSpecInfo]
+ extra_specs.append(fsspec_info.spec)
+ for f in fsspec_info.referenced:
+ inputs.append(f)
+ else:
+ # Raw .fsspec prototext. No referenced data allowed.
+ di = fsspec[DefaultInfo]
+ extra_specs += di.files.to_list()
+
+ ctx.actions.run(
+ mnemonic = "GenFSSpecImage",
+ progress_message = "Generating a fsspec based image: {}".format(output_file.short_path),
+ outputs = [output_file],
+ inputs = [fs_spec] + inputs + extra_specs,
+ tools = [tool],
+ executable = tool,
+ arguments = ["-out", output_file.path, fs_spec.path] + [s.path for s in extra_specs],
+ )
+ return
diff --git a/osbase/build/fwprune/def.bzl b/osbase/build/fwprune/def.bzl
index 4633c93..e05d237 100644
--- a/osbase/build/fwprune/def.bzl
+++ b/osbase/build/fwprune/def.bzl
@@ -1,4 +1,4 @@
-load("//osbase/build:def.bzl", "FSSpecInfo")
+load("//osbase/build/fsspec:def.bzl", "FSSpecInfo")
def _fsspec_linux_firmware(ctx):
fsspec_out = ctx.actions.declare_file(ctx.label.name + ".prototxt")
diff --git a/osbase/build/mkcpio/def.bzl b/osbase/build/mkcpio/def.bzl
new file mode 100644
index 0000000..402314e
--- /dev/null
+++ b/osbase/build/mkcpio/def.bzl
@@ -0,0 +1,65 @@
+load("//osbase/build:def.bzl", "build_pure_transition", "build_static_transition")
+load("//osbase/build/fsspec:def.bzl", "FSSpecInfo", "fsspec_core_impl")
+
+def _node_initramfs_impl(ctx):
+ initramfs_name = ctx.label.name + ".cpio.zst"
+ initramfs = ctx.actions.declare_file(initramfs_name)
+
+ fsspec_core_impl(ctx, ctx.executable._mkcpio, initramfs)
+
+ # TODO(q3k): Document why this is needed
+ return [DefaultInfo(runfiles = ctx.runfiles(files = [initramfs]), files = depset([initramfs]))]
+
+node_initramfs = rule(
+ implementation = _node_initramfs_impl,
+ doc = """
+ Build a node initramfs. The initramfs will contain a basic /dev directory and all the files specified by the
+ `files` attribute. Executable files will have their permissions set to 0755, non-executable files will have
+ their permissions set to 0444. All parent directories will be created with 0755 permissions.
+ """,
+ attrs = {
+ "files": attr.string_keyed_label_dict(
+ mandatory = True,
+ allow_files = True,
+ doc = """
+ Dictionary of Labels to String, placing a given Label's output file in the initramfs at the location
+ specified by the String value. The specified labels must only have a single output.
+ """,
+ # Attach pure transition to ensure all binaries added to the initramfs are pure/static binaries.
+ cfg = build_pure_transition,
+ ),
+ "files_cc": attr.string_keyed_label_dict(
+ allow_files = True,
+ doc = """
+ Special case of 'files' for compilation targets that need to be built with the musl toolchain like
+ go_binary targets which need cgo or cc_binary targets.
+ """,
+ # Attach static transition to all files_cc inputs to ensure they are built with musl and static.
+ cfg = build_static_transition,
+ ),
+ "symlinks": attr.string_dict(
+ default = {},
+ doc = """
+ Symbolic links to create. Similar format as in files and files_cc, so the target of the symlink is the
+ key and the value of it is the location of the symlink itself. Only raw strings are allowed as targets,
+ labels are not permitted. Include the file using files or files_cc, then symlink to its location.
+ """,
+ ),
+ "fsspecs": attr.label_list(
+ default = [],
+ doc = """
+ List of file system specs (osbase.build.fsspec.FSSpec) to also include in the resulting image.
+ These will be merged with all other given attributes.
+ """,
+ providers = [FSSpecInfo],
+ allow_files = True,
+ ),
+
+ # Tool
+ "_mkcpio": attr.label(
+ default = Label("//osbase/build/mkcpio"),
+ executable = True,
+ cfg = "exec",
+ ),
+ },
+)
diff --git a/osbase/build/mkerofs/def.bzl b/osbase/build/mkerofs/def.bzl
new file mode 100644
index 0000000..45f00d8
--- /dev/null
+++ b/osbase/build/mkerofs/def.bzl
@@ -0,0 +1,64 @@
+load("//osbase/build:def.bzl", "build_pure_transition", "build_static_transition")
+load("//osbase/build/fsspec:def.bzl", "FSSpecInfo", "fsspec_core_impl")
+
+def _erofs_image_impl(ctx):
+ fs_name = ctx.label.name + ".img"
+ fs_out = ctx.actions.declare_file(fs_name)
+
+ fsspec_core_impl(ctx, ctx.executable._mkerofs, fs_out)
+
+ return [DefaultInfo(files = depset([fs_out]))]
+
+erofs_image = rule(
+ implementation = _erofs_image_impl,
+ doc = """
+ Build an EROFS. All files specified in files, files_cc and all specified symlinks will be contained.
+ Executable files will have their permissions set to 0555, non-executable files will have
+ their permissions set to 0444. All parent directories will be created with 0555 permissions.
+ """,
+ attrs = {
+ "files": attr.string_keyed_label_dict(
+ mandatory = True,
+ allow_files = True,
+ doc = """
+ Dictionary of Labels to String, placing a given Label's output file in the EROFS at the location
+ specified by the String value. The specified labels must only have a single output.
+ """,
+ # Attach pure transition to ensure all binaries added to the initramfs are pure/static binaries.
+ cfg = build_pure_transition,
+ ),
+ "files_cc": attr.string_keyed_label_dict(
+ allow_files = True,
+ doc = """
+ Special case of 'files' for compilation targets that need to be built with the musl toolchain like
+ go_binary targets which need cgo or cc_binary targets.
+ """,
+ # Attach static transition to all files_cc inputs to ensure they are built with musl and static.
+ cfg = build_static_transition,
+ ),
+ "symlinks": attr.string_dict(
+ default = {},
+ doc = """
+ Symbolic links to create. Similar format as in files and files_cc, so the target of the symlink is the
+ key and the value of it is the location of the symlink itself. Only raw strings are allowed as targets,
+ labels are not permitted. Include the file using files or files_cc, then symlink to its location.
+ """,
+ ),
+ "fsspecs": attr.label_list(
+ default = [],
+ doc = """
+ List of file system specs (osbase.build.fsspec.FSSpec) to also include in the resulting image.
+ These will be merged with all other given attributes.
+ """,
+ providers = [FSSpecInfo],
+ allow_files = True,
+ ),
+
+ # Tools, implicit dependencies.
+ "_mkerofs": attr.label(
+ default = Label("//osbase/build/mkerofs"),
+ executable = True,
+ cfg = "exec",
+ ),
+ },
+)
diff --git a/osbase/build/efi.bzl b/osbase/build/mkpayload/def.bzl
similarity index 98%
rename from osbase/build/efi.bzl
rename to osbase/build/mkpayload/def.bzl
index 54b43a6..fe7cf74 100644
--- a/osbase/build/efi.bzl
+++ b/osbase/build/mkpayload/def.bzl
@@ -4,7 +4,7 @@
"""
load("//build/toolchain/llvm-efi:transition.bzl", "build_efi_transition")
-load("//osbase/build:def.bzl", "VerityInfo")
+load("//osbase/build/mkverity:def.bzl", "VerityInfo")
def _efi_unified_kernel_image_impl(ctx):
# Find the dependency paths to be passed to mkpayload.
diff --git a/osbase/build/mkverity/def.bzl b/osbase/build/mkverity/def.bzl
new file mode 100644
index 0000000..417c883
--- /dev/null
+++ b/osbase/build/mkverity/def.bzl
@@ -0,0 +1,72 @@
+# VerityInfo is emitted by verity_image, and contains a file enclosing a
+# singular dm-verity target table.
+VerityInfo = provider(
+ "Information necessary to mount a single dm-verity target.",
+ fields = {
+ "table": "A file containing the dm-verity target table. See: https://www.kernel.org/doc/html/latest/admin-guide/device-mapper/verity.html",
+ },
+)
+
+def _verity_image_impl(ctx):
+ """
+ Create a new file containing the source image data together with the Verity
+ metadata appended to it, and provide an associated DeviceMapper Verity target
+ table in a separate file, through VerityInfo provider.
+ """
+
+ # Run mkverity.
+ image = ctx.actions.declare_file(ctx.attr.name + ".img")
+ table = ctx.actions.declare_file(ctx.attr.name + ".dmt")
+ ctx.actions.run(
+ mnemonic = "GenVerityImage",
+ progress_message = "Generating a dm-verity image: {}".format(image.short_path),
+ inputs = [ctx.file.source],
+ outputs = [
+ image,
+ table,
+ ],
+ executable = ctx.file._mkverity,
+ arguments = [
+ "-input=" + ctx.file.source.path,
+ "-output=" + image.path,
+ "-table=" + table.path,
+ "-data_alias=" + ctx.attr.rootfs_partlabel,
+ "-hash_alias=" + ctx.attr.rootfs_partlabel,
+ ],
+ )
+
+ return [
+ DefaultInfo(
+ files = depset([image]),
+ runfiles = ctx.runfiles(files = [image]),
+ ),
+ VerityInfo(
+ table = table,
+ ),
+ ]
+
+verity_image = rule(
+ implementation = _verity_image_impl,
+ doc = """
+ Build a dm-verity target image by appending Verity metadata to the source
+ image. A corresponding dm-verity target table will be made available
+ through VerityInfo provider.
+ """,
+ attrs = {
+ "source": attr.label(
+ doc = "A source image.",
+ allow_single_file = True,
+ ),
+ "rootfs_partlabel": attr.string(
+ doc = "GPT partition label of the rootfs to be used with dm-mod.create.",
+ default = "PARTLABEL=METROPOLIS-SYSTEM-X",
+ ),
+ "_mkverity": attr.label(
+ doc = "The mkverity executable needed to generate the image.",
+ default = "//osbase/build/mkverity",
+ allow_single_file = True,
+ executable = True,
+ cfg = "exec",
+ ),
+ },
+)
diff --git a/osbase/test/ktest/ktest.bzl b/osbase/test/ktest/ktest.bzl
index 37efd30..60a90a5 100644
--- a/osbase/test/ktest/ktest.bzl
+++ b/osbase/test/ktest/ktest.bzl
@@ -18,7 +18,8 @@
Ktest provides a macro to run tests under a normal Metropolis node kernel
"""
-load("//osbase/build:def.bzl", "FSSpecInfo", "build_pure_transition", "build_static_transition", "fsspec_core_impl")
+load("//osbase/build:def.bzl", "build_pure_transition", "build_static_transition")
+load("//osbase/build/fsspec:def.bzl", "FSSpecInfo", "fsspec_core_impl")
_KTEST_SCRIPT = """
#!/usr/bin/env bash