github.com/distbuild/reclient@v0.0.0-20240401075343-3de72e395564/README.md (about) 1 # Remote Execution Client 2 3 This repository contains a client implementation of 4 [Remote Execution API](https://github.com/bazelbuild/remote-apis) that works 5 with 6 [Remote Execution API SDKs](https://github.com/bazelbuild/remote-apis-sdks). 7 8 Reclient integrates with an existing build system to enable remote execution and 9 caching of build actions. 10 11 When used with Server implementation of Remote Execution API, it helps to reduce 12 the build times by applying 2 main techniques: 13 14 1. Distribution of the load by executing individual build actions in parallel 15 on separate remote workers instead of on one build machine so that the build 16 actions that are executed in parallel don’t compete for the same local 17 resources. 18 1. RE Server instance-wide cache for build actions, inputs, and artifacts As a 19 consequence, results of a build action that was already executed for exactly 20 the same inputs on the same instance of RE Server will be fetched from the 21 cache even if the action was never executed on the machine. 22 23 Most clients are expected to see the performance improvement of their builds 24 after migrating from local to remote builds. However, builds with a high number 25 of deterministic build actions that can be executed in parallel are expected to 26 see the greatest improvement. 27 28 Reclient consists of the following main binaries: 29 30 1. **rewrapper** - a wrapper that forwards build commands to RBE 31 1. **reproxy** - a process that should be started at the beginning of the build 32 and shut down at the end. It communicates with RBE to execute build actions 33 remotely and/or fetch build artifacts from RE Server's CAS (Content 34 Addressable Storage). 35 1. **bootstrap** - starts and stops reproxy, and aggregates the metrics during 36 the shutdown. 37 1. **scandeps_server** - a standalone process for scanning includes of C(++) 38 compile actions. Started and stopped automatically by reproxy. 39 40 ## Note 41 42 This is not an officially supported Google product. 43 44 # Prerequisites 45 46 * `re-client` builds with [Bazel](https://bazel.build/). We recommend using 47 [Bazelisk](https://github.com/bazelbuild/bazelisk) to use the version of Bazel 48 currently supported by this code base. 49 * `re-client` also requires `gclient`, which can be installed by checking out 50 [depot_tools](https://chromium.googlesource.com/chromium/tools/depot_tools/) 51 and adding the `depot_tools` directory to your `PATH`. 52 53 # Building 54 55 `re-client` currently builds and is supported on Linux / Mac / Windows. 56 57 Once you've installed Bazel, and are in the re-client repo: 58 59 ``` 60 61 # Build the code 62 $ bazelisk build --config=clangscandeps //cmd/... 63 # You should now have binaries for 'bootstrap', 'dumpstats', 'reproxy', 64 # 'rewrapper'. 65 66 # Run unit tests 67 $ bazelisk test //pkg/... //internal/... 68 [...] 69 INFO: Elapsed time: 77.166s, Critical Path: 30.24s 70 INFO: 472 processes: 472 linux-sandbox. 71 INFO: Build completed successfully, 504 total actions 72 //internal/pkg/cli:go_default_test PASSED in 0.2s 73 //internal/pkg/deps:go_default_test PASSED in 1.2s 74 //internal/pkg/inputprocessor/action/cppcompile:go_default_test PASSED in 0.1s 75 //internal/pkg/inputprocessor/flagsparser:go_default_test PASSED in 0.1s 76 //internal/pkg/inputprocessor/pathtranslator:go_default_test PASSED in 0.1s 77 //internal/pkg/inputprocessor/toolchain:go_default_test PASSED in 0.2s 78 //internal/pkg/labels:go_default_test PASSED in 0.1s 79 //internal/pkg/logger:go_default_test PASSED in 0.2s 80 //internal/pkg/rbeflag:go_default_test PASSED in 0.1s 81 //internal/pkg/reproxy:go_default_test PASSED in 15.5s 82 //internal/pkg/rewrapper:go_default_test PASSED in 0.2s 83 //internal/pkg/stats:go_default_test PASSED in 0.1s 84 //pkg/cache:go_default_test PASSED in 0.2s 85 //pkg/cache/singleflightcache:go_default_test PASSED in 0.1s 86 //pkg/filemetadata:go_default_test PASSED in 2.1s 87 //pkg/inputprocessor:go_default_test PASSED in 0.2s 88 89 Executed 16 out of 16 tests: 16 tests pass. 90 ``` 91 92 Reclient can be built to use Goma's input processor. Goma's input processor is 93 3x faster than clang-scan-deps for a typical compile action in Chrome. Build as 94 follows: 95 96 ``` 97 bazelisk build //cmd/... --config=goma 98 ``` 99 100 101 # Versioning 102 103 There are four binaries that are built from this repository and used with 104 Android Platform for build acceleration: 105 106 - rewrapper 107 - reproxy 108 - dumpstats 109 - bootstrap 110 111 These binaries must be stamped with an appropriate version number before they 112 are dropped into Android source for consumption. 113 114 ## Versioning Guidelines 115 116 1. We will *maintain a consistent version across all of the binaries*. That 117 means, when there are changes to only one of the binaries, we will increment 118 the version number for all of them. 119 120 2. In order to be consistent with 121 [Semantic versioning scheme](https://semver.org/), the version format is of 122 the form “X.Y.Z.SHA” denoting “MAJOR.MINOR.PATCH.GIT_SHA”. 123 124 3. Updating version numbers: 125 126 MAJOR 127 128 - Declare major version “1” when re-client is feature complete for caching 129 and remote-execution capabilities. 130 - Update major version post “1”, when there are breaking changes to 131 interface / behavior of rewrapper tooling. Some examples of this are: 132 changing any of the flag names passed to rewrapper, changing the name of 133 rewrapper binary. 134 135 MINOR - Update minor version when 136 137 - New features are introduced in a backward compatible way. For example, 138 when remote-execution capability is introduced. 139 - Major implementation changes without changes to behavior / interface. 140 For example, if the “.deps” file is changed to JSON format. 141 142 PATCH - Update patch version 143 144 - For all other bug fixes only. Feature additions (irrespective of how 145 insignificant they are) should result in a MINOR version change. 146 - Any new release to Android Platform of re-client tools should update the 147 PATCH version at minimum. 148 149 4. Release Frequency: 150 151 - Kokoro release workflows can be triggered as often as necessary to 152 generate new release artifacts. 153 154 ## How to update version numbers? 155 156 You can update the MAJOR/MINOR/PATCH version numbers by simply changing the 157 `version.bzl` file present in the root of this repository. 158 159 160 # Reclient releases 161 162 Reclient binaries are released into the 163 [CIPD](https://chrome-infra-packages.appspot.com/p/infra/rbe/client) (Chrome 164 Infrastructure Package Deployment) with separate packages for Linux, Mac (amd64 165 and arm64), and Windows. Whenever a new version of Reclient is released there 166 are 2 sets of binaries released for each of the platforms. Those binaries use 2 167 different include scanners for C++ build actions: clang-scan-deps and goma. The 168 binaries using the goma include scanner have a version number ending with 169 “-gomaip” suffix, the ones using clang-scan-deps don’t have the suffix. Clients 170 migrating from Goma should use the releases using goma include scanner (with 171 -gomaip suffix). 172 173 ## Downloading Reclient binaries 174 175 Reclient binaries can be downloaded using CIPD's 176 [Web UI](\(https://chrome-infra-packages.appspot.com/p/infra/rbe/client\)), with 177 a 178 [CLI client](https://chromium.googlesource.com/infra/luci/luci-go/+/refs/heads/main/cipd/client), 179 or using 180 [gclient](https://chromium.googlesource.com/chromium/tools/depot_tools/+/HEAD/README.gclient.md)'s 181 configuration. 182 183 ### Downloading binaries with CIPD CLI client 184 185 To download Reclient with GomaIP dependency scanner (used for building 186 Chromium): 187 188 ``` 189 echo 'infra/rbe/client/${platform}' $RECLIENT_VERSION > /tmp/reclient.ensure 190 cipd ensure --root $CHECKOUT_DIR --ensure-file /tmp/reclient.ensure 191 ``` 192 193 To use Reclient with Clangscandeps (used for Android builds) instead, add `-csd` 194 suffix to CIPD package: 195 196 ``` 197 echo 'infra/rbe/client/${platform}-csd' $RECLIENT_VERSION > /tmp/reclient.ensure 198 199 ``` 200 201 * **`$RECLIENT_VERSION`** - the version of Reclient. It can be set to one of 202 the following: 203 204 * A fixed version of Reclient. For example 205 `re_client_version:0.114.2.81e819b-gomaip` (for Reclient with GomaIP 206 dependency scanner) or `re_client_version:0.114.2.81e819b` (for Reclient 207 with Clangscandeps). 208 * `latest` - the latest released Reclient version. 209 * `stable` - the latest stable Reclient version. Stable version is usually 210 1-2wks behind the `latest` as Reclient needs to run a few days on test 211 and staging environments without issues and degradations before it's 212 considered as `stable`. 213 214 * **`$CHECKOUT_DIR`** - the location where Reclient should be downloaded. 215 216 ### Downloading binaries with gclient 217 218 You can configure 219 [gclient](https://chromium.googlesource.com/chromium/tools/depot_tools/+/HEAD/README.gclient.md) 220 to download Reclient binaries during the `gclient sync` phase. Gclient expects a 221 DEPS file in the repository’s root directory. The file contains components that 222 will be checked out during the sync phase. To check out Reclient, the file 223 should have a similar entry to: 224 225 ``` 226 vars = { 227 ... 228 'reclient_version': '<version>', 229 ... 230 } 231 232 deps = { 233 ... 234 '<checkout-directory>': { 235 'packages': [ 236 { 237 'package': 'infra/rbe/client/${{platform}}', 238 'version': Var('reclient_version'), 239 } 240 ], 241 'dep_type': 'cipd', 242 }, 243 } 244 ``` 245 246 This will instruct **gclient** to check out `<version>` of Reclient from 247 `/infra/rbe/client/<platform>` CIPD package into `<checkout-directory>` 248 ([example](https://source.chromium.org/chromium/chromium/src/+/main:DEPS;l=583-590;drc=9362acf277a0dac6295d43e5c592ee8b065c496b)). 249 Extracting a version to a variable (as in an example above) is optional, but 250 provides a benefit of being able to override the default value through gclient’s 251 custom variables. 252 253 **Note:** The snippet above will instruct `gclient` to download Reclient with 254 GomaIP dependency processor. If you prefer Reclient with Clangscandeps, you'd 255 need to set package to `infra/rbe/client/${{platform}}-csd`. 256 257 # Using Reclient 258 259 ## Starting and stopping reproxy 260 261 Reclient requires reproxy to be started at the beginning of the build, and 262 stopped at the end. This is done through `bootstrap` binary by executing 263 following commands: 264 265 **Start:** 266 267 ``` 268 bootstrap -re_proxy=$reproxy_location [-cfg=$reproxy_config_location] 269 ``` 270 271 **Stop:** 272 273 ``` 274 bootstrap -re_proxy=$reproxy_location -shutdown 275 ``` 276 277 ## Configuration 278 279 Each of Reclient’s binaries can be configured either by command line flags, 280 environment variables, config files, or by combination of either of those (some 281 flags provided in the command line while others in the config file or set as 282 environment variables). If the same flag is defined in the command line and in 283 the config file or as an environment variable, the order of precedence is 284 following (from lowest to highest priority): 285 286 1. Config file 287 1. Environment variable 288 1. Command line argument 289 290 To use a configuration file, specify it with the `-cfg=$config_file_location` 291 flag. The config file is a list of `flag_name=flag_value` pairs, each on a new 292 line. Example below: 293 294 ``` 295 service=$RE_SERVER_ADDRESS 296 instance=$RE_SERVER_INSTANCE 297 server_address=unix:///tmp/reproxy.sock 298 log_dir=/tmp 299 output_dir=/tmp 300 proxy_log_dir=/tmp 301 depsscanner_address=$scandeps_server_location #distributed with Reclient 302 use_gce_credentials=true 303 ``` 304 305 To configure Reclient with environment variables, the variables should be 306 prefixed with `RBE_` (e.g. the value of `RBE_service` environment variable is 307 used to set the `service` flag). 308 309 ### Rewrapper 310 311 Full list of rewrapper config flags can be found in 312 [docs/cmd-line-flags.md](docs/cmd-line-flags.md). A few of the most commonly 313 used flags are: 314 315 * **platform** - Comma-separated key value pairs in the form key=value. This 316 is used to identify remote platform settings like the docker image to use to 317 run the command. The list of supported keys depends on RE Server 318 implementation. A detailed lexicon can be found 319 [here](https://github.com/bazelbuild/remote-apis/blob/main/build/bazel/remote/execution/v2/platform.md) 320 * **server_address** - The address reproxy is running on. It needs to be set 321 to the same value as reproxy’s `server_address` flag so that rewrapper and 322 reproxy can communicate with each other. This value should be UDS on 323 Linux/Mac (e.g. unix:///tmp/reproxy.sock) and a named pipe on Windows (e.g. 324 pipe://reproxy.ipc). Depot_tools has a helper choosing the address based on 325 the platform 326 ([here](https://source.chromium.org/chromium/chromium/tools/depot_tools/+/main:reclient_helper.py;l=159-168;drc=60b21dd19301b13eaf7c9069ac191f95f84ca6e9)). 327 * **labels** - Identifies the type of command to help the proxy make decisions 328 regarding remote execution. Labels consist of comma-separated key-value 329 pairs in form key=value where key is one of the following: type, compiler, 330 lang, tool, and toolname. Some examples of valid labels are: 331 * `type=compile,compiler=clang,lang=cpp` - clang compile actions 332 * `type=compile,compiler=clang-cl,lang=cpp` - clang compile actions 333 * `type=compile,compiler=nacl,lang=cpp` - nacl compile actions 334 * `type=compile,compiler=javac,lang=java` - java compile actions 335 * `type=link,tool=clang` - link actions 336 * `type=tool` - generic action that doesn’t require any action specific 337 input processing 338 * **exec_strategy** - One of `local`, `remote`, `remote_local_fallback`, 339 `racing`. It is recommended to set it to `remote_local_fallback` or 340 `racing`. With `remote_local_fallback` it will try to execute the action 341 remotely and fallback to local if the remote execution failed. With `racing` 342 it tries to execute both and picks the one that finished sooner. 343 * `env_var_allowlist` - List of environment variables allowed to pass to the 344 proxy. If the build action depends on local environment variables, they 345 should be set here, so they're reproduced on the remote worker. 346 347 If you are experiencing sporadic timeouts when dialing reproxy, you might 348 consider adding: 349 350 * **dial_timeout** - By default is 3m, if the flag is not set. But for some 351 projects, increasing it up to 10m has proved beneficial in eliminating the 352 timeouts 353 354 ### Reproxy 355 356 Full list of reproxy flags can be found 357 [docs/cmd-line-flags.md](docs/cmd-line-flags.md). A few of the most commonly 358 used flags are: 359 360 * **service** - The remote execution service to dial when calling via gRPC, 361 including port, such as `localhost:8790` 362 * **instance** - If a server supports multiple instances of the execution 363 system (with their own workers, storage, caches, etc.), the field instructs 364 the server which instance of the execution system to operate against. If the 365 server does not support different instances, the field can be omitted. 366 * **server_address** - An address reproxy should start its gRPC server on and 367 listen for incoming communication from rewrapper (should be set to the same 368 value as rewrapper's `server_address` parameter) 369 * **depsscanner_address** - The address of the dependency scanner service. To 370 use the `scandeps_server` distributed with Reclient set the value to 371 `exec://$absolute_path_to_reclient_dir/scandeps_server` For instance, if 372 Reclient is checked out to `/home/$user/chromium/src/buildtools/reclient/`, 373 the value of the attribute should be 374 `exec:///home/$user/chromium/src/buildtools/reclient/scandeps_server` 375 376 #### Authentication flags 377 378 If your RE Server implementation does not use RPC authentication then use one 379 of: 380 381 * **service_no_auth** - If `true`, do not authenticate with the service 382 (implied by `-service_no_security`). 383 * **use_rpc_credentials** - If `false`, no per-RPC credentials will be used. 384 Disables `--credential_file`, `-use_application_default_credentials`, and 385 `-use_gce_credentials`. (default `true`). 386 387 If your RE Server uses RPC authentication then use one of the following flags: 388 389 * **use_gce_credentials** - If `true` (and 390 `--use_application_default_credentials` is `false`), use the default GCE 391 credentials to authenticate with remote execution 392 (https://cloud.google.com/docs/authentication/provide-credentials-adc#attached-sa). 393 * **use_application_default_credentials** - If `true`, use application default 394 credentials to connect to remote execution. See 395 https://cloud.google.com/sdk/gcloud/reference/auth/application-default/login 396 * **credential_file** - The name of a file that contains service account 397 credentials to use when calling remote execution. Used only if 398 `-use_application_default_credentials` and `-use_gce_credentials` are false. 399 400 The reproxy is typically started via the bootstrap, so it is recommended to 401 avoid configuring it through the command line flags. It's advised to use 402 either a configuration file that’s passed to the bootstrap with the `-cfg` 403 flag or by setting environment variables before starting the bootstrap 404 ([example](https://source.chromium.org/chromium/chromium/tools/build/+/main:recipes/recipe_modules/reclient/api.py;l=378-396;drc=f3b7708f2a5728408a74ccbb6cba6eb9cb161aae)). 405 406 ## Integration with the build system 407 408 To execute your build actions remotely through Reclient, the build command 409 should be prepended with: 410 411 ``` 412 $rewrapper [-cfg=$config-file] -exec_root=$checkout-dir -- 413 ``` 414 415 , where: 416 417 * **\$rewrapper** - path of the rewrapper binary 418 * **\$config-file** - path of the rewrapper config file (assuming that 419 rewrapper was configured with config file) 420 * **\$checkout-dir** - root directory of the source repository 421 422 When rewrapper is executed, it passes the build command to a running instance of 423 reproxy that: 424 425 * Determines dependencies either from command line flags (e.g. clang/gcc’s -I 426 flag) or from the content of input files (during input processing phase) 427 * Uploads toolchain, the inputs, and their dependencies to RBE 428 * Executes the command remotely 429 * Downloads artifacts locally 430 431 Before the build is executed, reproxy needs to be started by bootstrap and shut 432 down at the end of the build. 433 434 During the run, reproxy writes its application-level logs to a directory 435 specified by a `log_dir` flag and logs records about the executed build actions 436 to an RPL file in a directory specified by the `proxy_log_dir` flag. During 437 reproxy shutdown, bootstrap dumps Reclient related build metrics to 438 `rbe_metrics.txt` file saved at a location specified by the bootstrap's 439 `output_path` flag. 440 441 ### GN integration 442 443 [GN](https://gn.googlesource.com/gn/) is a meta-build system that generates 444 build files for Ninja. Its configuration files are written in a simple, 445 dynamically typed language. Reclient can be integrated with the build by 446 modifying the GN config files. Because of GN's language flexibility the method 447 of how Reclient should be integrated will depend on the project, but usually it 448 should involve adding a rewrapper prefix 449 ([example](https://source.chromium.org/chromium/chromium/src/+/main:build/toolchain/gcc_toolchain.gni;l=214;drc=df7d81e33033a594ff56d5ab8387aa1f13cd1c39)) 450 that's controlled by a gn argument 451 ([example](https://source.chromium.org/chromium/chromium/src/+/main:build/toolchain/rbe.gni;l=14;drc=dc850b9b1565dc29b7d8997994ed82d867852250)), 452 and starting and stopping reproxy before and after the build. The latter might 453 be done by a helper script with reproxy start and stop steps around the ninja 454 call 455 [example](https://source.chromium.org/chromium/chromium/tools/depot_tools/+/main:reclient_helper.py). 456 457 ### CMake integration 458 459 You can integrate CMake with Reclient by using 460 [`<LANG>_COMPILER_LAUNCHER`](https://cmake.org/cmake/help/v3.14/prop_tgt/LANG_COMPILER_LAUNCHER.html) 461 property. This property is initialized by the value of the 462 `CMAKE_<LANG>_COMPILER_LAUNCHER` variable if it is set when a target is created. 463 For instance, to use Reclient for c/c++ compile actions, you’d need to set both 464 `CMAKE_C_COMPILER_LAUNCHER` and `CMAKE_CXX_COMPILER_LAUNCHER` to 465 `$rewrapper;-cfg=$config-file;-exec_root=$checkout-dir` (the property accepts 466 semicolon separated list as a launcher command). 467 468 Please note that CMake operates on absolute paths and you need to ensure that RE 469 server executes the action on a remote worker in the same directory as it is in 470 a local build machine (the method depends on your RE Server implementation). 471 Moreover, please be aware that rewrapper's `canonicalize_working_dir` flag 472 tampers the build actions' inputs paths, and thus should be disabled for the 473 build actions generated by CMake. 474 475 Example of CMake build integration with Reclient can be found 476 [here](https://chromium.googlesource.com/emscripten-releases/+/refs/heads/main/src/host_toolchains.py).