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/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