dpranke | fe460231 | 2015-04-08 16:20:35 | [diff] [blame] | 1 | # The MB (Meta-Build wrapper) user guide |
| 2 | |
| 3 | [TOC] |
| 4 | |
| 5 | ## Introduction |
| 6 | |
Dirk Pranke | d181a1a | 2017-12-14 01:47:11 | [diff] [blame] | 7 | `mb` is a simple python wrapper GN meta-build tool; it was originally |
| 8 | written as part of the GYP->GN migration. |
dpranke | fe460231 | 2015-04-08 16:20:35 | [diff] [blame] | 9 | |
| 10 | It is intended to be used by bots to make it easier to manage the configuration |
| 11 | each bot builds (i.e., the configurations can be changed from chromium |
| 12 | commits), and to consolidate the list of all of the various configurations |
| 13 | that Chromium is built in. |
| 14 | |
| 15 | Ideally this tool will no longer be needed after the migration is complete. |
| 16 | |
dpranke | a5a77ca | 2015-07-16 23:24:17 | [diff] [blame] | 17 | For more discussion of MB, see also [the design spec](design_spec.md). |
dpranke | fe460231 | 2015-04-08 16:20:35 | [diff] [blame] | 18 | |
dpranke | a5a77ca | 2015-07-16 23:24:17 | [diff] [blame] | 19 | ## MB subcommands |
dpranke | fe460231 | 2015-04-08 16:20:35 | [diff] [blame] | 20 | |
Dirk Pranke | f24e6b2 | 2018-03-27 20:12:30 | [diff] [blame] | 21 | ### mb analyze |
dpranke | fe460231 | 2015-04-08 16:20:35 | [diff] [blame] | 22 | |
| 23 | `mb analyze` is reponsible for determining what targets are affected by |
| 24 | a list of files (e.g., the list of files in a patch on a trybot): |
| 25 | |
| 26 | ``` |
| 27 | mb analyze -c chromium_linux_rel //out/Release input.json output.json |
| 28 | ``` |
| 29 | |
Ben Pastene | 7450249 | 2021-01-06 17:07:15 | [diff] [blame] | 30 | Either the `-c/--config` flag or the `--builder-group` and `-b/--builder` flags |
dpranke | fe460231 | 2015-04-08 16:20:35 | [diff] [blame] | 31 | must be specified so that `mb` can figure out which config to use. |
| 32 | |
dpranke | ee5b51f6 | 2015-04-09 00:03:22 | [diff] [blame] | 33 | The first positional argument must be a GN-style "source-absolute" path |
| 34 | to the build directory. |
dpranke | fe460231 | 2015-04-08 16:20:35 | [diff] [blame] | 35 | |
dpranke | ee5b51f6 | 2015-04-09 00:03:22 | [diff] [blame] | 36 | The second positional argument is a (normal) path to a JSON file containing |
dpranke | 06de67be | 2015-11-12 22:10:03 | [diff] [blame] | 37 | a single object with the following fields: |
dpranke | fe460231 | 2015-04-08 16:20:35 | [diff] [blame] | 38 | |
dpranke | 06de67be | 2015-11-12 22:10:03 | [diff] [blame] | 39 | * `files`: an array of the modified filenames to check (as paths relative to |
| 40 | the checkout root). |
| 41 | * `test_targets`: an array of (ninja) build targets that needed to run the |
| 42 | tests we wish to run. An empty array will be treated as if there are |
| 43 | no tests that will be run. |
| 44 | * `additional_compile_targets`: an array of (ninja) build targets that |
| 45 | reflect the stuff we might want to build *in addition to* the list |
Takuto Ikuta | f91b4b28 | 2024-05-15 08:33:08 | [diff] [blame] | 46 | passed in `test_targets`. Targets in this list will be treated |
dpranke | 06de67be | 2015-11-12 22:10:03 | [diff] [blame] | 47 | specially, in the following way: if a given target is a "meta" |
Dirk Pranke | d181a1a | 2017-12-14 01:47:11 | [diff] [blame] | 48 | (GN: group) target like 'blink_tests' or or even the |
Thiago Farina | 511bb6d | 2017-06-30 22:24:10 | [diff] [blame] | 49 | ninja-specific 'all' target, then only the *dependencies* of the |
| 50 | target that are affected by the modified files will be rebuilt |
| 51 | (not the target itself, which might also cause unaffected dependencies |
| 52 | to be rebuilt). An empty list will be treated as if there are no additional |
| 53 | targets to build. |
dpranke | 06de67be | 2015-11-12 22:10:03 | [diff] [blame] | 54 | Empty lists for both `test_targets` and `additional_compile_targets` |
| 55 | would cause no work to be done, so will result in an error. |
| 56 | * `targets`: a legacy field that resembled a union of `compile_targets` |
| 57 | and `test_targets`. Support for this field will be removed once the |
| 58 | bots have been updated to use compile_targets and test_targets instead. |
dpranke | fe460231 | 2015-04-08 16:20:35 | [diff] [blame] | 59 | |
dpranke | ee5b51f6 | 2015-04-09 00:03:22 | [diff] [blame] | 60 | The third positional argument is a (normal) path to where mb will write |
| 61 | the result, also as a JSON object. This object may contain the following |
| 62 | fields: |
dpranke | fe460231 | 2015-04-08 16:20:35 | [diff] [blame] | 63 | |
| 64 | * `error`: this should only be present if something failed. |
dpranke | 06de67be | 2015-11-12 22:10:03 | [diff] [blame] | 65 | * `compile_targets`: the list of ninja targets that should be passed |
| 66 | directly to the corresponding ninja / compile.py invocation. This |
| 67 | list may contain entries that are *not* listed in the input (see |
Takuto Ikuta | f91b4b28 | 2024-05-15 08:33:08 | [diff] [blame] | 68 | the description of `additional_compile_targets` above and |
dpranke | 06de67be | 2015-11-12 22:10:03 | [diff] [blame] | 69 | [design_spec.md](the design spec) for how this works). |
| 70 | * `invalid_targets`: a list of any targets that were passed in |
| 71 | either of the input lists that weren't actually found in the graph. |
| 72 | * `test_targets`: the subset of the input `test_targets` that are |
| 73 | potentially out of date, indicating that the matching test steps |
| 74 | should be re-run. |
| 75 | * `targets`: a legacy field that indicates the subset of the input `targets` |
| 76 | that depend on the input `files`. |
| 77 | * `build_targets`: a legacy field that indicates the minimal subset of |
| 78 | targets needed to build all of `targets` that were affected. |
| 79 | * `status`: a field containing one of three strings: |
| 80 | |
| 81 | * `"Found dependency"` (build the `compile_targets`) |
dpranke | fe460231 | 2015-04-08 16:20:35 | [diff] [blame] | 82 | * `"No dependency"` (i.e., no build needed) |
dpranke | 06de67be | 2015-11-12 22:10:03 | [diff] [blame] | 83 | * `"Found dependency (all)"` (`test_targets` is returned as-is; |
| 84 | `compile_targets` should contain the union of `test_targets` and |
| 85 | `additional_compile_targets`. In this case the targets do not |
| 86 | need to be pruned). |
| 87 | |
| 88 | See [design_spec.md](the design spec) for more details and examples; the |
| 89 | differences can be subtle. We won't even go into how the `targets` and |
| 90 | `build_targets` differ from each other or from `compile_targets` and |
| 91 | `test_targets`. |
dpranke | fe460231 | 2015-04-08 16:20:35 | [diff] [blame] | 92 | |
Ben Pastene | 7450249 | 2021-01-06 17:07:15 | [diff] [blame] | 93 | The `-b/--builder`, `-c/--config`, `-f/--config-file`, `--builder-group`, |
dpranke | a5a77ca | 2015-07-16 23:24:17 | [diff] [blame] | 94 | `-q/--quiet`, and `-v/--verbose` flags work as documented for `mb gen`. |
| 95 | |
Dirk Pranke | f24e6b2 | 2018-03-27 20:12:30 | [diff] [blame] | 96 | ### mb gen |
dpranke | a5a77ca | 2015-07-16 23:24:17 | [diff] [blame] | 97 | |
Dirk Pranke | d181a1a | 2017-12-14 01:47:11 | [diff] [blame] | 98 | `mb gen` is responsible for generating the Ninja files by invoking GN with |
| 99 | the right sets of build args for the given bot. It takes arguments to |
| 100 | specify a build config and a directory, then runs GN as appropriate: |
dpranke | a5a77ca | 2015-07-16 23:24:17 | [diff] [blame] | 101 | |
| 102 | ``` |
| 103 | % mb gen -m tryserver.chromium.linux -b linux_rel //out/Release |
| 104 | % mb gen -c linux_rel_trybot //out/Release |
| 105 | ``` |
| 106 | |
Ben Pastene | 7450249 | 2021-01-06 17:07:15 | [diff] [blame] | 107 | Either the `-c/--config` flag or the `--builder-group` and `-b/--builder` flags |
dpranke | b9380a1 | 2016-07-21 21:44:09 | [diff] [blame] | 108 | must be specified so that `mb` can figure out which config to use. The |
| 109 | `--phase` flag must also be used with builders that have multiple |
| 110 | build/compile steps (and only with those builders). |
dpranke | a5a77ca | 2015-07-16 23:24:17 | [diff] [blame] | 111 | |
dpranke | e0f486f | 2015-11-19 23:42:00 | [diff] [blame] | 112 | By default, MB will look for a bot config file under `//ios/build/bots` (see |
| 113 | [design_spec.md](the design spec) for details of how the bot config files |
| 114 | work). If no matching one is found, will then look in |
| 115 | `//tools/mb/mb_config.pyl` to look up the config information, but you can |
| 116 | specify a custom config file using the `-f/--config-file` flag. |
dpranke | a5a77ca | 2015-07-16 23:24:17 | [diff] [blame] | 117 | |
| 118 | The path must be a GN-style "source-absolute" path (as above). |
| 119 | |
| 120 | You can pass the `-n/--dryrun` flag to mb gen to see what will happen without |
| 121 | actually writing anything. |
| 122 | |
| 123 | You can pass the `-q/--quiet` flag to get mb to be silent unless there is an |
| 124 | error, and pass the `-v/--verbose` flag to get mb to log all of the files |
| 125 | that are read and written, and all the commands that are run. |
| 126 | |
Dirk Pranke | f24e6b2 | 2018-03-27 20:12:30 | [diff] [blame] | 127 | ### mb help |
dpranke | fe460231 | 2015-04-08 16:20:35 | [diff] [blame] | 128 | |
| 129 | Produces help output on the other subcommands |
| 130 | |
Dirk Pranke | f24e6b2 | 2018-03-27 20:12:30 | [diff] [blame] | 131 | ### mb isolate |
Dirk Pranke | 8cb6aa78 | 2017-12-16 02:31:33 | [diff] [blame] | 132 | |
| 133 | Builds a given (ninja) target and produces an `.isolated` file suitable |
| 134 | for then running the command either locally in an isolated environment, |
| 135 | or remotely by uploading it to an isolate server and running it under |
| 136 | swarming. See below for more information on isolates and swarming. |
| 137 | |
Dirk Pranke | f24e6b2 | 2018-03-27 20:12:30 | [diff] [blame] | 138 | ### mb lookup |
dpranke | fe460231 | 2015-04-08 16:20:35 | [diff] [blame] | 139 | |
| 140 | Prints what command will be run by `mb gen` (like `mb gen -n` but does |
| 141 | not require you to specify a path). |
| 142 | |
Ben Pastene | 7450249 | 2021-01-06 17:07:15 | [diff] [blame] | 143 | The `-b/--builder`, `-c/--config`, `-f/--config-file`, `--builder-group`, |
dpranke | b9380a1 | 2016-07-21 21:44:09 | [diff] [blame] | 144 | `--phase`, `-q/--quiet`, and `-v/--verbose` flags work as documented for |
| 145 | `mb gen`. |
dpranke | a5a77ca | 2015-07-16 23:24:17 | [diff] [blame] | 146 | |
Dirk Pranke | f24e6b2 | 2018-03-27 20:12:30 | [diff] [blame] | 147 | ### mb run |
Dirk Pranke | 8cb6aa78 | 2017-12-16 02:31:33 | [diff] [blame] | 148 | |
| 149 | Builds and runs a given (ninja) target. By default the target will |
| 150 | be run locally but isolated (i.e., outside of the source tree, just |
| 151 | as it would be run under swarming). If the `-s/--swarming` flag is |
| 152 | passed, the target will be built, run, uploaded to the isolate server, |
| 153 | and run under swarming. |
| 154 | |
| 155 | By default, a set of dimensions appropriate for running the target in the |
| 156 | default pool for the build will be provided. You can specify additional |
| 157 | dimensions with the `-d/--dimension` flags, and you can skip the default |
| 158 | dimensions with the `--no-default-dimensions` flag (which can be useful |
| 159 | if you need to run on devices or in a different pool). See below for more |
| 160 | information on isolates and swarming. |
| 161 | |
| 162 | In either case, any flags past `--` will be passed on to the command |
| 163 | to be run inside the isolate. |
| 164 | |
Dirk Pranke | f24e6b2 | 2018-03-27 20:12:30 | [diff] [blame] | 165 | ### mb validate |
dpranke | fe460231 | 2015-04-08 16:20:35 | [diff] [blame] | 166 | |
| 167 | Does internal checking to make sure the config file is syntactically |
| 168 | valid and that all of the entries are used properly. It does not validate |
| 169 | that the flags make sense, or that the builder names are legal or |
| 170 | comprehensive, but it does complain about configs and mixins that aren't |
| 171 | used. |
| 172 | |
dpranke | a5a77ca | 2015-07-16 23:24:17 | [diff] [blame] | 173 | The `-f/--config-file` and `-q/--quiet` flags work as documented for |
| 174 | `mb gen`. |
| 175 | |
dpranke | fe460231 | 2015-04-08 16:20:35 | [diff] [blame] | 176 | This is mostly useful as a presubmit check and for verifying changes to |
| 177 | the config file. |
| 178 | |
Dirk Pranke | f24e6b2 | 2018-03-27 20:12:30 | [diff] [blame] | 179 | ### mb zip |
| 180 | |
| 181 | Builds and isolates a given (ninja) target like the `isolate` command does, |
| 182 | and then takes all of the files in the isolate and writes them into a single |
| 183 | zip file that can then easily be redistributed. |
| 184 | |
dpranke | a5a77ca | 2015-07-16 23:24:17 | [diff] [blame] | 185 | ## Isolates and Swarming |
| 186 | |
| 187 | `mb gen` is also responsible for generating the `.isolate` and |
| 188 | `.isolated.gen.json` files needed to run test executables through swarming |
Dirk Pranke | d181a1a | 2017-12-14 01:47:11 | [diff] [blame] | 189 | in a GN build. |
dpranke | a5a77ca | 2015-07-16 23:24:17 | [diff] [blame] | 190 | |
| 191 | If you wish to generate the isolate files, pass `mb gen` the |
| 192 | `--swarming-targets-file` command line argument; that arg should be a path |
| 193 | to a file containing a list of ninja build targets to compute the runtime |
| 194 | dependencies for (on Windows, use the ninja target name, not the file, so |
| 195 | `base_unittests`, not `base_unittests.exe`). |
| 196 | |
| 197 | MB will take this file, translate each build target to the matching GN |
| 198 | label (e.g., `base_unittests` -> `//base:base_unittests`, write that list |
| 199 | to a file called `runtime_deps` in the build directory, and pass that to |
| 200 | `gn gen $BUILD ... --runtime-deps-list-file=$BUILD/runtime_deps`. |
| 201 | |
| 202 | Once GN has computed the lists of runtime dependencies, MB will then |
| 203 | look up the command line for each target (currently this is hard-coded |
John Palmer | ab8812a | 2021-05-21 17:03:43 | [diff] [blame] | 204 | in [mb.py](https://source.chromium.org/chromium/chromium/src/+/main:tools/mb/mb.py;l=1370)), and write out the |
dpranke | a5a77ca | 2015-07-16 23:24:17 | [diff] [blame] | 205 | matching `.isolate` and `.isolated.gen.json` files. |
| 206 | |
Dirk Pranke | f24e6b2 | 2018-03-27 20:12:30 | [diff] [blame] | 207 | ## The mb_config.pyl config file |
dpranke | fe460231 | 2015-04-08 16:20:35 | [diff] [blame] | 208 | |
| 209 | The `mb_config.pyl` config file is intended to enumerate all of the |
| 210 | supported build configurations for Chromium. Generally speaking, you |
| 211 | should never need to (or want to) build a configuration that isn't |
| 212 | listed here, and so by using the configs in this file you can avoid |
Dirk Pranke | d181a1a | 2017-12-14 01:47:11 | [diff] [blame] | 213 | having to juggle long lists of gn args by hand. |
dpranke | fe460231 | 2015-04-08 16:20:35 | [diff] [blame] | 214 | |
| 215 | `mb_config.pyl` is structured as a file containing a single PYthon Literal |
Ben Pastene | 7450249 | 2021-01-06 17:07:15 | [diff] [blame] | 216 | expression: a dictionary with three main keys, `builder_groups`, `configs` and |
dpranke | fe460231 | 2015-04-08 16:20:35 | [diff] [blame] | 217 | `mixins`. |
| 218 | |
Ben Pastene | 7450249 | 2021-01-06 17:07:15 | [diff] [blame] | 219 | The `builder_groups` key contains a nested series of dicts containing mappings |
| 220 | of builder_group -> builder -> config . This allows us to isolate the builder |
dpranke | b9380a1 | 2016-07-21 21:44:09 | [diff] [blame] | 221 | recipes from the actual details of the configs. The config should either |
| 222 | be a single string value representing a key in the `configs` dictionary, |
| 223 | or a list of strings, each of which is a key in the `configs` dictionary; |
| 224 | the latter case is for builders that do multiple compiles with different |
| 225 | arguments in a single build, and must *only* be used for such builders |
| 226 | (where a --phase argument must be supplied in each lookup or gen call). |
dpranke | fe460231 | 2015-04-08 16:20:35 | [diff] [blame] | 227 | |
dpranke | b9380a1 | 2016-07-21 21:44:09 | [diff] [blame] | 228 | The `configs` key points to a dictionary of named build configurations. |
dpranke | fe460231 | 2015-04-08 16:20:35 | [diff] [blame] | 229 | |
| 230 | There should be an key in this dict for every supported configuration |
| 231 | of Chromium, meaning every configuration we have a bot for, and every |
| 232 | configuration commonly used by develpers but that we may not have a bot |
| 233 | for. |
| 234 | |
| 235 | The value of each key is a list of "mixins" that will define what that |
| 236 | build_config does. Each item in the list must be an entry in the dictionary |
| 237 | value of the `mixins` key. |
| 238 | |
| 239 | Each mixin value is itself a dictionary that contains one or more of the |
| 240 | following keys: |
| 241 | |
dpranke | fe460231 | 2015-04-08 16:20:35 | [diff] [blame] | 242 | * `gn_args`: a string containing a list of values passed to gn --args. |
| 243 | * `mixins`: a list of other mixins that should be included. |
dpranke | fe460231 | 2015-04-08 16:20:35 | [diff] [blame] | 244 | |
| 245 | When `mb gen` or `mb analyze` executes, it takes a config name, looks it |
| 246 | up in the 'configs' dict, and then does a left-to-right expansion of the |
Dirk Pranke | d181a1a | 2017-12-14 01:47:11 | [diff] [blame] | 247 | mixins; gn_args values are concatenated. |
dpranke | fe460231 | 2015-04-08 16:20:35 | [diff] [blame] | 248 | |
| 249 | For example, if you had: |
| 250 | |
| 251 | ``` |
| 252 | { |
| 253 | 'configs`: { |
Dirk Pranke | d181a1a | 2017-12-14 01:47:11 | [diff] [blame] | 254 | 'linux_release_trybot': ['gn_release', 'trybot'], |
dpranke | fe460231 | 2015-04-08 16:20:35 | [diff] [blame] | 255 | 'gn_shared_debug': None, |
| 256 | } |
| 257 | 'mixins': { |
| 258 | 'bot': { |
Takuto Ikuta | f91b4b28 | 2024-05-15 08:33:08 | [diff] [blame] | 259 | 'gn_args': 'use_remoteexec=true dcheck_always_on=false', |
dpranke | fe460231 | 2015-04-08 16:20:35 | [diff] [blame] | 260 | }, |
| 261 | 'debug': { |
| 262 | 'gn_args': 'is_debug=true', |
| 263 | }, |
Dirk Pranke | d181a1a | 2017-12-14 01:47:11 | [diff] [blame] | 264 | 'gn_release': { |
dpranke | fe460231 | 2015-04-08 16:20:35 | [diff] [blame] | 265 | 'mixins': ['release'], |
dpranke | fe460231 | 2015-04-08 16:20:35 | [diff] [blame] | 266 | }, |
| 267 | 'release': { |
| 268 | 'gn_args': 'is_debug=false', |
| 269 | } |
| 270 | 'shared': { |
| 271 | 'gn_args': 'is_component_build=true', |
dpranke | fe460231 | 2015-04-08 16:20:35 | [diff] [blame] | 272 | }, |
| 273 | 'trybot': { |
dpranke | fe460231 | 2015-04-08 16:20:35 | [diff] [blame] | 274 | 'gn_args': 'dcheck_always_on=true', |
| 275 | } |
| 276 | } |
| 277 | } |
martiniss | ceaaa71 | 2015-10-23 22:45:26 | [diff] [blame] | 278 | ``` |
dpranke | fe460231 | 2015-04-08 16:20:35 | [diff] [blame] | 279 | |
| 280 | and you ran `mb gen -c linux_release_trybot //out/Release`, it would |
Takuto Ikuta | f91b4b28 | 2024-05-15 08:33:08 | [diff] [blame] | 281 | translate into a call to `gn --args="use_remoteexec=true dcheck_always_on=false dcheck_always_on=true"`. |
dpranke | fe460231 | 2015-04-08 16:20:35 | [diff] [blame] | 282 | |
| 283 | (From that you can see that mb is intentionally dumb and does not |
Dirk Pranke | d181a1a | 2017-12-14 01:47:11 | [diff] [blame] | 284 | attempt to de-dup the flags, it lets GN do that). |
dpranke | fe460231 | 2015-04-08 16:20:35 | [diff] [blame] | 285 | |
dpranke | a5a77ca | 2015-07-16 23:24:17 | [diff] [blame] | 286 | ## Debugging MB |
dpranke | fe460231 | 2015-04-08 16:20:35 | [diff] [blame] | 287 | |
| 288 | By design, MB should be simple enough that very little can go wrong. |
| 289 | |
| 290 | The most obvious issue is that you might see different commands being |
| 291 | run than you expect; running `'mb -v'` will print what it's doing and |
| 292 | run the commands; `'mb -n'` will print what it will do but *not* run |
| 293 | the commands. |
| 294 | |
| 295 | If you hit weirder things than that, add some print statements to the |
| 296 | python script, send a question to [email protected], or |
| 297 | [file a bug](https://crbug.com/new) with the label |
| 298 | 'mb' and cc: [email protected]. |