# Perfetto Project Development Guidelines

This document provides essential instructions and best practices for developing
in the Perfetto codebase. Adhere to these guidelines to ensure consistency and
quality.

## 1. Building the Project

Use the following commands to build the project for different configurations.
All commands should be run from the root of the repository.

The output folder where code is built lives in out/xxx. Different people use
different output folders. Pick the output folder as follows
- The $OUT env var should contain the path of the output folder. If it exists respect that.
- If $OUT is empty/unset, set it by looking at the most recent out/ subdir, i.e.
  `OUT=out/$(ls -t1 out | head -n1)`

### Building C++ code

Our C++ sources use tools/gn and tools/ninja to build.

- If you touch a .gn or .gni file, rerun `tools/gn gen --check $OUT`
- Afterwards, you can build code running `tools/ninja -C $OUT TARGET_NAME"
- TARGET_NAME is:
  - perfetto_unittests: for any file in src/**/*_unittest.cc
  - perfetto_integrationtests: for any file in src/**/*_integrationtest.cc (and most code under test/)
  - perfetto_benchmarks: for any file in src/**/*_benchmark.cc (and most code under test/)
  - Other target names are usually: traced, traced_probes, perfetto, trace_processor_shell. You can discover them following the root /BUILD.gn file

When adding/removing source files, keep BUILD.gn files updated.
Usually there is a BUILD.gn file in each directory. If not, look at closer parent dirs for precedent.

Never bother manually updating Android.bp files or bazel BUILD files.
Those are autogenerated later when uploading the pull request via
`tools/gen_all $OUT`, but humans will take care of that.

To build one or more targets:

```sh
tools/ninja -C $OUT -k 10000 trace_processor_shell perfetto_unittests
```

### 2. Running C++ Tests

Perfetto uses the Google Test framework. You will see c++ sources like
```cpp
TEST(ProtozeroToJsonTest, Foo) {
...
}
```

ProtozeroToJsonTest is the test suite name, Foo the test name.

You can run all the tests in a test suite by doing:

```sh
$OUT/perfetto_unittests --gtest_brief=1 --gtest_filter="ProtozeroToJsonTest.*"
```

Or if you touch a specific test, you can run only that one doing
```sh
$OUT/perfetto_unittests --gtest_brief=1 --gtest_filter="ProtozeroToJsonTest.Foo"
```
Same goes for perfetto_integrationtests.

For perfetto_benchmarks you need instead to run

```sh
$OUT/perfetto_benchmarks --benchmark_filter='.*BM_RtMutex_NoContention.*'
```

Note that unlike Google Test, where the filter is a glob, in Google Benchmarks the filter is a regex.

### Trace Processor Diff Tests

Trace Processor Diff Tests (or diff tests for short) are executed by running the
following command:

```sh
tools/diff_test_trace_processor.py $OUT$/trace_processor_shell --keep-input --quiet --name-filter="<regex of test names>"
```

**Note:** These tests can also be run with ASan or MSan builds by changing the
path from `out/linux_clang_release/` to `out/linux_asan/` or `out/linux_msan/`
respectively. **Note:** The `--name-filter` argument is optional. **Note:** When
using the `--name-filter` flag, do not include `test_` in the filter. The test
runner automatically drops this prefix. For example, to run `test_my_cool_test`,
use the filter `MyTestSuite.my_cool_test`.


### Test Guidelines

- **Prefer test suites over individual tests.** When using the `--gtest_filter`
  flag, specify a whole test suite (e.g., `"MyTestSuite.*"`) instead of a single
  test case (e.g., `"MyTestSuite.MySpecificTest"`). This ensures broader test
  coverage.
- **Do not test unstable IDs.** When writing diff tests, do not include columns
  that contain unstable IDs (e.g. `upid`, `utid`, `id`, etc) in the output. These
  IDs can change between different runs of the same test, which will cause the
  test to fail.
- **Remove `test_` prefix for diff tests.** When using the `--name-filter` flag
  for diff tests, do not include `test_` in the filter. The test
  runner automatically drops this prefix. For example, to run `test_my_cool_test`,
  use the filter `MyTestSuite.my_cool_test`.

## 3. Core Software Engineering Principles

Follow these principles when writing and modifying code.

### Principle 1: Don't Repeat Yourself (DRY)

- **Avoid code duplication.** Before writing a new function, search the codebase
  for existing functions that provide similar functionality.
- **Reuse and refactor.** If a suitable function exists, reuse it. If it's close
  but not an exact match, consider refactoring the existing function to
  accommodate the new use case instead of creating a copy.
- **Consult if unsure.** If you are considering duplicating a function or a
  significant block of code, consult with the user first.

## 4. Getting Diffs

When asked to "get a diff" or "read the current diff", run the following
command:

```sh
git diff $(git config branch.$(git rev-parse --abbrev-ref HEAD).parent)
```

## 5. Fixing GN Dependencies

When asked to fix GN dependencies, run the following command and fix any errors
that are reported:

```sh
tools/gn check $OUT
```

**Note:** When fixing include errors, do not add dependencies to `public_deps`
unless explicitly instructed to by the user. Instead, add a direct dependency to
the target that requires it.

## 6. Other Configurations

### ASan (AddressSanitizer) Build

To build with ASan for memory error detection:

```sh
tools/ninja -C out/linux_asan -k 10000 trace_processor_shell perfetto_unittests
```

### MSan (MemorySanitizer) Build

To build with MSan for uninitialized read detection:

```sh
tools/ninja -C out/linux_msan -k 10000 trace_processor_shell perfetto_unittests
```

### ASan (AddressSanitizer) Tests

**Note:** Ensure the `ASAN_SYMBOLIZER_PATH` is set correctly.

```sh
ASAN_SYMBOLIZER_PATH="$(pwd)/buildtools/linux64/clang/bin/llvm-symbolizer" \
out/linux_asan/perfetto_unittests --gtest_brief=1 --gtest_filter="<TestSuiteName.*>"
```

### MSan (MemorySanitizer) Tests

**Note:** Ensure the `MSAN_SYMBOLIZER_PATH` is set correctly.

```sh
MSAN_SYMBOLIZER_PATH="$(pwd)/buildtools/linux64/clang/bin/llvm-symbolizer" \
out/linux_msan/perfetto_unittests --gtest_brief=1 --gtest_filter="<TestSuiteName.*>"

## 7. Creating Pull Requests

When creating a pull request, follow these steps:

1.  **Create a new branch:**
    Use the command `git new-branch dev/lalitm/<name-of-branch>` to create a new branch for your pull request.

2.  **Create a stacked/dependent pull request:**
    To create a pull request that depends on another, use the command `git new-branch --parent <name-of-parent-branch> dev/lalitm/<name-of-branch>`.

**Note:** The `git new-branch` command only creates and switches to a new
branch. The normal `git add` and `git commit` workflow should be used to add
changes to the branch.

## 8. Commit Messages

When writing commit messages, follow these guidelines:

- **Prefix your commits.** Prefix changes to Trace Processor code with `tp:`,
  UI code with `ui:`, and general Perfetto changes with `perfetto:`.
- **Keep it concise.** A short one-line summary followed by a paragraph
  describing the change is the best commit message.
