1*bcb5dc79SHONG Yifan# Skylib 2*bcb5dc79SHONG Yifan 3*bcb5dc79SHONG Yifan[](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