Search code examples
bazelbazel-rules

Where is the executable files which is generated in a rule file in bazel?


I made a rule file contains two actions and here is a simple explanation about actions.

  • First action: create a script. This script is come from a template. This script name is create_a_file.sh in this test
  • Second action: execute a script first action made. As a result of this action, A new file is created. This script name is print_message.sh in this test.

I got error messages when I execute bazel run as follows.

$> bazel run //rules/test_rule/examples:gen_script --subcommands --verbose_failures                                                                                                                                      ✔  16:23:42 
Starting local Bazel server and connecting to it...
INFO: Analyzed target //rules/test_rule/examples:gen_script (5 packages loaded, 7 targets configured).
INFO: Found 1 target...
SUBCOMMAND: # //rules/test_rule/examples:gen_script [action 'Action rules/test_rule/examples/print_message.sh', configuration: 6167a43bee81d7c4ceebdf8986e0027b728c609e76e2c99eb3032efb76afa9e5, execution platform: @local_config_platform//:host]
(cd /home/ryan/.cache/bazel/_bazel_ryan/7935e4c8c361f40ea6fa5552c32b5ad7/execroot/ruletest_0 && \
  exec env - \
  bazel-out/k8-fastbuild/bin/rules/test_rule/examples/create_a_file.sh)
# Configuration: 6167a43bee81d7c4ceebdf8986e0027b728c609e76e2c99eb3032efb76afa9e5
# Execution platform: @local_config_platform//:host
ERROR: /home/.../ruletest_0/rules/test_rule/examples/BUILD:4:11: output 'rules/test_rule/examples/print_message.sh' was not created
ERROR: /home/.../ruletest_0/rules/test_rule/examples/BUILD:4:11: Action rules/test_rule/examples/print_message.sh failed: not all outputs were created or valid
Target //rules/test_rule/examples:gen_script failed to build
INFO: Elapsed time: 1.921s, Critical Path: 0.04s
INFO: 5 processes: 4 internal, 1 linux-sandbox.
FAILED: Build did NOT complete successfully
FAILED: Build did NOT complete successfully

It seems that print_message.sh file was created in an unexpected location and seems to have been deleted when the bazel run were completed. Because when I check the location where the result of the bazel action is stored, create_a_file.sh's symlink is normal, while print_message.sh's symlink is incorrect.

Would you let me know how I can fix this?

This is bazel action result stored location

$> pwd
/home/.../ruletest_0/bazel-out/k8-fastbuild/bin/rules/test_rule/examples/print_message.sh.runfiles/ruletest_0/rules/test_rule/examples/print_message.sh.runfiles/ruletest_0/rules/test_rule/examples

$> ll
create_a_file.sh -> /home/.../.cache/bazel/_bazel_.../7935e4c8c361f40ea6fa5552c32b5ad7/execroot/ruletest_0/bazel-out/k8-fastbuild/bin/rules/test_rule/examples/create_a_file.sh // correct symlink
print_message.sh -> /home/.../.cache/bazel/_bazel_.../7935e4c8c361f40ea6fa5552c32b5ad7/execroot/ruletest_0/bazel-out/k8-fastbuild/bin/rules/test_rule/examples/print_message.sh // incorrect symlink. print_message.sh file is nowhere

This is my rule file

# this rule creates a file
def _gen_script_impl(ctx):

    scr_name = ctx.attr._scrname
    file_name = ctx.attr._filename
    file_contents = ctx.attr._filecontents
    script_template = ctx.file._script_template

    file_creation_script = ctx.actions.declare_file(scr_name)

    ctx.actions.expand_template(
        template = script_template,
        output = file_creation_script,
        substitutions = {
            "{FILE_NAME}": file_name,
            "{FILE_CONTENTS}": file_contents,
        },
        is_executable = True,
    )

    created_file = ctx.actions.declare_file(file_name)
    ctx.actions.run(
        outputs = [created_file],
        executable = file_creation_script,
    )

    allfiles = depset([file_creation_script] + [created_file])
    runfiles = ctx.runfiles(files = [file_creation_script] + [created_file])

    return [
        DefaultInfo(
            executable = created_file,
            files = allfiles,
            runfiles = runfiles,
        ),
    ]

gen_script = rule(
    implementation = _gen_script_impl,
    attrs = {
        "_scrname": attr.string(
            default = "create_a_file.sh",
        ),
        "_filename": attr.string(
            default = "print_message.sh",
        ),
        "_filecontents": attr.string(
            default = "hello?",
        ),
        "_script_template": attr.label(
            allow_single_file = True,
            default = Label("@ruletest_0//rules/test_rule/script_template:create_a_file.sh.template"),
        )
    },
    executable = True,
)

This is a script template file

#!/usr/bin/zsh

# $1: file name
# $2: file content
function create_a_file {
    echo "echo $2" > $1
}

create_a_file "{FILE_NAME}" "{FILE_CONTENTS}"

Solution

  • You should generate the file at the path Bazel specifies, which is created_file.path. Move the line declaring created_file up before the ctx.actions.expand_template, and replace "{FILE_NAME}": file_name, with "{FILE_NAME}": created_file.path,.