Search code examples
bazelbazel-rules

how to create a bazel rule to get a path as a flag from commandline and create a filegroup for all the files in that path?


Update: I modified the situation so that there is a BUILD.bazel file present in a given directory. The question is how to tell a certain target to depend on a dynamically selected target the path of which is given by a flag.


Seems pretty straightforward but after spending a whole day, I'm ready to throw the towel. Any help is greatly appreciated.

I want to get a path (or a dir name) when invoking Bazel build command, and include all the files in that path as a filegroup.

I'm trying the following code (not sure even if I'm on the right track or not):

def _impl(ctx):
    my_setting_value = ctx.build_setting_value
    all_files = native.glob(["<path to>/" + my_setting_value + "/**"])

    ctx.actions.declare_file_group(
        name = ctx.label.name + "_group",
        srcs = all_files,
    )

custom_filegroup = rule(
    implementation = _impl,
    build_setting = config.string(flag = True),

    outputs = {
        "my_custom_filegroup": "%{name}_group",
    },
)

Then, in my build file I have this target: custom_filegroup(name = "my_files", build_setting_default="")

And I'm adding ":my_files.my_custom_filegroup" as a dependency in another target. When I try to build the target using bazel build //<path to>:my_files, I keep getting an error related to native.glob as follows:

"Error in glob: 'native.glob' can only be called during the loading phase"


Solution

  • Just for others benefit, the answer to this question is easier than my complex solution here. There is a built-in flag in bazel called label_flag which solves the problem I've been trying to solve. Here is a sample solution:

    In //workspace/just/sample/path/BUILD.bazel, define a label_flag as follows:

    label_flag(
        name = "my_label_flag",
        build_setting_default="//workspace/some/default/path:some_build_target"
    )
    

    The in the target that needs customizable dependency, add this label_flag as dependency as follows:

    deps = ["//workspace/just/sample/path:my_label_flag"]
    

    Then when running bazel build, you can run it as follows:

    bazel build workspace/path/to/your/target --//workspace/just/sample/path:my_label_flag="GIVE_YOUR_CUSTOM_TARGET_HERE e.g //workspace/some/custom/path:custom_target"
    

    This way you can give your custom target that can be changed on command line.