Practical Bazel: path or short_path?
Practical Bazel bazel
Published: 2020-10-22
Practical Bazel: path or short_path?

When writing custom Bazel rules, you spend a lot of time either reading or writing Bazel File objects.

File objects have two properties for accessing the underlying file path: File.path and File.short_path. When writing custom rules, I often chose one of the two properties at random, and switched to the other if it didn’t work right.

I wrote some simple custom rules to test the various combination of rule types and file types to determine when I should use path or short_path. The custom rules used bash script templates that were populated with file paths, such as:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# my_build.bzl
def _impl(ctx):
    exe = ctx.actions.declare_file("{}-build.sh".format(ctx.label.name))
    ctx.actions.write(
        output = exe,
        content = """#!/bin/bash

set -euo pipefail
set -x

cp {src} {out}
""".format(
            src = ctx.file.src.path, # .short_path breaks for generated files
            out = ctx.outputs.out.path, # .short_path doesn't work
        ),
        is_executable = True,
    )

    ctx.actions.run(
        inputs = ctx.files.src,
        outputs = [ctx.outputs.out],
        executable = exe,
    )

my_build = rule(
    implementation = _impl,
    attrs = {
        "src": attr.label(mandatory = True, allow_single_file = True),
        "out": attr.output(mandatory = True),
    },
)

Here are the results of the test:

File Type Build Rule Test Rule Executable Rule
Input file, on-disk Either path or short_path works Either path or short_path works Either path or short_path works
Input file, generated path short_path short_path
Output file path N/A N/A

The above table can be simplified to the following rules:

Bazel Rule Type Always Use
build path
test short_path
executable short_path

My test code can be found at at https://github.com/sengelha/practical_bazel_examples/tree/master/path_or_short_path