Contribution tools

The Carbon language project has a number of tools used to assist in preparing contributions.

Table of contents

Setup commands

These commands should help set up a development environment on your machine.

Debian or Ubuntu

# Update apt.
sudo apt update

# Check that the `clang` version is at least 19, our minimum version. That needs
# the number of the `:` in the output to be over 19. For example, `1:19.0-1`.
apt-cache show clang | grep 'Version:'

# Install tools.
sudo apt install \
  clang \
  gh \
  libc++-dev \
  libc++abi-dev \
  lld \
  lldb \
  python3 \
  pipx

# Install pre-commit.
pipx install pre-commit

# Set up git.
# If you don't already have a fork:
gh repo fork --clone carbon-language/carbon-lang
cd carbon-lang
pre-commit install

# Run tests.
./scripts/run_bazelisk.py test //...:all

Installing Bazelisk

Although the run_bazelisk script can make it easy to get started, if you’re frequently building Carbon, it can be a bit much to type. Consider either aliasing bazel to the run_bazelisk.py script, or downloading a bazelisk release, adding it to your $PATH, and aliasing bazel to it.

Old clang versions

If the version of clang is earlier than 19, you may still have version 19 available. You can use the following install instead:

# Install explicitly versioned Clang tools.
sudo apt install \
  clang-19 \
  libc++-19-dev \
  libc++abi-19-dev \
  lld-19 \
  lldb-19

# In your Carbon checkout, tell Bazel where to find `clang`. You can also
# export this path as the `CC` environment variable, or add it directly to
# your `PATH`.
echo "build --repo_env=CC=$(readlink -f $(which clang-19))" >> user.bazelrc

And if it’s not available directly from the distribution, you can install Clang tools on Debian/Ubuntu from https://apt.llvm.org.

NOTE: Most LLVM 19+ installs should build Carbon. If you’re having issues, see troubleshooting build issues.

macOS

# Install Homebrew.
/bin/bash -c "$(curl -fsSL \
  https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

# IMPORTANT: Make sure `brew` is added to the PATH!

# Install Homebrew tools.
brew install \
  bazelisk \
  gh \
  llvm \
  python@3.10 \
  pre-commit

# IMPORTANT: Make sure `llvm` is added to the PATH! It's separate from `brew`.

# Set up git.
gh repo fork --clone carbon-language/carbon-lang
cd carbon-lang
pre-commit install

# Run tests. Note homebrew makes `bazel` an alias to `bazelisk`.
bazel test //...:all

NOTE: On macOS, you should end up adding rc file lines similar to:

# For `brew`, `gh`, and other tools:
export PATH="${HOME}/.brew/bin:${PATH}"
# For `llvm`:
export PATH="$(brew --prefix llvm)/bin:${PATH}"

Tools

Main tools

These tools are essential for work on Carbon.

  • Package managers
    • apt (for Debian or Ubuntu)
      • To upgrade versions of apt packages, it will be necessary to periodically run sudo apt update && sudo apt upgrade.
    • Homebrew (for macOS)
      • To upgrade versions of brew packages, it will be necessary to periodically run brew upgrade.
    • Python
      • Carbon requires Python 3.9 or newer.
      • To upgrade versions of pip-installed packages, it will be necessary to periodically run pipx list --outdated, then pipx install -U <package> to upgrade desired packages.
      • When upgrading, version dependencies may mean packages should be outdated, and not be upgraded.
  • Main tools

Running pre-commit

pre-commit is typically set up using pre-commit install. When set up in this mode, it will check for issues when git commit is run. A typical commit workflow looks like:

  1. git commit to try committing files. This automatically executes pre-commit run, which may fail and leave files modified for cleanup.
  2. git add . to add the automatically modifications done by pre-commit.
  3. git commit again.

You can also use pre-commit run to check pending changes without git commit, or pre-commit run -a to run on all files in the repository.

NOTE: Some developers prefer to run pre-commit on git push instead of git commit because they want to commit files as originally authored instead of with pre-commit modifications. To switch, run pre-commit uninstall && pre-commit install -t pre-push.

Optional tools

These tools aren’t necessary to contribute to Carbon, but can be worth considering if they fit your workflow.

  • GitHub Desktop: A UI for managing GitHub repositories.
  • rs-git-fsmonitor and Watchman: Helps make git run faster on large repositories.
    • WARNING: Bugs in rs-git-fsmonitor and/or Watchman can result in pre-commit deleting files. If you see files being deleted, disable rs-git-fsmonitor with git config --unset core.fsmonitor.
  • vim-prettier: A vim integration for Prettier, which we use for formatting.
  • Visual Studio Code: A code editor.
    • We provide recommended extensions to assist Carbon development. Some settings changes must be made separately:
      • Python › Formatting: Provider: black
    • WARNING: Visual Studio Code modifies the PATH environment variable, particularly in the terminals it creates. The PATH difference can cause bazel to detect different startup options, discarding its build cache. As a consequence, it’s recommended to use either normal terminals or Visual Studio Code to run bazel, not both in combination. Visual Studio Code can still be used for other purposes, such as editing files, without interfering with bazel.
    • We also provide recommended setups for debugging in VS Code with either LLDB or [GDB]((/toolchain/docs/debugging.md#debugging-with-gdb)
  • clangd: An LSP server implementation for C/C++.
    • To ensure that clangd reports accurate diagnostics. It needs a generated file called compile_commands.json. This can be generated by invoking the command below:
      ./scripts/create_compdb.py
      
      • NOTE: This assumes you have python 3 installed on your system.
  • uv: A fast Python package manager.
    • Notably, uv supports automatic management of even complex Python dependencies for scripts: https://docs.astral.sh/uv/guides/scripts/
    • Installation: https://docs.astral.sh/uv/getting-started/installation/

We primarily test against apt.llvm.org and Homebrew installations. However, you can build and install LLVM yourself if you feel more comfortable with it. The essential CMake options to pass in order for this to work reliably include:

-DLLVM_ENABLE_PROJECTS=clang;clang-tools-extra;lld;lldb
-DLLVM_ENABLE_RUNTIMES=compiler-rt;libcxx;libcxxabi;libunwind
-DRUNTIMES_CMAKE_ARGS=-DLLVM_ENABLE_PER_TARGET_RUNTIME_DIR=OFF;-DCMAKE_POSITION_INDEPENDENT_CODE=ON;-DLIBCXX_ENABLE_STATIC_ABI_LIBRARY=ON;-DLIBCXX_STATICALLY_LINK_ABI_IN_SHARED_LIBRARY=OFF;-DLIBCXX_STATICALLY_LINK_ABI_IN_STATIC_LIBRARY=ON;-DLIBCXX_USE_COMPILER_RT=ON;-DLIBCXXABI_USE_COMPILER_RT=ON;-DLIBCXXABI_USE_LLVM_UNWINDER=ON
-DLLDB_ENABLE_PYTHON=ON

Troubleshooting build issues

bazel clean

Changes to packages installed on your system may not be noticed by bazel. This includes things such as changing LLVM versions, or installing libc++. Running bazel clean should force cached state to be rebuilt.

Old LLVM versions

Many build issues result from the particular options clang and llvm have been built with, particularly when it comes to system-installed versions. If you run clang --version, you should see at least version 19. If you see an older version, please update, or use the special clang-19 instructions above.

System installs of macOS typically won’t work, for example being an old LLVM version or missing llvm-ar; setup commands includes LLVM from Homebrew for this reason.

Run bazel clean when changing the installed LLVM version.

Debugging

See the toolchain documentation for guidance on how to debug problems with the toolchain itself.

Asking for help

If you’re having trouble resolving issues, please ask on #build-help, providing the output of the following diagnostic commands:

echo $CC
which clang
which clang-19
clang --version
grep llvm_bindir $(bazel info workspace)/bazel-execroot/external/+clang_toolchain_extension+bazel_cc_toolchain/clang_detected_variables.bzl

# If on macOS:
brew --prefix llvm

These commands will help diagnose potential build issues by showing which tooling is in use.