blob: f5876ddedbbf02957998b6a09425f8fdd1cab7a5 [file] [log] [blame] [edit]
# Copyright 2023 The ChromiumOS Authors
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
def add_install_groups(args, install_groups):
"""
Adds --install-target to the command-line for a list of install groups.
Args:
args: ctx.actions.Args: Args to add the install groups to.
group: list[list[BinaryPackageInfo]]: A list of install groups.
"""
for group in install_groups:
args.add_joined(
"--install-target",
[binpkg.file for binpkg in group],
join_with = ":",
)
def calculate_install_groups(install_list, provided_packages):
"""
Splits a package set to install groups and pre-installed layers.
Args:
install_list: list[BinaryPackageInfo]: A list of packages to install.
This list must be closed over transitive runtime dependencies.
provided_packages: depset(BinaryPackageInfo): The packages that have
already been installed in previous SDK layers. These packages will
be filtered out.
Returns:
list[list[BinaryPackageInfo]]: An ordered list containing a list of
packages that can be installed in parallel.
"""
# The size of provided packages is normally expected to be O(~20) or less.
seen = {dep.file.path: True for dep in provided_packages.to_list()}
remaining_packages = [dep for dep in install_list if dep.file.path not in seen]
groups = []
for _ in range(100):
if len(remaining_packages) == 0:
break
satisfied_list = []
not_satisfied_list = []
for package in remaining_packages:
all_seen = True
for dep in package.direct_runtime_deps:
if dep.path not in seen:
all_seen = False
break
if all_seen:
satisfied_list.append(package)
else:
not_satisfied_list.append(package)
if len(satisfied_list) == 0:
fail("Dependency list is unsatisfiable")
for dep in satisfied_list:
seen[dep.file.path] = True
groups.append(satisfied_list)
remaining_packages = not_satisfied_list
if len(remaining_packages) > 0:
fail("Too many dependencies")
return groups