Skip to content

Latest commit

 

History

History
117 lines (90 loc) · 4.69 KB

HACKING.md

File metadata and controls

117 lines (90 loc) · 4.69 KB

Tips and tricks for hacking on Buck2

You might have been lead here by reading CONTRIBUTING.md. If not, please read that as well! That will give you the high level overview; this is the document is all about the needed elbow grease you'll have to apply.

Building the code

Buck2 is written in Rust, and currently requires a nightly toolchain. You need rustup installed to provision the necessary version of rustc and cargo as a result.

You can either build buck2 from a clone of the Buck2 repo (this will cause rustup/cargo to install the right nightly version of rustc):

git clone https://github.com/facebook/buck2.git
cd buck2/
cargo install --path=app/buck2

Or, alternatively, install it directly from GitHub:

rustup install nightly-2023-04-23
cargo +nightly-2023-04-23 install --git https://github.com/facebook/buck2.git buck2

Side note: using Nix to compile the source

NOTE: You shouldn't need to do this if you already have a tool such as rustup installed. The following instructions are for Nix and NixOS users specifically.

Most Nix users provision tools directly with Nix itself, rather than rustup; the Buck2 source code includes a flake.nix file, which can be used to compile Buck2 itself via cargo:

git clone https://github.com/facebook/buck2.git
cd buck2/
nix develop . # add 'rustc' and 'cargo' to $PATH
cargo build --release --path=app/buck2

A Nix package (e.g. nix build .#buck2) does not yet exist.

Side note: protoc binaries and alternative operating systems

NOTE: You can probably skip this if you're on a typical "Tier 1" operating system like aarch64/x86_64 Linux, Windows, or macOS.

Buck2 uses Protocol Buffers quite extensively in its internals, and also for communication with remote systems for tasks like Remote Execution. Therefore there are .proto files in the codebase that need to be compiled to Rust code. Due to the architecture of how Protocol Buffers works, you'll need the protoc compiler available in order to do this.

For the 3 major operating systems — Linux, Windows, and macOS — the cargo build uses prebuilt protoc binaries from protoc-bin-vendored crate to accomplish this. So everything should transparently work with no intervention needed and just running cargo build is enough.

But there are non-Tier-1 operating systems where Buck2 might be used, and the above crate won't work, and you'll need to override it. You will need to install protoc from some other source. Doing that is out of scope for this document. But once you've done so, you can use the following two environment variables before running cargo build to override the crate:

  • BUCK2_BUILD_PROTOC, the path to the protoc binary
  • BUCK2_BUILD_PROTOC_INCLUDE, the path to the protocol buffers header file directory

Assuming you have your protocol buffers installation located in /opt/protobuf, you can do the following:

export BUCK2_BUILD_PROTOC=/opt/protobuf/bin/protoc
export BUCK2_BUILD_PROTOC_INCLUDE=/opt/protobuf/include

Buck2 should then build with cargo using the steps above.

Coding conventions

Beyond the obvious (well-tested, easy to read) we prefer guidelines that are automatically enforced, e.g. through Rustfmt, Clippy or the custom linter we have written. Some rules:

  • Follow standard rustfmt conventions.
  • Use the utilities from Gazebo where they are useful, in particular, dupe.
  • Prefer to_owned to convert &str to String.
  • Qualify anyhow::Result rather than use anyhow::Result.
  • Most errors should be returned as anyhow::Result. Inspecting errors outside tests and the top-level error handler is strongly discouraged.
  • Most errors should be constructed with thiserror deriving enum values, not raw anyhow!.
  • We use the derivative library to derive the PartialEq and Hash traits when some fields should be ignored.
  • Prefer use crate::foo::bar over use super::bar or use crate::foo::*, apart from test modules which often have use super::* at the top.
  • Modules should either have submodules or types/functions/constants, but not both.
  • Prefer anyhow::Error for checking internal invariants that are maintained between multiple files, while panic!/unreachable! are reasonable if the invariant is file-local.

Error messages

  • Names (of variables, targets, files, etc) should be quoted with backticks, e.g. Variable `x` not defined.
  • Lists should use square brackets, e.g. Available targets: [`aa`, `bb`].
  • Error messages should start with an upper case letter. Error messages should not end with a period.