--- /dev/null
+load("@bazel_skylib//lib:paths.bzl", "paths")
+
+def _sqfs_package_impl(ctx):
+ """Implementation rule for sqfs_package."""
+ output = ctx.actions.declare_file(ctx.label.name)
+
+ # Build pseudo-file specifications for mksquashfs -p entries.
+ # Each binary becomes bin/<basename> inside the squashfs image.
+ # Symlinks are resolved to their targets so mksquashfs can read them.
+ pseudo_files = [
+ "bin d 0755 0 0",
+ ]
+ all_files = depset()
+ for binary in ctx.attr.binaries:
+ file_list = binary.files.to_list()
+ file = file_list[0]
+ all_files = depset(transitive = [all_files, binary.files])
+ basename = paths.basename(file.path)
+ if basename.endswith(".symlink"):
+ # Resolve the symlink target; use absolute path so it works
+ # inside mksquashfs's chroot.
+ pseudo_files.append(
+ "bin/{} f 0755 0 0 cat $(readlink -f \"{}\")".format(
+ basename,
+ file.path,
+ ),
+ )
+ else:
+ pseudo_files.append(
+ "bin/{} f 0755 0 0 cat {}".format(
+ basename,
+ file.path,
+ ),
+ )
+
+ ctx.actions.run_shell(
+ outputs = [output],
+ inputs = all_files,
+ tools = depset([ctx.executable.mksquashfs]),
+ command = """
+ export SOURCE_DATE_EPOCH=665374440; \
+ mkdir /tmp/emptydir.$$$$; \
+ exec {mksquashfs} /tmp/emptydir.$$$$ $@ \
+ -force-uid 0 -force-gid 0 -root-uid 0 -root-gid 0 \
+ -comp zstd -exit-on-error -no-recovery \
+ -p "{pseudo}"
+ """.format(
+ mksquashfs = ctx.executable.mksquashfs.path,
+ pseudo = '" -p "'.join(pseudo_files),
+ ),
+ arguments = [output.path],
+ )
+
+ return [
+ DefaultInfo(files = depset([output])),
+ ]
+
+_sqfs_package = rule(
+ implementation = _sqfs_package_impl,
+ attrs = {
+ "binaries": attr.label_list(
+ doc = "Binaries to include in the squashfs image",
+ mandatory = True,
+ cfg = "exec",
+ ),
+ "mksquashfs": attr.label(
+ doc = "mksquashfs executable (from @squashfs-tools//:mksquashfs)",
+ executable = True,
+ cfg = "exec",
+ default = Label("@squashfs-tools//:mksquashfs"),
+ ),
+ },
+)
+
+def sqfs_package(
+ name, # type: str
+ binaries, # type: list[label]
+):
+ """Create a SquashFS image containing the given binaries.
+
+ Args:
+ name: Target name; must end in `.sqfs`. The output file will be
+ named exactly `<name>` (e.g. `echo-server.sqfs`).
+ binaries: List of binary labels to include in the squashfs image.
+ Each binary is placed at `bin/<basename>` inside the image.
+ """
+ if name[-5:] != ".sqfs":
+ fail("name must end in .sqfs: {}".format(name))
+
+ _sqfs_package(
+ name = name,
+ binaries = binaries,
+ mksquashfs = "@squashfs-tools//:mksquashfs",
+ visibility = ["//visibility:public"],
+ )