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).