6

I want a Bazel rule that is able to build multiple targets at once. So basically something like this:

build_all(
  name = "build_all",
  targets = [
    "//services/service1:build",
    "//services/service2:build",
    "//services/service3:build",
  ]
)

So I would just run

bazel build //:build_all

to build all my services with one simple command (and the same for testing). But I couldn't find any current solutions.

Is there a way to achieve this?

Florian Ludewig
  • 4,338
  • 11
  • 71
  • 137
  • I googled and found this. Maybe it helps: https://github.com/atlassian/bazel-tools/tree/master/multirun – Héctor Feb 01 '20 at 21:40
  • Yeah, I've tried it a few minutes ago, but it seems only to work for "runnable" targets. Tests and builds gave me an error. But maybe you can prove me wrong :) – Florian Ludewig Feb 01 '20 at 21:45
  • You should set your services as dependencies of build_all. Generally, "data" is the most flexible attribute for doing that. But also know that bazel build //... will build everything and bazel build //services/... will build everything under services. – Aaron Bentley Feb 01 '20 at 22:03

5 Answers5

13

It would appear that filegroup would be a ready made rule that could be abused for the purpose:

filegroup(
  name = "build_all",
  srcs = [
    "//services/service1:build",
    "//services/service2:build",
    "//services/service3:build",
  ]
)

It otherwise allows you to give a collective name to bunch of files (labels) to be passed conveniently along, but seems to work just as well as a summary target to use on the command line.

Ondrej K.
  • 8,841
  • 11
  • 24
  • 39
  • This does not work for me when py_binary rules are listed in srcs. It will silently not rebuild them when their sources are updated. So then I need to go back and call bazel build directly on the py_binary rules. – LolPython Jun 08 '21 at 20:54
  • What if I have to pass arguments for the build targets? ex: "bazel build //services/service1:build -- -arg1 -arg2" – Starfish Mar 29 '22 at 18:24
3

If you only want a subset of the build targets the other answers are probably better, but you could also try bazel build :all and bazel test :all

gph
  • 1,045
  • 8
  • 25
2

Because I was trying to deploy multiple Kubernetes configurations I ended up using Multi-Object Actions for rules_k8s which then looks like:

load("@io_bazel_rules_k8s//k8s:objects.bzl", "k8s_objects")

k8s_objects(
   name = "deployments",
   objects = [
      "//services/service1:build",
      "//services/service2:build",
      "//services/service3:build",
   ]
)
Florian Ludewig
  • 4,338
  • 11
  • 71
  • 137
1

You can also use --build_tag_filters to selectively build multiple targets with a given tags.

EDIT: --build_tag_filters is using OR logic. If you want to build target that satisfy multiple tags, I would suggest you to query it first, and then build the resulting target.

e.g.

QUERY="attr(tags, 'tag1', attr(tags, 'tag2', ...))"
BUILD_TARGETS=$(bazel query "$QUERY")
bazel build "$BUILD_TARGETS"
dieend
  • 2,231
  • 1
  • 24
  • 29
0

The suggestion to use a file group rule as a build-in rule to collect a bunch of dependencies works well if the dependencies are single files (like a cc_binary), but will not trigger creation and collection of auxiliary runfiles (like the labels under "data" in a py_binary) needed for some types of targets.

If you do want to build multiple targets at once, including their runfiles, the sh_binary built in rule with a simple no-opt script is also quite flexible, and you can specify an arbitrary list of targets in its data attribute. These targets will be considered runnable inputs to the sh_binary, and thus will trigger creation of the indirect targets themselves as well as all of their supplementary runtime data.