summaryrefslogtreecommitdiff
path: root/chromium/docs/static_initializers.md
blob: 514caf77dac90efdc7dbc08f0c2197db57908ffb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# Static Initializers

[TOC]

Some background on the original decision to ban static initializers:

http://neugierig.org/software/chromium/notes/2011/08/static-initializers.html

Note: Another name for static initializers is "global constructors".

# How Static Initializers are Checked

* For Linux and Mac:
  * The expected count is stored in [//testing/scripts/check_static_initializers.py](https://source.chromium.org/chromium/chromium/src/+/main:testing/scripts/check_static_initializers.py)
* For Android:
  * The expected count is stored in the build target [//chrome/android:monochrome_static_initializers](https://cs.chromium.org/chromium/src/chrome/android/BUILD.gn)

## Removing Static Initializers

Common fixes include:

* Add constexpr.
* Move global variable to be a static variable within a function that returns
  it, often wrapped in `base::NoDestructor`.

## Listing Static Initializers

### Step 1 - Use objdump to report them
For Linux:

    tools/linux/dump-static-initializers.py out/Release/chrome

For Android (from easiest to hardest):

    # Build with: is_official_build=true is_chrome_branded=true
    # This will dump the list of SI's only when they don't match the expected
    # number in static_initializers.gni (this is what the bots use).
    ninja chrome/android:monochrome_static_initializers
    # or:
    tools/binary_size/diagnose_bloat.py HEAD  # See README.md for flags.
    # or (the other two use this under the hood):
    tools/linux/dump-static-initializers.py --toolchain-prefix third_party/android_ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/arm-linux-androideabi- out/Release/lib.unstripped/libmonochrome.so
    # arm32 ^^ vv arm64
    tools/linux/dump-static-initializers.py --toolchain-prefix third_party/android_ndk/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android- out/Release/lib.unstripped/libmonochrome.so
    # Note: For arm64, having use_thin_lto=true seems to dump a couple extra
    #     initializers that don't actually exist.

The last one may actually be the easiest if you've already properly built
`libmonochrome.so` with `is_official_build=true`.

### Step 2 - Ask compiler to report them

If the source of the new initiazers is not obvious from Step 1, you can ask the
compiler to pinpoint the exact source line.

1. Edit [//build/config/BUILDCONFIG.gn](https://cs.chromium.org/chromium/src/build/config/BUILDCONFIG.gn)
and add `"//build/config/compiler:wglobal_constructors"` to `default_compiler_configs`
2. Remove the config from the `configs` in `//base:base`
3. Set GN arg `treat_warnings_as_errors=false`
4. Compile and look for warnings **from the files identified by step 1** (may want to pipe ninja output to a file).

*** note
The compiler warning triggers for every static initializer that exists
*before optimization*. We care only about those that survive optimization.
More details in [crbug/1136086](https://bugs.chromium.org/p/chromium/issues/detail?id=1136086).
***

* For more information about `diagnose_bloat.py`, refer to its [README.md](/tools/binary_size/README.md#diagnose_bloat.py)
* List of existing static initializers documented in [static_initializers.gni](/chrome/android/static_initializers.gni)