blob: 6fed64e3113d622f4737815c665dde3dd63e9c1a [file] [edit]
#!/usr/bin/env python3
# allow-non-vendored-python
# Copyright 2026 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.
"""Resolves the active main product bundle name for a Fuchsia build directory.
Uses only the Python standard library so it can be imported by host tools or
invoked directly under system python3 with low startup latency and without
requiring downloaded prebuilts.
"""
from __future__ import annotations
import os
import sys
def resolve_product_bundle_name(
build_dir: str | os.PathLike[str], main_pb_label: str
) -> str | None:
"""Maps a GN product bundle label to its name in product_bundles.json."""
clean_label = main_pb_label.split("(", 1)[0]
if not clean_label:
return None
import json
try:
with open(
os.path.join(os.fspath(build_dir), "product_bundles.json"),
encoding="utf-8",
) as f:
pbs = json.load(f)
except (OSError, ValueError):
return None
if not isinstance(pbs, list):
return None
for pb in pbs:
if not isinstance(pb, dict):
continue
pb_label = pb.get("label")
if (
isinstance(pb_label, str)
and pb_label.split("(", 1)[0] == clean_label
):
name = pb.get("name")
if isinstance(name, str) and name:
return name
return None
def get_main_pb_name(
build_dir: str | os.PathLike[str],
fallback_to_label_name: bool = True,
) -> str | None:
"""Returns the main product bundle name configured in args.json."""
bdir = os.fspath(build_dir)
try:
with open(os.path.join(bdir, "args.json"), encoding="utf-8") as f:
raw_args = f.read()
if '"main_pb_label"' not in raw_args:
return None
import json
args = json.loads(raw_args)
except (OSError, ValueError):
return None
if not isinstance(args, dict):
return None
label = args.get("main_pb_label")
if not isinstance(label, str) or not label:
return None
resolved = resolve_product_bundle_name(bdir, label)
if resolved:
return resolved
if fallback_to_label_name:
fallback = label.split("(", 1)[0].rsplit(":", 1)[-1]
return fallback or None
return None
def main(argv: list[str] | None = None) -> int:
import argparse
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
"--build-dir",
default=os.environ.get("FUCHSIA_BUILD_DIR")
or os.environ.get("FUCHSIA_BUILD_DIR_FROM_FX"),
help="Path to the Fuchsia build directory.",
)
parsed = parser.parse_args(argv)
if not parsed.build_dir:
return 1
name = get_main_pb_name(parsed.build_dir)
if not name:
return 1
print(name)
return 0
if __name__ == "__main__":
sys.exit(main())