blob: 242d06f82934195a67c6d22f2ac7f0866f1dba8c [file] [log] [blame] [edit]
#!/usr/bin/env fuchsia-vendored-python
# Copyright 2023 The Fuchsia Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
import argparse
import dataclasses
import os
import re
from typing import TextIO
from assembly import AssemblyInputBundle, PackageManifest
from depfile import DepFile
from serialization.serialization import json_load
_RUST_LIBSTD_RE = re.compile("lib\/libstd-[a-z0-9]+\.so")
_RUST_LIBSTD_WILDCARD = "lib/libstd-*"
@dataclasses.dataclass
class CollectedArtifacts(object):
static_packages: set[str]
bootfs_packages: set[str]
bootfs_files: set[str]
kernel_cmdline: set[str]
deps: list[str]
def collect_aib_artifacts(
aib: AssemblyInputBundle, aib_path: str
) -> CollectedArtifacts:
static_packages = set()
bootfs_packages = set()
for pkg in aib.packages:
package_str = str(pkg.package)
if pkg.set == "base":
name = package_str.removeprefix("packages/")
static_packages.add(name)
elif pkg.set == "cache":
name = package_str.removeprefix("packages/")
static_packages.add(name)
elif pkg.set == "flexible":
name = package_str.removeprefix("packages/")
static_packages.add(name)
elif pkg.set == "bootfs":
name = package_str.removeprefix("packages/")
bootfs_packages.add(name)
for base_driver in aib.base_drivers:
name = str(base_driver.package).removeprefix("packages/")
static_packages.add(name)
for boot_driver in aib.boot_drivers:
name = str(boot_driver.package).removeprefix("packages/")
bootfs_packages.add(name)
bootfs_files = set()
deps = []
if aib.bootfs_files_package:
manifest_path = os.path.join(aib_path, aib.bootfs_files_package)
deps.append(manifest_path)
with open(manifest_path, "r") as f:
manifest = json_load(PackageManifest, f)
for blob in manifest.blobs:
blob_path = str(blob.path)
if blob_path.startswith("meta/"):
continue
path = blob_path.removeprefix("bootfs/")
bootfs_files.add(path)
cmdline = set()
cmdline.update(aib.kernel.args)
cmdline.update(aib.boot_args)
return CollectedArtifacts(
static_packages, bootfs_packages, bootfs_files, cmdline, deps
)
class Golden:
def __init__(self) -> None:
self.lines: set[str] = set()
def add_optional(self, names: set[str]) -> None:
for name in names:
name = name.strip()
if name not in self.lines:
self.lines.add("?" + name)
def add_required(self, names: set[str]) -> None:
for name in names:
name = name.strip()
optional = "?" + name
if optional in self.lines:
self.lines.remove(optional)
if _RUST_LIBSTD_RE.match(name):
name = _RUST_LIBSTD_WILDCARD
self.lines.add(name)
def write(self, output: TextIO) -> None:
lines = sorted(self.lines, key=lambda s: s.removeprefix("?"))
for line in lines:
output.write(line + "\n")
def main() -> int:
parser = argparse.ArgumentParser(
description="Tool that parses AIBs and generates relevant scrutiny configs for the platform"
)
parser.add_argument(
"--assembly-input-bundles",
nargs="+",
type=argparse.FileType("r"),
help="Path to an assembly input bundle config to search for artifacts",
)
parser.add_argument(
"--required-assembly-input-bundles",
nargs="+",
type=argparse.FileType("r"),
help="Path to an assembly input bundle config to search for artifacts",
)
parser.add_argument(
"--static-packages-input",
type=argparse.FileType("r"),
help="Optional static packages to merge in",
)
parser.add_argument(
"--bootfs-packages-input",
type=argparse.FileType("r"),
help="Optional bootfs packages to merge in",
)
parser.add_argument(
"--bootfs-files-input",
type=argparse.FileType("r"),
help="Optional list of bootfs packages to merge in",
)
parser.add_argument(
"--kernel-args-input",
type=argparse.FileType("r"),
help="Optional list of kernel arguments to merge in",
)
parser.add_argument(
"--static-packages-output",
required=True,
type=argparse.FileType("w"),
help="Path to the output list of static packages",
)
parser.add_argument(
"--bootfs-packages-output",
required=True,
type=argparse.FileType("w"),
help="Path to the output list of bootfs packages",
)
parser.add_argument(
"--bootfs-files-output",
required=True,
type=argparse.FileType("w"),
help="Path to the output list of bootfs files",
)
parser.add_argument(
"--kernel-cmdline-output",
required=True,
type=argparse.FileType("w"),
help="Path to the output list of kernel cmdlines",
)
parser.add_argument(
"--depfile",
type=argparse.FileType("w"),
)
args = parser.parse_args()
deps = []
static_packages = Golden()
bootfs_packages = Golden()
bootfs_files = Golden()
kernel_cmdline = Golden()
for file in args.assembly_input_bundles:
aib_path = os.path.dirname(file.name)
aib = json_load(AssemblyInputBundle, file)
artifacts = collect_aib_artifacts(aib, aib_path)
deps.extend(artifacts.deps)
static_packages.add_optional(artifacts.static_packages)
bootfs_packages.add_optional(artifacts.bootfs_packages)
bootfs_files.add_optional(artifacts.bootfs_files)
kernel_cmdline.add_optional(artifacts.kernel_cmdline)
for file in args.required_assembly_input_bundles:
aib_path = os.path.dirname(file.name)
aib = json_load(AssemblyInputBundle, file)
artifacts = collect_aib_artifacts(aib, aib_path)
deps.extend(artifacts.deps)
static_packages.add_required(artifacts.static_packages)
bootfs_packages.add_required(artifacts.bootfs_packages)
bootfs_files.add_required(artifacts.bootfs_files)
kernel_cmdline.add_required(artifacts.kernel_cmdline)
# Merge in the optional input goldens.
if args.static_packages_input:
static_packages.add_optional(args.static_packages_input.readlines())
if args.bootfs_packages_input:
bootfs_packages.add_optional(args.bootfs_packages_input.readlines())
if args.bootfs_files_input:
bootfs_files.add_optional(args.bootfs_files_input.readlines())
if args.kernel_args_input:
kernel_cmdline.add_optional(args.kernel_args_input.readlines())
with args.static_packages_output as static_packages_output:
static_packages.write(static_packages_output)
with args.bootfs_packages_output as bootfs_packages_output:
bootfs_packages.write(bootfs_packages_output)
with args.bootfs_files_output as bootfs_files_output:
bootfs_files.write(bootfs_files_output)
with args.kernel_cmdline_output as kernel_cmdline_output:
kernel_cmdline.write(kernel_cmdline_output)
if args.depfile:
with args.depfile as depfile:
DepFile.from_deps(args.static_packages_output.name, deps).write_to(
depfile
)
return 0