mirror of
https://github.com/electron/electron.git
synced 2026-10-28 11:44:46 +08:00
* build: only ship grit resources the binary actually references (Linux) * chore: update patches * build: only pack webxr_internals resources when VR support is enabled webxr_internals_resources.pak is only generated when enable_vr is true (see content/browser/resources/BUILD.gn), which excludes macOS, Windows without checkout_openxr, and 32-bit ARM Linux. * build: enable resource allowlist generation for testing builds Moves enable_resource_allowlist_generation from release.gn to all.gn so that testing builds also generate the allowlist, repack slimmed locale paks, and run the allowlist completeness check. This makes a reference to an unshipped resource fail PR CI instead of the next release build. * build: keep the resource allowlist check stamp out of the dist zip The check target was wired as a data_dep of electron_dist_zip, which puts its stamp output into the runtime deps list that zip.py packs. Use a plain dep instead: the check still gates zip creation but contributes no files. --------- Co-authored-by: PatchUp <73610968+patchup[bot]@users.noreply.github.com>
111 lines
3.9 KiB
Python
111 lines
3.9 KiB
Python
#!/usr/bin/env python3
|
|
"""Verifies that every grit resource referenced by the electron binary is
|
|
present in at least one of the .pak files we ship.
|
|
|
|
The resource allowlist is the set of resource IDs referenced by the binary's
|
|
link inputs (see //electron:electron_resource_allowlist). Any allowlisted ID
|
|
that no shipped .pak provides means native code can ask ResourceBundle for a
|
|
resource that does not exist at runtime -- typically because a .grd was added
|
|
or moved upstream and electron_paks.gni was not updated. That normally ships
|
|
as a silently empty string; this check turns it into a build failure instead.
|
|
"""
|
|
|
|
import argparse
|
|
import glob
|
|
import os
|
|
import re
|
|
import sys
|
|
|
|
|
|
def load_id_names(gen_dir):
|
|
"""Maps resource id -> (name, header) using the grit-generated headers."""
|
|
pattern = re.compile(r'#define (\S+) \(::ui::AllowlistedResource<(\d+)>')
|
|
names = {}
|
|
for header in glob.glob(
|
|
os.path.join(gen_dir, '**', 'grit', '*.h'), recursive=True):
|
|
try:
|
|
with open(header, encoding='utf-8', errors='ignore') as f:
|
|
text = f.read()
|
|
except OSError:
|
|
continue
|
|
rel = os.path.relpath(header, gen_dir)
|
|
for m in pattern.finditer(text):
|
|
names.setdefault(int(m.group(2)), (m.group(1), rel))
|
|
return names
|
|
|
|
|
|
def main():
|
|
parser = argparse.ArgumentParser(description=__doc__)
|
|
parser.add_argument('--allowlist', required=True,
|
|
help='Path to the generated resource allowlist')
|
|
parser.add_argument('--pak', action='append', default=[],
|
|
help='A shipped .pak file (repeatable)')
|
|
parser.add_argument('--gen-dir', required=True,
|
|
help='Root gen dir, used to map ids back to names')
|
|
parser.add_argument('--grit-dir', required=True,
|
|
help='Path to //tools/grit for the data_pack module')
|
|
parser.add_argument('--suppressions',
|
|
help='Optional file of resource names/ids to ignore')
|
|
parser.add_argument('--stamp', required=True, help='Stamp file to touch')
|
|
args = parser.parse_args()
|
|
|
|
sys.path.insert(0, args.grit_dir)
|
|
from grit.format import data_pack
|
|
|
|
with open(args.allowlist) as f:
|
|
allowlisted = {int(line) for line in f.read().split()}
|
|
|
|
shipped = set()
|
|
for pak in args.pak:
|
|
shipped.update(data_pack.ReadDataPack(pak).resources.keys())
|
|
|
|
suppressed_name_globs = []
|
|
suppressed_headers = set()
|
|
suppressed_ids = set()
|
|
if args.suppressions:
|
|
with open(args.suppressions) as f:
|
|
for line in f:
|
|
line = line.split('#', 1)[0].strip()
|
|
if not line:
|
|
continue
|
|
if line.isdigit():
|
|
suppressed_ids.add(int(line))
|
|
elif line.startswith('header:'):
|
|
suppressed_headers.add(line[len('header:'):])
|
|
else:
|
|
suppressed_name_globs.append(line)
|
|
|
|
missing = sorted(allowlisted - shipped - suppressed_ids)
|
|
if missing:
|
|
import fnmatch
|
|
names = load_id_names(args.gen_dir)
|
|
|
|
def is_suppressed(resource_id):
|
|
name, header = names.get(resource_id, ('', ''))
|
|
if header in suppressed_headers:
|
|
return True
|
|
return any(fnmatch.fnmatch(name, glob) for glob in suppressed_name_globs)
|
|
|
|
missing = [m for m in missing if not is_suppressed(m)]
|
|
|
|
if missing:
|
|
print('error: %d resource(s) are referenced by the electron binary but '
|
|
'are not present in any shipped .pak file.' % len(missing),
|
|
file=sys.stderr)
|
|
print('Add the .grd that provides them to build/electron_paks.gni, or, if '
|
|
'the referencing code is genuinely unreachable in Electron, add the '
|
|
'resource name to the suppressions file.\n', file=sys.stderr)
|
|
for resource_id in missing:
|
|
name, header = names.get(resource_id, ('<unknown>', '<unknown header>'))
|
|
print(' %s (id %d) from %s' % (name, resource_id, header),
|
|
file=sys.stderr)
|
|
return 1
|
|
|
|
with open(args.stamp, 'w'):
|
|
pass
|
|
return 0
|
|
|
|
|
|
if __name__ == '__main__':
|
|
sys.exit(main())
|