|
| 1 | +Project: /_project.yaml |
| 2 | +Book: /_book.yaml |
| 3 | +keywords: product:Bazel,lockfile,Bzlmod |
| 4 | + |
| 5 | +# Bazel Lockfile |
| 6 | + |
| 7 | +{% include "_buttons.html" %} |
| 8 | + |
| 9 | +The lockfile feature in Bazel enables the recording of specific versions or |
| 10 | +dependencies of software libraries or packages required by a project. It |
| 11 | +achieves this by storing the result of module resolution and extension |
| 12 | +evaluation. The lockfile promotes reproducible builds, ensuring consistent |
| 13 | +development environments. Additionally, it enhances build efficiency by allowing |
| 14 | +Bazel to skip the resolution process when there are no changes in project |
| 15 | +dependencies. Furthermore, the lockfile improves stability by preventing |
| 16 | +unexpected updates or breaking changes in external libraries, thereby reducing |
| 17 | +the risk of introducing bugs. |
| 18 | + |
| 19 | +## Lockfile Generation {:#lockfile-generation} |
| 20 | + |
| 21 | +The lockfile is generated under the workspace root with the name |
| 22 | +`MODULE.bazel.lock`. It is created or updated during the build process, |
| 23 | +specifically after module resolution and extension evaluation. The lockfile |
| 24 | +captures the current state of the project, including the MODULE file, flags, |
| 25 | +overrides, and other relevant information. Importantly, it only includes |
| 26 | +dependencies that are included in the current invocation of the build. |
| 27 | + |
| 28 | +When changes occur in the project that affect its dependencies, the lockfile is |
| 29 | +automatically updated to reflect the new state. This ensures that the lockfile |
| 30 | +remains focused on the specific set of dependencies required for the current |
| 31 | +build, providing an accurate representation of the project's resolved |
| 32 | +dependencies. |
| 33 | + |
| 34 | +## Lockfile Usage {:#lockfile-usage} |
| 35 | + |
| 36 | +The lockfile can be controlled by the flag |
| 37 | +[`--lockfile_mode`](/reference/command-line-reference#flag--lockfile_mode) to |
| 38 | +customize the behavior of Bazel when the project state differs from the |
| 39 | +lockfile. The available modes are: |
| 40 | + |
| 41 | +* `update` (Default): If the project state matches the lockfile, the |
| 42 | + resolution result is immediately returned from the lockfile. Otherwise, |
| 43 | + resolution is executed, and the lockfile is updated to reflect the current |
| 44 | + state. |
| 45 | +* `error`: If the project state matches the lockfile, the resolution result is |
| 46 | + returned from the lockfile. Otherwise, Bazel throws an error indicating the |
| 47 | + variations between the project and the lockfile. This mode is particularly |
| 48 | + useful when you want to ensure that your project's dependencies remain |
| 49 | + unchanged, and any differences are treated as errors. |
| 50 | +* `off`: The lockfile is not checked at all. |
| 51 | + |
| 52 | +## Lockfile Benefits {:#lockfile-benefits} |
| 53 | + |
| 54 | +The lockfile offers several benefits and can be utilized in various ways: |
| 55 | + |
| 56 | +- **Reproducible builds.** By capturing the specific versions or dependencies |
| 57 | + of software libraries, the lockfile ensures that builds are reproducible |
| 58 | + across different environments and over time. Developers can rely on |
| 59 | + consistent and predictable results when building their projects. |
| 60 | + |
| 61 | +- **Efficient resolution skipping.** The lockfile enables Bazel to skip the |
| 62 | + resolution process if there are no changes in the project dependencies since |
| 63 | + the last build. This significantly improves build efficiency, especially in |
| 64 | + scenarios where resolution can be time-consuming. |
| 65 | + |
| 66 | +- **Stability and risk reduction.** The lockfile helps maintain stability by |
| 67 | + preventing unexpected updates or breaking changes in external libraries. By |
| 68 | + locking the dependencies to specific versions, the risk of introducing bugs |
| 69 | + due to incompatible or untested updates is reduced. |
| 70 | + |
| 71 | +## Lockfile Contents {:#lockfile-contents} |
| 72 | + |
| 73 | +The lockfile contains all the necessary information to determine whether the |
| 74 | +project state has changed. It also includes the result of building the project |
| 75 | +in the current state. The lockfile consists of two main parts: |
| 76 | + |
| 77 | +1. Inputs of the module resolution, such as `moduleFileHash`, `flags` and |
| 78 | + `localOverrideHashes`, as well as the output of the resolution, which is |
| 79 | + `moduleDepGraph`. |
| 80 | +2. For each module extension, the lockfile includes inputs that affect it, |
| 81 | + represented by `transitiveDigest`, and the output of running that extension |
| 82 | + referred to as `generatedRepoSpecs` |
| 83 | + |
| 84 | +Here is an example that demonstrates the structure of the lockfile, along with |
| 85 | +explanations for each section: |
| 86 | + |
| 87 | +```json |
| 88 | +{ |
| 89 | + "lockFileVersion": 1, |
| 90 | + "moduleFileHash": "b0f47b98a67ee15f9.......8dff8721c66b721e370", |
| 91 | + "flags": { |
| 92 | + "cmdRegistries": [ |
| 93 | + "https://bcr.bazel.build/" |
| 94 | + ], |
| 95 | + "cmdModuleOverrides": {}, |
| 96 | + "allowedYankedVersions": [], |
| 97 | + "envVarAllowedYankedVersions": "", |
| 98 | + "ignoreDevDependency": false, |
| 99 | + "directDependenciesMode": "WARNING", |
| 100 | + "compatibilityMode": "ERROR" |
| 101 | + }, |
| 102 | + "localOverrideHashes": { |
| 103 | + "bazel_tools": "b5ae1fa37632140aff8.......15c6fe84a1231d6af9" |
| 104 | + }, |
| 105 | + "moduleDepGraph": { |
| 106 | + "<root>": { |
| 107 | + "name": "", |
| 108 | + "version": "", |
| 109 | + "executionPlatformsToRegister": [], |
| 110 | + "toolchainsToRegister": [], |
| 111 | + "extensionUsages": [ |
| 112 | + { |
| 113 | + "extensionBzlFile": "extension.bzl", |
| 114 | + "extensionName": "lockfile_ext" |
| 115 | + } |
| 116 | + ], |
| 117 | + ... |
| 118 | + } |
| 119 | + }, |
| 120 | + "moduleExtensions": { |
| 121 | + "//:extension.bzl%lockfile_ext": { |
| 122 | + "transitiveDigest": "oWDzxG/aLnyY6Ubrfy....+Jp6maQvEPxn0pBM=", |
| 123 | + "generatedRepoSpecs": { |
| 124 | + "hello": { |
| 125 | + "bzlFile": "@@//:extension.bzl", |
| 126 | + ... |
| 127 | + } |
| 128 | + } |
| 129 | + } |
| 130 | + } |
| 131 | +} |
| 132 | +``` |
| 133 | + |
| 134 | +### Module File Hash {:#module-file-hash} |
| 135 | + |
| 136 | +The `moduleFileHash` represents the hash of the `MODULE.bazel` file contents. If |
| 137 | +any changes occur in this file, the hash value differs. |
| 138 | + |
| 139 | +### Flags {:#flags} |
| 140 | + |
| 141 | +The `Flags` object stores all the flags that can affect the resolution result. |
| 142 | + |
| 143 | +### Local Override Hashes {:#local-override-hashes} |
| 144 | + |
| 145 | +If the root module includes `local_path_overrides`, this section stores the hash |
| 146 | +of the `MODULE.bazel` file in the local repository. It allows tracking changes |
| 147 | +to this dependency. |
| 148 | + |
| 149 | +### Module Dependency Graph {:#module-dep-graph} |
| 150 | + |
| 151 | +The `moduleDepGraph` represents the result of the resolution process using the |
| 152 | +inputs mentioned above. It forms the dependency graph of all the modules |
| 153 | +required to run the project. |
| 154 | + |
| 155 | +### Module Extensions {:#module-extensions} |
| 156 | + |
| 157 | +The `moduleExtensions` section is a map that includes only the extensions used |
| 158 | +in the current invocation or previously invoked, while excluding any extensions |
| 159 | +that are no longer utilized. In other words, if an extension is not being used |
| 160 | +anymore across the dependency graph, it is removed from the `moduleExtensions` |
| 161 | +map. |
| 162 | + |
| 163 | +Each entry in this map corresponds to a used extension and is identified by its |
| 164 | +containing file and name. The corresponding value for each entry contains the |
| 165 | +relevant information associated with that extension: |
| 166 | + |
| 167 | +1. The `transitiveDigest` the digest of the extension implementation and its |
| 168 | + transitive .bzl files. |
| 169 | +2. The `generatedRepoSpecs` the result of running that extension with the |
| 170 | + current input. |
| 171 | + |
| 172 | +An additional factor that can affect the extension results is their _usages_. |
| 173 | +Although not stored in the lockfile, the usages are considered when comparing |
| 174 | +the current state of the extension with the one in the lockfile. |
| 175 | + |
| 176 | +## Best Practices {:#best-practices} |
| 177 | + |
| 178 | +To maximize the benefits of the lockfile feature, consider the following best |
| 179 | +practices: |
| 180 | + |
| 181 | +* Regularly update the lockfile to reflect changes in project dependencies or |
| 182 | + configuration. This ensures that subsequent builds are based on the most |
| 183 | + up-to-date and accurate set of dependencies. |
| 184 | + |
| 185 | +* Include the lockfile in version control to facilitate collaboration and |
| 186 | + ensure that all team members have access to the same lockfile, promoting |
| 187 | + consistent development environments across the project. |
| 188 | + |
| 189 | +By following these best practices, you can effectively utilize the lockfile |
| 190 | +feature in Bazel, leading to more efficient, reliable, and collaborative |
| 191 | +software development workflows. |
0 commit comments