lib/depgraph: Add functions to generate some common depgraphs
BUG=chromium:1135361
TEST=manually generated depgraphs
Change-Id: I392dceb91205aef74686385ed99ed080879486a8
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/chromite/+/2575354
Commit-Queue: Alex Klein <saklein@chromium.org>
Tested-by: Alex Klein <saklein@chromium.org>
Reviewed-by: Mike Frysinger <vapier@chromium.org>
diff --git a/lib/constants.py b/lib/constants.py
index 9c764ac..3c05a51 100644
--- a/lib/constants.py
+++ b/lib/constants.py
@@ -415,12 +415,23 @@
MERGE_BRANCH
]
+# SDK target.
+TARGET_SDK = 'virtual/target-sdk'
# Default OS target packages.
TARGET_OS_PKG = 'virtual/target-os'
TARGET_OS_DEV_PKG = 'virtual/target-os-dev'
TARGET_OS_TEST_PKG = 'virtual/target-os-test'
TARGET_OS_FACTORY_PKG = 'virtual/target-os-factory'
TARGET_OS_FACTORY_SHIM_PKG = 'virtual/target-os-factory-shim'
+# The virtuals composing a "full" build, e.g. what's built in the cq.
+# Local (developer) builds only use target-os by default.
+ALL_TARGET_PACKAGES = (
+ TARGET_OS_PKG,
+ TARGET_OS_DEV_PKG,
+ TARGET_OS_TEST_PKG,
+ TARGET_OS_FACTORY_PKG,
+ TARGET_OS_FACTORY_SHIM_PKG,
+)
# Constants for uprevving Chrome
diff --git a/lib/depgraph.py b/lib/depgraph.py
index b844156..f5b16d4 100644
--- a/lib/depgraph.py
+++ b/lib/depgraph.py
@@ -7,12 +7,17 @@
from __future__ import print_function
+import collections
import copy
import os
import sys
import time
+from typing import List, Optional, Union
+from chromite.lib import constants
+from chromite.lib import cros_logging as logging
from chromite.lib import cros_test_lib
+from chromite.lib.parser import package_info
assert sys.version_info >= (3, 6), 'This module requires Python 3.6+'
@@ -854,3 +859,125 @@
print(' %s' % (j))
if not needs:
print(' no dependencies')
+
+
+# Depgraph results data container used by the raw depgraph functions. The
+# deps attribute has the main depgraph info, while the bdeps attribute
+# contains just the bdepends depgraph, i.e. the depgraph installed to the SDK.
+DepgraphResult = collections.namedtuple('DepgraphResult',
+ ('deps', 'bdeps', 'packages'))
+
+
+def _get_emerge_args(sysroot_path: str,
+ packages: Union[List[str], List[package_info.PackageInfo]],
+ include_bdeps: bool) -> List[str]:
+ """Get the default emerge arguments for building a depgraph."""
+ # Pretend: Don't actually install anything.
+ # Emptytree: Act as though nothing is installed (even if some packages are).
+ # Sysroot: Which sysroot we're considering.
+ args = ['--quiet', '--pretend', '--emptytree', '--sysroot', sysroot_path]
+ # Also set the root for DepGraphGenerator specific semantics. This might not
+ # be necessary, pending more investigation.
+ # TODO: Document final reason or remove if unnecessary.
+ args.extend(['--root', sysroot_path])
+ if include_bdeps:
+ args.append('--include-bdepend')
+
+ try:
+ # Assume PackageInfo instance.
+ final_pkgs = [p.atom for p in packages]
+ except AttributeError:
+ # Also accept strings.
+ final_pkgs = [str(p) for p in packages]
+ args.extend(final_pkgs)
+
+ logging.info('Generating depgraph for packages: %s', ', '.join(final_pkgs))
+
+ return args
+
+
+def _get_sysroot_path(
+ sysroot: Union[str, 'sysroot_lib.Sysroot'],
+ build_target: Union[str, 'build_target_lib.BuildTarget']) -> str:
+ """Convenience function to support sysroot paths from a variety of sources.
+
+ Get the sysroot path from a sysroot (the path, or a Sysroot instance), or
+ a build target (by name, or from the BuildTarget instance).
+ """
+ if sysroot:
+ try:
+ return sysroot.path
+ except AttributeError:
+ return sysroot
+ else:
+ try:
+ return build_target.root
+ except AttributeError:
+ return cros_build_lib.GetSysroot(build_target)
+
+
+def _get_raw_sdk_depgraph(
+ packages: Optional[Union[List[str], List[package_info.PackageInfo]]] = None
+) -> DepgraphResult:
+ """Get the depgraph for the SDK itself.
+
+ The SDK deps will contain the packages installed to a fresh SDK.
+ The bdeps will always be empty since everything is installed to the SDK.
+ """
+ sysroot_path = cros_build_lib.GetSysroot(board=None)
+ packages = packages or [constants.TARGET_SDK]
+ lib_argv = _get_emerge_args(sysroot_path, packages, include_bdeps=True)
+ deps = DepGraphGenerator()
+ deps.Initialize(lib_argv)
+ deps_tree, _deps_info, bdeps_tree = deps.GenDependencyTree()
+
+ return DepgraphResult(deps=deps_tree, bdeps=bdeps_tree, packages=packages)
+
+
+def _get_raw_sysroot_depgraph(
+ sysroot: Optional['sysroot_lib.Sysroot'] = None,
+ build_target: Optional['build_target_lib.BuildTarget'] = None,
+ packages: Optional[Union[List[str], List[package_info.PackageInfo]]] = None
+) -> DepgraphResult:
+ """Get the sysroot depgraph for a build target.
+
+ The sysroot deps are the packages installed to a sysroot -- effectively
+ the packages installed on a device. The bdeps contains all the packages
+ installed to the SDK when the board is built. The two graphs are technically
+ disjoint, but packages can appear in both (with different roots).
+ """
+ assert build_target or sysroot
+ packages = packages or constants.ALL_TARGET_PACKAGES
+ sysroot_path = _get_sysroot_path(sysroot, build_target)
+ lib_argv = _get_emerge_args(sysroot_path, packages, include_bdeps=False)
+
+ deps = DepGraphGenerator()
+ deps.Initialize(lib_argv)
+ deps_tree, _deps_info, bdeps_tree = deps.GenDependencyTree()
+
+ return DepgraphResult(deps=deps_tree, bdeps=bdeps_tree, packages=packages)
+
+
+def _get_raw_build_target_depgraph(
+ sysroot: Optional['sysroot_lib.Sysroot'] = None,
+ build_target: Optional['build_target_lib.BuildTarget'] = None,
+ packages: Optional[Union[List[str], List[package_info.PackageInfo]]] = None
+) -> DepgraphResult:
+ """Get the full depgraph for a build target - its sysroot and bdepends.
+
+ The build target deps contains the [r]depends packages installed
+ to the sysroot and bdepends packages installed to the SDK.
+ The bdeps contains only the bdepends packages installed to
+ the SDK. The bdeps graph is a subgraph of the deps graph.
+ """
+ assert build_target or sysroot
+ packages = packages or constants.ALL_TARGET_PACKAGES
+ sysroot_path = _get_sysroot_path(sysroot, build_target)
+ lib_argv = _get_emerge_args(sysroot_path, packages, include_bdeps=True)
+
+ deps = DepGraphGenerator()
+ deps.Initialize(lib_argv)
+
+ deps_tree, _deps_info, bdeps_tree = deps.GenDependencyTree()
+ return DepgraphResult(deps=deps_tree, bdeps=bdeps_tree, packages=packages)
+