Search code examples
bazelcustom-build

Create and read temporary file with Bazel


I am trying to setup my custom build system for TensorFlow using Bazel. I need to create a temporary file during the configure step that I will use as a cache during the building step. I was able to create it in my .bzl file with:

repository_ctx.file(filename)

And after a configure I can see that it inside the folder:

$HOME/.cache/bazel/_bazel_$USERNAME/%MD5%/external/%repository_name%

where repository_name is actually repository_ctx.name

But I can't access to this path from my .tpl script during build time. I wanted to send it from the .bzl script via the substitutions of repository_ctx.template but even here I haven't found how to find this path!

It doesn't look like I can access this folder using the symbolic links like bazel-out or bazel-genfiles (which sounds very promising but is not...). I also wasn't able to create the file outside of this folder.

It's a very simple problem and I just cannot believe that there is no other way than to hardcode the path or to find it...


Solution

  • I'd guess the problem is that you're not exposing the file in the repo's BUILD file for your build to use it. You need to do something like:

    repository_ctx.file('whatever')
    repository_ctx.file('BUILD', 'exports_files(["whatever"])')
    

    Then you can use @repository_name//:whatever in any other BUILD file.

    exports_files is used to let packages depend on source files from other packages.

    Then, in your .bzl file you're loading during build time, add the file as an attribute, e.g.,

    attrs = {
        '_my_external_src' : attr.label(
            default = Label('@my_repository//:whatever'),
            allow_single_file = True,
        ),
    },
    

    Then, in the rule implementation, you can access it through the context:

    def _impl(ctx):
        print(ctx.file._my_external_src.path)
    

    .path gets the file's path.