xref: /aosp_15_r20/external/bazel-skylib/README.md (revision bcb5dc7965af6ee42bf2f21341a2ec00233a8c8a)
1*bcb5dc79SHONG Yifan# Skylib
2*bcb5dc79SHONG Yifan
3*bcb5dc79SHONG Yifan[![Build status](https://badge.buildkite.com/921dc61e2d3a350ec40efb291914360c0bfa9b6196fa357420.svg?branch=main)](https://buildkite.com/bazel/bazel-skylib)
4*bcb5dc79SHONG Yifan
5*bcb5dc79SHONG YifanSkylib is a library of Starlark functions for manipulating collections, file paths,
6*bcb5dc79SHONG Yifanand various other data types in the domain of Bazel build rules.
7*bcb5dc79SHONG Yifan
8*bcb5dc79SHONG YifanEach of the `.bzl` files in the `lib` directory defines a "module"—a
9*bcb5dc79SHONG Yifan`struct` that contains a set of related functions and/or other symbols that can
10*bcb5dc79SHONG Yifanbe loaded as a single unit, for convenience.
11*bcb5dc79SHONG Yifan
12*bcb5dc79SHONG YifanSkylib also provides build rules under the `rules` directory.
13*bcb5dc79SHONG Yifan
14*bcb5dc79SHONG Yifan## Getting Started
15*bcb5dc79SHONG Yifan
16*bcb5dc79SHONG Yifan### `WORKSPACE` file
17*bcb5dc79SHONG Yifan
18*bcb5dc79SHONG YifanSee the **WORKSPACE setup** section [for the current release](https://github.com/bazelbuild/bazel-skylib/releases).
19*bcb5dc79SHONG Yifan
20*bcb5dc79SHONG YifanIf you want to use `lib/unittest.bzl` from Skylib versions released in or after
21*bcb5dc79SHONG YifanDecember 2018, then you also should add to the `WORKSPACE` file:
22*bcb5dc79SHONG Yifan
23*bcb5dc79SHONG Yifan```python
24*bcb5dc79SHONG Yifanload("@bazel_skylib//:workspace.bzl", "bazel_skylib_workspace")
25*bcb5dc79SHONG Yifan
26*bcb5dc79SHONG Yifanbazel_skylib_workspace()
27*bcb5dc79SHONG Yifan```
28*bcb5dc79SHONG Yifan
29*bcb5dc79SHONG Yifan### `BUILD` and `*.bzl` files
30*bcb5dc79SHONG Yifan
31*bcb5dc79SHONG YifanThen, in the `BUILD` and/or `*.bzl` files in your own workspace, you can load
32*bcb5dc79SHONG Yifanthe modules (listed [below](#list-of-modules)) and access the symbols by
33*bcb5dc79SHONG Yifandotting into those structs:
34*bcb5dc79SHONG Yifan
35*bcb5dc79SHONG Yifan```python
36*bcb5dc79SHONG Yifanload("@bazel_skylib//lib:paths.bzl", "paths")
37*bcb5dc79SHONG Yifanload("@bazel_skylib//lib:shell.bzl", "shell")
38*bcb5dc79SHONG Yifan
39*bcb5dc79SHONG Yifanp = paths.basename("foo.bar")
40*bcb5dc79SHONG Yifans = shell.quote(p)
41*bcb5dc79SHONG Yifan```
42*bcb5dc79SHONG Yifan
43*bcb5dc79SHONG Yifan## List of modules (in lib/)
44*bcb5dc79SHONG Yifan
45*bcb5dc79SHONG Yifan* [collections](docs/collections_doc.md)
46*bcb5dc79SHONG Yifan* [dicts](docs/dicts_doc.md)
47*bcb5dc79SHONG Yifan* [partial](docs/partial_doc.md)
48*bcb5dc79SHONG Yifan* [paths](docs/paths_doc.md)
49*bcb5dc79SHONG Yifan* [selects](docs/selects_doc.md)
50*bcb5dc79SHONG Yifan* [sets](lib/sets.bzl) - _deprecated_, use `new_sets`
51*bcb5dc79SHONG Yifan* [modules](docs/modules_doc.md)
52*bcb5dc79SHONG Yifan* [new_sets](docs/new_sets_doc.md)
53*bcb5dc79SHONG Yifan* [shell](docs/shell_doc.md)
54*bcb5dc79SHONG Yifan* [structs](docs/structs_doc.md)
55*bcb5dc79SHONG Yifan* [subpackages](docs/subpackages_doc.md)
56*bcb5dc79SHONG Yifan* [types](docs/types_doc.md)
57*bcb5dc79SHONG Yifan* [unittest](docs/unittest_doc.md)
58*bcb5dc79SHONG Yifan* [versions](docs/versions_doc.md)
59*bcb5dc79SHONG Yifan
60*bcb5dc79SHONG Yifan## List of rules (in rules/)
61*bcb5dc79SHONG Yifan
62*bcb5dc79SHONG Yifan* [analysis_test](docs/analysis_test_doc.md)
63*bcb5dc79SHONG Yifan* [build_test](docs/build_test_doc.md)
64*bcb5dc79SHONG Yifan* [common_settings](docs/common_settings_doc.md)
65*bcb5dc79SHONG Yifan* [directories](docs/copy_directory_doc.md)
66*bcb5dc79SHONG Yifan    * [directory](docs/directory_doc.md)
67*bcb5dc79SHONG Yifan    * [directory_glob](docs/directory_glob.md)
68*bcb5dc79SHONG Yifan    * [subdirectory](docs/subdirectory_doc.md)
69*bcb5dc79SHONG Yifan* [copy_directory](docs/copy_directory_doc.md)
70*bcb5dc79SHONG Yifan* [copy_file](docs/copy_file_doc.md)
71*bcb5dc79SHONG Yifan* [diff_test](docs/diff_test_doc.md)
72*bcb5dc79SHONG Yifan* [expand_template](docs/expand_template_doc.md)
73*bcb5dc79SHONG Yifan* [native_binary and native_test](docs/native_binary_doc.md)
74*bcb5dc79SHONG Yifan* [run_binary](docs/run_binary_doc.md)
75*bcb5dc79SHONG Yifan* [select_file](docs/select_file_doc.md)
76*bcb5dc79SHONG Yifan* [write_file](docs/write_file_doc.md)
77*bcb5dc79SHONG Yifan
78*bcb5dc79SHONG Yifan## Writing a new module
79*bcb5dc79SHONG Yifan
80*bcb5dc79SHONG YifanThe criteria for adding a new function or module to this repository are:
81*bcb5dc79SHONG Yifan
82*bcb5dc79SHONG Yifan1. Is it widely needed? The new code must solve a problem that occurs often during the development of Bazel build rules. It is not sufficient that the new code is merely useful. Candidate code should generally have been proven to be necessary across several projects, either because it provides indispensable common functionality, or because it requires a single standardized implementation.
83*bcb5dc79SHONG Yifan
84*bcb5dc79SHONG Yifan1. Is its interface simpler than its implementation? A good abstraction provides a simple interface to a complex implementation, relieving the user from the burden of understanding. By contrast, a shallow abstraction provides little that the user could not easily have written out for themselves. If a function's doc comment is longer than its body, it's a good sign that the abstraction is too shallow.
85*bcb5dc79SHONG Yifan
86*bcb5dc79SHONG Yifan1. Is its interface unimpeachable? Given the problem it tries to solve, does it have sufficient parameters or generality to address all reasonable cases, or does it make arbitrary policy choices that limit its usefulness? If the function is not general, it likely does not belong here. Conversely, if it is general thanks only to a bewildering number of parameters, it also does not belong here.
87*bcb5dc79SHONG Yifan
88*bcb5dc79SHONG Yifan1. Is it efficient? Does it solve the problem using the asymptotically optimal algorithm, without using excessive looping, allocation, or other high constant factors? Starlark is an interpreted language with relatively expensive basic operations, and an approach that might make sense in C++ may not in Starlark.
89*bcb5dc79SHONG Yifan
90*bcb5dc79SHONG YifanIf your new module meets all these criteria, then you should consider sending us a pull request. It is always better to discuss your plans before executing them.
91*bcb5dc79SHONG Yifan
92*bcb5dc79SHONG YifanMany of the declarations already in this repository do not meet this bar.
93*bcb5dc79SHONG Yifan
94*bcb5dc79SHONG Yifan
95*bcb5dc79SHONG YifanSteps to add a module to Skylib:
96*bcb5dc79SHONG Yifan
97*bcb5dc79SHONG Yifan1. Create a new `.bzl` file in the `lib` directory.
98*bcb5dc79SHONG Yifan
99*bcb5dc79SHONG Yifan1. Write the functions or other symbols (such as constants) in that file,
100*bcb5dc79SHONG Yifan   defining them privately (prefixed by an underscore).
101*bcb5dc79SHONG Yifan
102*bcb5dc79SHONG Yifan1. Create the exported module struct, mapping the public names of the symbols
103*bcb5dc79SHONG Yifan   to their implementations. For example, if your module was named `things` and
104*bcb5dc79SHONG Yifan   had a function named `manipulate`, your `things.bzl` file would look like
105*bcb5dc79SHONG Yifan   this:
106*bcb5dc79SHONG Yifan
107*bcb5dc79SHONG Yifan   ```python
108*bcb5dc79SHONG Yifan   def _manipulate():
109*bcb5dc79SHONG Yifan     ...
110*bcb5dc79SHONG Yifan
111*bcb5dc79SHONG Yifan   things = struct(
112*bcb5dc79SHONG Yifan       manipulate=_manipulate,
113*bcb5dc79SHONG Yifan   )
114*bcb5dc79SHONG Yifan   ```
115*bcb5dc79SHONG Yifan
116*bcb5dc79SHONG Yifan1. Add unit tests for your module in the `tests` directory.
117*bcb5dc79SHONG Yifan
118*bcb5dc79SHONG Yifan## `bzl_library`
119*bcb5dc79SHONG Yifan
120*bcb5dc79SHONG YifanThe `bzl_library.bzl` rule can be used to aggregate a set of
121*bcb5dc79SHONG YifanStarlark files and its dependencies for use in test targets and
122*bcb5dc79SHONG Yifandocumentation generation.
123*bcb5dc79SHONG Yifan
124*bcb5dc79SHONG Yifan## Troubleshooting
125*bcb5dc79SHONG Yifan
126*bcb5dc79SHONG YifanIf you try to use `unittest` and you get the following error:
127*bcb5dc79SHONG Yifan
128*bcb5dc79SHONG Yifan```
129*bcb5dc79SHONG YifanERROR: While resolving toolchains for target //foo:bar: no matching toolchains found for types @bazel_skylib//toolchains:toolchain_type
130*bcb5dc79SHONG YifanERROR: Analysis of target '//foo:bar' failed; build aborted: no matching toolchains found for types @bazel_skylib//toolchains:toolchain_type
131*bcb5dc79SHONG Yifan```
132*bcb5dc79SHONG Yifan
133*bcb5dc79SHONG Yifanthen you probably forgot to load and call `bazel_skylib_workspace()` in your
134*bcb5dc79SHONG Yifan`WORKSPACE` file.
135*bcb5dc79SHONG Yifan
136*bcb5dc79SHONG Yifan### Maintainer's guide
137*bcb5dc79SHONG Yifan
138*bcb5dc79SHONG YifanSee the [maintaner's guide](docs/maintainers_guide.md) for instructions for
139*bcb5dc79SHONG Yifancutting a new release.
140*bcb5dc79SHONG Yifan
141*bcb5dc79SHONG Yifan## Gazelle Plugin
142*bcb5dc79SHONG Yifan
143*bcb5dc79SHONG Yifan`bazel_skylib` ships with a [gazelle](https://github.com/bazelbuild/bazel-gazelle)
144*bcb5dc79SHONG Yifanplugin to generate `bzl_library` entries in build files. To use this, in your
145*bcb5dc79SHONG Yifan`WORKSPACE`:
146*bcb5dc79SHONG Yifan
147*bcb5dc79SHONG Yifan```starlark
148*bcb5dc79SHONG Yifanload("@bazel_skylib_gazelle_plugin//:workspace.bzl", "bazel_skylib_gazelle_plugin_workspace")
149*bcb5dc79SHONG Yifan
150*bcb5dc79SHONG Yifanbazel_skylib_gazelle_plugin_workspace()
151*bcb5dc79SHONG Yifan
152*bcb5dc79SHONG Yifanload("@bazel_skylib_gazelle_plugin//:setup.bzl", "bazel_skylib_gazelle_plugin_setup")
153*bcb5dc79SHONG Yifan
154*bcb5dc79SHONG Yifanbazel_skylib_gazelle_plugin_setup()
155*bcb5dc79SHONG Yifan```
156*bcb5dc79SHONG Yifan
157*bcb5dc79SHONG YifanYou may then include the plugin using code similar to this in your `BUILD.bazel`
158*bcb5dc79SHONG Yifanfile:
159*bcb5dc79SHONG Yifan
160*bcb5dc79SHONG Yifan```starlark
161*bcb5dc79SHONG Yifanload("@bazel_gazelle//:def.bzl", "DEFAULT_LANGUAGES", "gazelle", "gazelle_binary")
162*bcb5dc79SHONG Yifan
163*bcb5dc79SHONG Yifangazelle(
164*bcb5dc79SHONG Yifan    name = "gazelle",
165*bcb5dc79SHONG Yifan    gazelle = ":gazelle_bin",
166*bcb5dc79SHONG Yifan)
167*bcb5dc79SHONG Yifan
168*bcb5dc79SHONG Yifangazelle_binary(
169*bcb5dc79SHONG Yifan    name = "gazelle_bin",
170*bcb5dc79SHONG Yifan    languages = DEFAULT_LANGUAGES + [
171*bcb5dc79SHONG Yifan        "@bazel_skylib_gazelle_plugin//bzl",
172*bcb5dc79SHONG Yifan    ],
173*bcb5dc79SHONG Yifan)
174*bcb5dc79SHONG Yifan```
175