xref: /aosp_15_r20/external/cronet/components/cronet/gn2bp/validate_gn2bp.py (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1#!/usr/bin/env python3
2# Copyright 2024 The Chromium Authors
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5import os
6import sys
7import tempfile
8import argparse
9from typing import List, Set
10
11REPOSITORY_ROOT = os.path.abspath(
12    os.path.join(os.path.dirname(__file__), os.pardir, os.pardir, os.pardir))
13
14sys.path.insert(0, REPOSITORY_ROOT)
15import components.cronet.tools.utils as cronet_utils  # pylint: disable=wrong-import-position
16import build.android.gyp.util.build_utils as build_utils  # pylint: disable=wrong-import-position
17
18_ARCHS = ["x86", "x64", "arm", "arm64"]
19_GN2BP_SCRIPT_PATH = os.path.join(REPOSITORY_ROOT,
20                                  "components/cronet/gn2bp/gen_android_bp.py")
21_OUT_DIR = os.path.join(REPOSITORY_ROOT, "out")
22_EXTRA_GN_ARGS = ("is_cronet_for_aosp_build=true"),
23_GN_PATH = os.path.join(REPOSITORY_ROOT, 'buildtools/linux64/gn')
24
25
26def _run_gn2bp(desc_files: Set[tempfile.NamedTemporaryFile]) -> int:
27  with tempfile.NamedTemporaryFile(mode="w+", encoding='utf-8') as android_bp:
28    base_cmd = ["python3", _GN2BP_SCRIPT_PATH, "--out", android_bp.name]
29    for desc_file in desc_files:
30      # desc_file.name represents the absolute path.
31      base_cmd += ["--desc", desc_file.name]
32    return cronet_utils.run(base_cmd)
33
34
35def _get_args_for_aosp(arch: str) -> List[str]:
36  default_args = cronet_utils.get_android_gn_args(True, arch)
37  default_args += _EXTRA_GN_ARGS
38  return ' '.join(cronet_utils.filter_gn_args(default_args,
39                                              ["use_remoteexec"]))
40
41
42def _write_desc_json(gn_out_dir: str,
43                     temp_file: tempfile.NamedTemporaryFile) -> int:
44  return cronet_utils.run([
45      _GN_PATH, "desc", gn_out_dir, "--format=json", "--all-toolchains", "//*"
46  ],
47                          stdout=temp_file)
48
49
50def _main():
51  parser = argparse.ArgumentParser()
52  parser.add_argument('--stamp',
53                      type=str,
54                      help='Path to touch on success',
55                      required=True)
56  args = parser.parse_args()
57  try:
58    # Create empty temp file for each architecture.
59    arch_to_temp_desc_file = {
60        arch: tempfile.NamedTemporaryFile(mode="w+", encoding='utf-8')
61        for arch in _ARCHS
62    }
63
64    for (arch, temp_file) in arch_to_temp_desc_file.items():
65      # gn desc behaves completely differently when the output
66      # directory is outside of chromium/src, some paths will
67      # stop having // in the beginning of their labels
68      # eg (//A/B will become A/B), this mostly apply to files
69      # that are generated through actions and not targets.
70      #
71      # This is why the temporary directory has to be generated
72      # beneath the repository root until gn2bp is tweaked to
73      # deal with this small differences.
74      with tempfile.TemporaryDirectory(dir=_OUT_DIR) as gn_out_dir:
75          cronet_utils.gn(gn_out_dir, _get_args_for_aosp(arch))
76          if _write_desc_json(gn_out_dir, temp_file) != 0:
77            # Close the files and exit if we failed to generate any
78            # of the desc.json files.
79            print(f"Failed to generate desc file for arch: {arch}")
80            for file in arch_to_temp_desc_file.values():
81              # Close the temporary files so they can be deleted.
82              file.close()
83            sys.exit(-1)
84
85    res = _run_gn2bp(arch_to_temp_desc_file.values())
86  finally:
87    for file in arch_to_temp_desc_file.values():
88      # Close the temporary files so they can be deleted.
89      file.close()
90
91  if res != 0:
92    print("Failed to execute gn2bp!")
93    sys.exit(-1)
94  else:
95    build_utils.Touch(args.stamp)
96  return 0
97
98
99if __name__ == '__main__':
100  sys.exit(_main())
101