0.3.6 filegroup Rule
recommendedfilegroup() is the built-in rule for saying "these files belong together." It takes an explicit file list, or the result of 0.3.4 Globs, and gives that collection a target label other rules can depend on.1,2 glob() answers which files match, while filegroup turns the answer into a reusable name in the package.
filegroup(
name = "config_files",
srcs = glob(["configs/*.yaml"]),
)
The config_files example above is the common pattern.1,2 The wildcard stays local to this package, but consumers only need the label :config_files. The texts target in glob-retraction follows the same idea: the file selection lives inside the filegroup, and downstream rules can depend on the named target instead of repeating the wildcard.
Why Name The Set?
Raw file lists are fine when only one target uses them. A filegroup becomes useful when the same collection needs to travel to multiple places, especially through data from 0.3.3 Attributes & Semantic Roles.1 The recommended pattern for multi-file runtime inputs is to enumerate them and then wrap them in filegroup() so a test or binary can depend on one label instead of a directory label.1
That matters because directory labels are a convenience with real trade-offs. Bazel can track explicit files and glob() matches, but a bare directory in data hides the actual members of the input set and can miss edits to individual files for rebuild purposes.1 A filegroup keeps the dependency explicit without forcing every consumer to repeat the same list.
filegroup vs exports_files()
filegroup and 0.2.7 exports_files() solve different problems. exports_files() makes specific source files in the current package visible to other packages.3,4 If you omit its visibility, those exported files become visible to every package.3
Use exports_files() when another package truly needs a raw file label such as //pkg:schema.sql.4 Use filegroup() when the package API is a collection: configs, fixtures, templates, or some other set that should move through the graph as one named target.1,2 In practice, exports_files() exposes files one by one. filegroup() gives the collection its own stable label.
Because filegroup() is a rule, its srcs can also point at another rule's generated outputs. The filegroup-generated-output snippet proves the distinction: exports_files() cannot change generated-file visibility, while a filegroup can name a generated file set for a downstream package.
A Small Rule With Downstream Effects
Because filegroup is a rule, other targets can refer to it with a normal label instead of repeating the underlying file list.1,2 It often appears in data for runtime files now and shows up again when 1.1.2 bazel run & Runfiles introduces runfiles later. The BUILD file can name meaningful file sets instead of scattering the same wildcard or file list across multiple consumers.
Reach for filegroup() when a file list stops being a one-off implementation detail and becomes a reusable part of the package interface. glob() chooses the files, filegroup gives that set a label, and exports_files() exposes individual raw files directly.
Check your understanding · 2 questions
1.When should you use filegroup() instead of exports_files() for a package API?
Select one answer
2.True or false: filegroup() usage and behavior.
Choose True or False for each sentence
Footnotes
-
Dependencies — warns against directory labels for multi-file runtime inputs, recommends explicit enumeration or
glob(), and showsfilegroup()as the reusable wrapper ↩1 ↩2 ↩3 ↩4 ↩5 ↩6 ↩7 -
Sponsored Session: Bazel Management for Developer Productivity Experts - Instructor: Billy Autrey — identifies
filegroupas a built-in rule and shows the canonicalconfig_files = glob(["configs/*.yaml"])pattern ↩1 ↩2 ↩3 ↩4 -
BUILD files —
exports_files()exports files from the current package and makes them public ifvisibilityis omitted ↩1 ↩2 -
Bazel Training 101 (Part 9): Packages, Rules, Targets, and Labels — source files are owned by their package and need
exports_files()for cross-package visibility ↩1 ↩2