8

I want to create the following structure in bazel.

dir1
   |_ file1
   |_ file2
   |_ dir2
         |_file3

Creating a specific structure doesn't seem trivial. I'm hoping there's a simple and reusable rule. Something like:

makedir(
  name = "dir1",
  path = "dir1",
)

makedir(
  name = "dir2",
  path = "dir1/dir2",
  deps = [":dir1"],
)

What I've tried:

  • I could create a macro with a python script, but want something cleaner.
  • I tried creating a genrule with mkdir -p path/to/directoy which didn't work

The use case is that I want to create a squashfs using bazel.

It's important to note that Bazel provides some packaging functions.

To create a squashfs, the command requires a directory structure populated with artifacts.

Braiam
  • 1
  • 11
  • 47
  • 78
GGhe
  • 663
  • 5
  • 17
  • Do you mean creating bazel packages? (directories that have BUILD files in them?) – Natan Feb 16 '19 at 20:14
  • No, I mean creating a directory structure that has artifacts inside. The use case is that I want to create a squashfs and to do that, it needs a populated directory. – GGhe Feb 19 '19 at 21:11
  • Do you need this to be on-the-fly, maybe for tests?. Or is this a one time thing? – Natan Feb 20 '19 at 06:33
  • For continuous integration, they need to be on-the-fly. – GGhe Feb 20 '19 at 21:34

3 Answers3

3

In my case, I want to create a directory structure and run mksquashfs to produce a squashfs file.

To accomplish this, I ended up modifying the basic example from bazel's docs on packaging.

load("@bazel_tools//tools/build_defs/pkg:pkg.bzl", "pkg_tar")

genrule(
    name = "file1",
    outs = ["file1.txt"],
    cmd = "echo exampleText > $@",
)

pkg_tar(
    name = "dir1",
    strip_prefix = ".",
    package_dir = "/usr/bin",
    srcs = [":file1"],
    mode = "0755",
)

pkg_tar(
    name = "dir2",
    strip_prefix = ".",
    package_dir = "/usr/share",
    srcs = ["//main:file2.txt", "//main:file3.txt"],
    mode = "0644",
)

pkg_tar(
    name = "pkg",
    extension = "tar.gz",
    deps = [
        ":dir1",
        ":dir2",
    ],
)

If there's an easier way to create a tar or directory structure without the need for intermediate tars, I'll make that top answer.

GGhe
  • 663
  • 5
  • 17
1

You could create such a Bazel macro, that uses genrule:

def mkdir(name, out_dir, marker_file = "marker"):
    """Create an empty directory that you can use as an input in another rule

    This will technically create an empty marker file in that directory to avoid Bazel warnings.
    You should depend on this marker file.
    """
    path = "%s/%s" % (out_dir, marker_file)
    native.genrule(
        name = name,
        outs = [path],
        cmd = """mkdir -p $$(dirname $(location :%s)) && touch $(location :%s)""" % (path, path),
    )

Then you can use the outputs generated by this macro in a pkg_tar definition:

mkdir(
    name = "generate_a_dir",
    out_dir = "my_dir",
)

pkg_tar(
    name = "package",
    srcs = [
        # ...
        ":generate_a_dir",
    ],
    # ...
)
0

You can always create a genrule target or a shell_binary target that will execute bash command or a shell script (respectively) that creates these directories.

with genrule you can use bazel's $(location) that will make sure that the dir structure you create will be under an output path that is inside bazel's sandbox environment. The genrule example shows how to use it exactly.

Here you can find more details on predefined output paths.

Natan
  • 1,944
  • 1
  • 11
  • 16
  • Please provide an example of how to accomplish the scenario above using genrule/shell_binary and I'll award your answer as the correct answer. – GGhe Feb 21 '19 at 21:59