xref: /aosp_15_r20/build/make/tools/aconfig/overrideflags/overrideflags.py (revision 9e94795a3d4ef5c1d47486f9a02bb378756cea8a)
1*9e94795aSAndroid Build Coastguard Worker#!/usr/bin/env python3
2*9e94795aSAndroid Build Coastguard Worker#
3*9e94795aSAndroid Build Coastguard Worker# Copyright (C) 2023 The Android Open Source Project
4*9e94795aSAndroid Build Coastguard Worker#
5*9e94795aSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License");
6*9e94795aSAndroid Build Coastguard Worker# you may not use this file except in compliance with the License.
7*9e94795aSAndroid Build Coastguard Worker# You may obtain a copy of the License at
8*9e94795aSAndroid Build Coastguard Worker#
9*9e94795aSAndroid Build Coastguard Worker#      http://www.apache.org/licenses/LICENSE-2.0
10*9e94795aSAndroid Build Coastguard Worker#
11*9e94795aSAndroid Build Coastguard Worker# Unless required by applicable law or agreed to in writing, software
12*9e94795aSAndroid Build Coastguard Worker# distributed under the License is distributed on an "AS IS" BASIS,
13*9e94795aSAndroid Build Coastguard Worker# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*9e94795aSAndroid Build Coastguard Worker# See the License for the specific language governing permissions and
15*9e94795aSAndroid Build Coastguard Worker# limitations under the License.
16*9e94795aSAndroid Build Coastguard Worker"""Create Aconfig value building rules.
17*9e94795aSAndroid Build Coastguard Worker
18*9e94795aSAndroid Build Coastguard WorkerThis script will help to create Aconfig flag value building rules. It will
19*9e94795aSAndroid Build Coastguard Workerparse necessary information in the value file to create the building rules, but
20*9e94795aSAndroid Build Coastguard Workerit will not validate the value file. The validation will defer to the building
21*9e94795aSAndroid Build Coastguard Workersystem.
22*9e94795aSAndroid Build Coastguard Worker"""
23*9e94795aSAndroid Build Coastguard Worker
24*9e94795aSAndroid Build Coastguard Workerimport argparse
25*9e94795aSAndroid Build Coastguard Workerimport pathlib
26*9e94795aSAndroid Build Coastguard Workerimport re
27*9e94795aSAndroid Build Coastguard Workerimport sys
28*9e94795aSAndroid Build Coastguard Worker
29*9e94795aSAndroid Build Coastguard Worker
30*9e94795aSAndroid Build Coastguard Worker_VALUE_LIST_TEMPLATE: str = """
31*9e94795aSAndroid Build Coastguard WorkerACONFIG_VALUES_LIST_LOCAL = [{}]
32*9e94795aSAndroid Build Coastguard Worker"""
33*9e94795aSAndroid Build Coastguard Worker
34*9e94795aSAndroid Build Coastguard Worker_ACONFIG_VALUES_TEMPLATE: str = """
35*9e94795aSAndroid Build Coastguard Workeraconfig_values {{
36*9e94795aSAndroid Build Coastguard Worker    name: "{}",
37*9e94795aSAndroid Build Coastguard Worker    package: "{}",
38*9e94795aSAndroid Build Coastguard Worker    srcs: [
39*9e94795aSAndroid Build Coastguard Worker        "{}",
40*9e94795aSAndroid Build Coastguard Worker    ]
41*9e94795aSAndroid Build Coastguard Worker}}
42*9e94795aSAndroid Build Coastguard Worker"""
43*9e94795aSAndroid Build Coastguard Worker
44*9e94795aSAndroid Build Coastguard Worker_ACONFIG_VALUES_NAME_SUFFIX: str = "aconfig-local-override-{}"
45*9e94795aSAndroid Build Coastguard Worker
46*9e94795aSAndroid Build Coastguard Worker_PACKAGE_REGEX = re.compile(r"^package\:\s*\"([\w\d\.]+)\"")
47*9e94795aSAndroid Build Coastguard Worker_ANDROID_BP_FILE_NAME = r"Android.bp"
48*9e94795aSAndroid Build Coastguard Worker
49*9e94795aSAndroid Build Coastguard Worker
50*9e94795aSAndroid Build Coastguard Workerdef _parse_packages(file: pathlib.Path) -> set[str]:
51*9e94795aSAndroid Build Coastguard Worker  packages = set()
52*9e94795aSAndroid Build Coastguard Worker  with open(file) as f:
53*9e94795aSAndroid Build Coastguard Worker    for line in f:
54*9e94795aSAndroid Build Coastguard Worker      line = line.strip()
55*9e94795aSAndroid Build Coastguard Worker      package_match = _PACKAGE_REGEX.match(line)
56*9e94795aSAndroid Build Coastguard Worker      if package_match is None:
57*9e94795aSAndroid Build Coastguard Worker        continue
58*9e94795aSAndroid Build Coastguard Worker      package_name = package_match.group(1)
59*9e94795aSAndroid Build Coastguard Worker      packages.add(package_name)
60*9e94795aSAndroid Build Coastguard Worker
61*9e94795aSAndroid Build Coastguard Worker  return packages
62*9e94795aSAndroid Build Coastguard Worker
63*9e94795aSAndroid Build Coastguard Worker
64*9e94795aSAndroid Build Coastguard Workerdef _create_android_bp(packages: set[str], file_name: str) -> str:
65*9e94795aSAndroid Build Coastguard Worker  android_bp = ""
66*9e94795aSAndroid Build Coastguard Worker  value_list = ",\n    ".join(
67*9e94795aSAndroid Build Coastguard Worker      map(f'"{_ACONFIG_VALUES_NAME_SUFFIX}"'.format, packages)
68*9e94795aSAndroid Build Coastguard Worker  )
69*9e94795aSAndroid Build Coastguard Worker  if value_list:
70*9e94795aSAndroid Build Coastguard Worker    value_list = "\n    " + value_list + "\n"
71*9e94795aSAndroid Build Coastguard Worker  android_bp += _VALUE_LIST_TEMPLATE.format(value_list) + "\n"
72*9e94795aSAndroid Build Coastguard Worker
73*9e94795aSAndroid Build Coastguard Worker  for package in packages:
74*9e94795aSAndroid Build Coastguard Worker    android_bp += _ACONFIG_VALUES_TEMPLATE.format(
75*9e94795aSAndroid Build Coastguard Worker        _ACONFIG_VALUES_NAME_SUFFIX.format(package), package, file_name
76*9e94795aSAndroid Build Coastguard Worker    )
77*9e94795aSAndroid Build Coastguard Worker    android_bp += "\n"
78*9e94795aSAndroid Build Coastguard Worker
79*9e94795aSAndroid Build Coastguard Worker  return android_bp
80*9e94795aSAndroid Build Coastguard Worker
81*9e94795aSAndroid Build Coastguard Worker
82*9e94795aSAndroid Build Coastguard Workerdef _write_android_bp(new_android_bp: str, out: pathlib.Path) -> None:
83*9e94795aSAndroid Build Coastguard Worker  if not out.is_dir():
84*9e94795aSAndroid Build Coastguard Worker    out.mkdir(parents=True, exist_ok=True)
85*9e94795aSAndroid Build Coastguard Worker
86*9e94795aSAndroid Build Coastguard Worker  output = out.joinpath(_ANDROID_BP_FILE_NAME)
87*9e94795aSAndroid Build Coastguard Worker  with open(output, "r+", encoding="utf8") as file:
88*9e94795aSAndroid Build Coastguard Worker    lines = []
89*9e94795aSAndroid Build Coastguard Worker    for line in file:
90*9e94795aSAndroid Build Coastguard Worker      line = line.rstrip("\n")
91*9e94795aSAndroid Build Coastguard Worker      if line.startswith("ACONFIG_VALUES_LIST_LOCAL"):
92*9e94795aSAndroid Build Coastguard Worker        break
93*9e94795aSAndroid Build Coastguard Worker      lines.append(line)
94*9e94795aSAndroid Build Coastguard Worker    # Overwrite the file with the updated contents.
95*9e94795aSAndroid Build Coastguard Worker    file.seek(0)
96*9e94795aSAndroid Build Coastguard Worker    file.truncate()
97*9e94795aSAndroid Build Coastguard Worker    file.write("\n".join(lines))
98*9e94795aSAndroid Build Coastguard Worker    file.write(new_android_bp)
99*9e94795aSAndroid Build Coastguard Worker
100*9e94795aSAndroid Build Coastguard Worker
101*9e94795aSAndroid Build Coastguard Workerdef main(args):
102*9e94795aSAndroid Build Coastguard Worker  """Program entry point."""
103*9e94795aSAndroid Build Coastguard Worker  args_parser = argparse.ArgumentParser()
104*9e94795aSAndroid Build Coastguard Worker  args_parser.add_argument(
105*9e94795aSAndroid Build Coastguard Worker      "--overrides",
106*9e94795aSAndroid Build Coastguard Worker      required=True,
107*9e94795aSAndroid Build Coastguard Worker      help="The path to override file.",
108*9e94795aSAndroid Build Coastguard Worker  )
109*9e94795aSAndroid Build Coastguard Worker  args_parser.add_argument(
110*9e94795aSAndroid Build Coastguard Worker      "--out",
111*9e94795aSAndroid Build Coastguard Worker      required=True,
112*9e94795aSAndroid Build Coastguard Worker      help="The path to output directory.",
113*9e94795aSAndroid Build Coastguard Worker  )
114*9e94795aSAndroid Build Coastguard Worker
115*9e94795aSAndroid Build Coastguard Worker  args = args_parser.parse_args(args)
116*9e94795aSAndroid Build Coastguard Worker  file = pathlib.Path(args.overrides)
117*9e94795aSAndroid Build Coastguard Worker  out = pathlib.Path(args.out)
118*9e94795aSAndroid Build Coastguard Worker  if not file.is_file():
119*9e94795aSAndroid Build Coastguard Worker    raise FileNotFoundError(f"File '{file}' is not found")
120*9e94795aSAndroid Build Coastguard Worker
121*9e94795aSAndroid Build Coastguard Worker  packages = _parse_packages(file)
122*9e94795aSAndroid Build Coastguard Worker  new_android_bp = _create_android_bp(packages, file.name)
123*9e94795aSAndroid Build Coastguard Worker  _write_android_bp(new_android_bp, out)
124*9e94795aSAndroid Build Coastguard Worker
125*9e94795aSAndroid Build Coastguard Worker
126*9e94795aSAndroid Build Coastguard Workerif __name__ == "__main__":
127*9e94795aSAndroid Build Coastguard Worker  main(sys.argv[1:])
128