Skip to main content
Every change to the browser is a patch file in patches/, a diff against the pinned Chromium tag 152.0.7977.83. patches/series lists the patches in the order they apply, and scripts/apply-patches.sh applies them with git apply, which allows no fuzz. The series has 134 patches, and the highest number is 0153. The checkout and build setup are on Build from source.

The patch format

A patch file is a subject line, a description, and the diff:
  • File name. NNNN-area-what-it-does.patch. Number a new patch one above the highest number in patches/. Numbers of removed patches are not reused.
  • Subject. The first line is Subject: [PATCH] area: what it does. The area is the Chromium component or topic the patch changes, such as net, display, speech or compose.
  • Description. After a blank line, say what the patch changes in the terms a page sees, and what stays as in stock Chromium. Write plain sentences and wrap them at about 72 columns.
  • Diff. After another blank line comes the diff, with a/ and b/ paths relative to Chromium’s src directory. git diff output and plain diff -u output both work, and both are in the series.

Write a patch

1

Apply the series

Start from a checkout with the whole series applied:
An earlier patch may already change the file you are about to edit. To see which patches touch a file, search for its path:
No output means no patch touches the file.
2

Copy the files you will edit

Your patch must hold only your change, on top of the series. From the repository root, keep a copy of each file before you edit it:
3

Edit and compile

Edit the file, then compile it with scripts/checkfile.sh (below) until it builds.
4

Write the patch file

Write the subject, the description and the diff into a new file in patches/, then remove the copy:
For a new file, git -C .workspace/src diff --no-index -- /dev/null path/to/new_file.cc writes the diff that creates it. For a file no earlier patch touches, git -C .workspace/src diff -- <path> gives the same diff as the copy. The series also edits v8, third_party/angle, third_party/dawn, third_party/ffmpeg, third_party/swiftshader and third_party/webrtc, which are Git repositories of their own, and git -C .workspace/src diff does not show changes in them. The copy method works for them, with the path still relative to src.
5

Add it to the series

Add the file name to patches/series after every patch it depends on. Order in the series has the rules.
6

Apply the series again

The series changed, so the script runs git checkout -- . in src and in each sub-repository the series edits, removes the files the series creates, and applies all patches in order. It stops at the first patch that does not apply and names it. Any edit in the checkout that no patch records is lost at this step. scripts/build.sh never applies patches, so run this after every change to a patch file, and check that the checkout has your change before you build.
7

Validate

Both run in CI on every pull request. Then compile the series for your target, build, and measure.

Order in the series

scripts/apply-patches.sh applies the entries of patches/series from top to bottom. Blank lines and lines starting with # are ignored. The order follows dependencies, not numbers, and scripts/validate-release-baseline.py --series-only checks these rules:
  • Every patches/*.patch file is listed exactly once, and every listed file exists.
  • Every entry is named NNNN-description.patch, and no number is used twice.
  • A patch that edits or deletes a file comes after the patch that creates it.
  • No two patches create the same file.
  • Entries are in ascending numeric order, except in a group that a # comment introduces. When a dependency moves a patch out of numeric order, put a comment that names the dependency directly above the moved entries, with no blank line between. The group ends at the next blank line or comment.

Hunk headers

A hunk header states how many lines its body covers, and git apply trusts that count. When the header says fewer lines than the body has, it drops the extra lines and still reports that the patch applied. A hand edit that adds or removes lines in a patch body leaves the header wrong. scripts/validate-patch-headers.py recounts every hunk of every listed patch and reports each header that disagrees with its body. --fix rewrites those headers, including the new-side start lines of the hunks that follow in the same file.

Line endings

Patch files are byte-exact. .gitattributes marks *.patch and patches/series as -text, so Git never converts their line endings on any platform. A patch that edits a Chromium file with CRLF line endings carries CRLF on those lines. 0042-audio-portable-neon-profile.patch does, because the vendored rustfft sources under third_party/rust/chromium_crates_io/vendor/rustfft-v6/ use CRLF. Edit such a patch with a tool that keeps the bytes, or regenerate its diff. An editor that normalizes line endings breaks the patch. scripts/test_patch_line_endings.py checks that git apply --check --whitespace=error, with core.whitespace set to blank-at-eol,blank-at-eof,space-before-tab,cr-at-eol, accepts a CRLF line and still rejects trailing spaces and tabs. Use that core.whitespace value when you check a CRLF patch for whitespace errors.

Check a patch before a full build

A full build takes hours. Compiling the files a patch touches takes minutes. Both scripts below need a configured output directory, so run scripts/configure.sh <target> once first. On Linux they run in the build container.

One file

checkfile.sh takes a path inside the Chromium checkout and an optional target, defaulting to the host’s. It looks up the objects that file compiles into in compile_commands.json and asks ninja to build only those, with any generated headers they need. It prints ==> OK <path> compiles on success.

The whole series

checkseries.sh compiles every translation unit the series touches on one target and classifies each one: A file that a target builds no object from must be declared in scripts/series-absences.tsv, one line per file: the path, the targets as comma-separated globs such as windows-*, the category platform or config, and the evidence, such as the BUILD.gn line that scopes the file. A declaration that the run disproves fails the run as stale. When a patch adds source files to a GN list, checkseries.sh also builds the archive of each library the files join and runs scripts/series-symbol-closure.py. It fails when an added object references a symbol that no member of its library defines. Without this check, a missing source file shows up only when the browser links. --list reads the whole build graph. On macOS it classified 159 translation units, 21 of them absent on that platform, in about nine minutes on an Apple M4 Max. CI runs checkseries.sh for linux-x64 and windows-x64 every Monday in series-gate.yml and merges the two reports.

Check a macOS build has your change

On macOS, ninja can leave an older framework inside Chromium.app after a rebuild. Before you measure a change, check that the binary contains a string only your patch adds:
0 means the bundle holds an old build. Delete the bundle and build chrome again in the same directory, which takes seconds: