Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a directory structure in bazel

Tags:

bazel

skylark

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.

like image 751
GGhe Avatar asked Feb 14 '19 00:02

GGhe


People also ask

How do I create a workspace in Bazel?

To designate a directory as a Bazel workspace, create an empty file named WORKSPACE in that directory. When Bazel builds the project, all inputs and dependencies must be in the same workspace.

Where do Bazel build files go?

The Bazel user's build state is located beneath outputRoot/_bazel_$USER . This is called the outputUserRoot directory. Beneath the outputUserRoot directory there is an install directory, and in it is an installBase directory whose name is the MD5 hash of the Bazel installation manifest.

What is Bazelrc file?

Bazel builds software from source code organized in a directory called a workspace. Source files in the workspace are organized in a nested hierarchy of packages, where each package is a directory that contains a set of related source files and one BUILD file.


2 Answers

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.

like image 104
GGhe Avatar answered Oct 06 '22 14:10

GGhe


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",
    ],
    # ...
)
like image 38
Gergely Fábián Avatar answered Oct 06 '22 14:10

Gergely Fábián