
* Remove debug code while fetching transitive source as well. Bug: 325113177 Change-Id: I3fc21915a2125cd405e9b0228bf2dee9f7b8aa3e Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/5384427 Commit-Queue: Brendon Tiszka <tiszka@chromium.org> Reviewed-by: Julia Hansbrough <flowerhack@google.com> Cr-Commit-Position: refs/heads/main@{#1276431}
115 lines
4.3 KiB
Python
115 lines
4.3 KiB
Python
# Copyright 2023 The Chromium Authors
|
|
# Use of this source code is governed by a BSD-style license that can be
|
|
# found in the LICENSE file.
|
|
import subprocess
|
|
import multiprocessing
|
|
import functools
|
|
|
|
def _convert_gn_sources_list_to_dict(gn_sources_list, build_dir):
|
|
""" Given a list of gn sources, transform them into standard filepaths and
|
|
place them in a dictionary. """
|
|
outpath_pattern = "//%s/" % build_dir
|
|
gn_sources_dict = {}
|
|
for line in gn_sources_list:
|
|
fixedline = line.replace(outpath_pattern, "").replace("//",
|
|
"../../").strip()
|
|
gn_sources_dict[fixedline] = True
|
|
return gn_sources_dict
|
|
|
|
|
|
def _get_sources_for_gn_target(all_transitive_sources, gn_path, build_dir,
|
|
target_name):
|
|
""" Given a particular target, stores all the source files for that target in
|
|
the given multiprocessing.Manager().dict().
|
|
|
|
Example input:
|
|
Args:
|
|
|
|
target_name: The name of a GN target e.g.
|
|
'//base/allocator/partition_allocator:partition_alloc'
|
|
all_transitive_sources: A multiprocess.Manager().dict().
|
|
|
|
Returns:
|
|
Nothing, but at the end of this function's execution, args[1] will look
|
|
like:
|
|
{
|
|
'//base/allocator/.../atomic_ref_count.h': True,
|
|
'//base/allocator/.../bit_cast.h': True,
|
|
...
|
|
}"""
|
|
if target_name is not None:
|
|
get_sources_command = [gn_path, "desc", build_dir, target_name, "sources"]
|
|
sources_output = subprocess.run(get_sources_command,
|
|
check=False,
|
|
capture_output=True)
|
|
if sources_output.returncode != 0:
|
|
# Some `gn desc` are expected to fail
|
|
# (because there's no `sources` for them).
|
|
pass
|
|
else:
|
|
for file in sources_output.stdout.decode(encoding='utf-8').split("\n"):
|
|
all_transitive_sources[file] = True
|
|
|
|
|
|
def _fetch_all_transitive_sources_for_gn_target(gn_target, build_dir, gn_path):
|
|
"""Fetches a list of all transitive source dependencies for a GN target.
|
|
|
|
For a given GN target and build directory, returns a list with all the
|
|
*transitive sources* upon which that target depends.
|
|
|
|
This list can be useful for constructing a CodeQL database, since that list
|
|
will be the 'minimal set' of commands required to generate a database.
|
|
|
|
Args:
|
|
gn_target: The name of a GN target e.g.
|
|
`//components:components_unittests`.
|
|
build_dir: The relative path to a Chromium build directory e.g.
|
|
`out/release`.
|
|
Returns:
|
|
A list of sources, for example:
|
|
['//base/allocator.../atomic_ref_count.h',
|
|
'//base/allocator/.../partition_alloc_base/bit_cast.h',
|
|
...
|
|
'//ui/platform_window/extensions/workspace_extension.cc',
|
|
...]
|
|
"""
|
|
get_deps_command = [gn_path, "desc", build_dir, gn_target, "deps", "--all"]
|
|
deps_output = subprocess.run(get_deps_command,
|
|
check=True,
|
|
capture_output=True)
|
|
target_names = deps_output.stdout.decode(encoding='utf-8').split("\n")
|
|
my_cpu_count = int(multiprocessing.cpu_count())
|
|
all_transitive_sources = multiprocessing.Manager().dict()
|
|
with multiprocessing.Pool(my_cpu_count) as p:
|
|
p.map(
|
|
functools.partial(_get_sources_for_gn_target, all_transitive_sources,
|
|
gn_path, build_dir), target_names)
|
|
return all_transitive_sources.keys()
|
|
|
|
|
|
def dictionary_of_all_transitive_sources(gn_target, build_dir, gn_path):
|
|
"""Constructs a dictionary of all transitive GN source deps for a target.
|
|
|
|
For a given GN target (e.g. `//components:components_unittests`) and the
|
|
path to some build directory (e.g. `out/release`), outputs a list of all
|
|
*transitive sources* for that GN target, in the form of a dictionary where
|
|
each entry has the value True.
|
|
|
|
Args:
|
|
gn_target: The name of a GN target e.g.
|
|
`//components:components_unittests`.
|
|
build_dir: The relative path to a Chromium build directory e.g.
|
|
`out/release`.
|
|
Returns:
|
|
A dictionary that maps sources to True, for example:
|
|
|
|
{'//base/allocator.../atomic_ref_count.h': True,
|
|
'//base/allocator/.../partition_alloc_base/bit_cast.h': True,
|
|
...
|
|
'//ui/platform_window/extensions/workspace_extension.cc': True,
|
|
...}
|
|
"""
|
|
gn_sources_list = _fetch_all_transitive_sources_for_gn_target(
|
|
gn_target, build_dir, gn_path)
|
|
return _convert_gn_sources_list_to_dict(gn_sources_list, build_dir)
|