xref: /aosp_15_r20/external/cronet/third_party/abseil-cpp/absl/abseil.podspec.gen.py (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker#!/usr/bin/env python3
2*6777b538SAndroid Build Coastguard Worker# -*- coding: utf-8 -*-
3*6777b538SAndroid Build Coastguard Worker"""This script generates abseil.podspec from all BUILD.bazel files.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard WorkerThis is expected to run on abseil git repository with Bazel 1.0 on Linux.
6*6777b538SAndroid Build Coastguard WorkerIt recursively analyzes BUILD.bazel files using query command of Bazel to
7*6777b538SAndroid Build Coastguard Workerdump its build rules in XML format. From these rules, it constructs podspec
8*6777b538SAndroid Build Coastguard Workerstructure.
9*6777b538SAndroid Build Coastguard Worker"""
10*6777b538SAndroid Build Coastguard Worker
11*6777b538SAndroid Build Coastguard Workerimport argparse
12*6777b538SAndroid Build Coastguard Workerimport collections
13*6777b538SAndroid Build Coastguard Workerimport os
14*6777b538SAndroid Build Coastguard Workerimport re
15*6777b538SAndroid Build Coastguard Workerimport subprocess
16*6777b538SAndroid Build Coastguard Workerimport xml.etree.ElementTree
17*6777b538SAndroid Build Coastguard Worker
18*6777b538SAndroid Build Coastguard Worker# Template of root podspec.
19*6777b538SAndroid Build Coastguard WorkerSPEC_TEMPLATE = """
20*6777b538SAndroid Build Coastguard Worker# This file has been automatically generated from a script.
21*6777b538SAndroid Build Coastguard Worker# Please make modifications to `abseil.podspec.gen.py` instead.
22*6777b538SAndroid Build Coastguard WorkerPod::Spec.new do |s|
23*6777b538SAndroid Build Coastguard Worker  s.name     = 'abseil'
24*6777b538SAndroid Build Coastguard Worker  s.version  = '${version}'
25*6777b538SAndroid Build Coastguard Worker  s.summary  = 'Abseil Common Libraries (C++) from Google'
26*6777b538SAndroid Build Coastguard Worker  s.homepage = 'https://abseil.io'
27*6777b538SAndroid Build Coastguard Worker  s.license  = 'Apache License, Version 2.0'
28*6777b538SAndroid Build Coastguard Worker  s.authors  = { 'Abseil Team' => '[email protected]' }
29*6777b538SAndroid Build Coastguard Worker  s.source = {
30*6777b538SAndroid Build Coastguard Worker    :git => 'https://github.com/abseil/abseil-cpp.git',
31*6777b538SAndroid Build Coastguard Worker    :tag => '${tag}',
32*6777b538SAndroid Build Coastguard Worker  }
33*6777b538SAndroid Build Coastguard Worker  s.resource_bundles = {
34*6777b538SAndroid Build Coastguard Worker    s.module_name => 'PrivacyInfo.xcprivacy',
35*6777b538SAndroid Build Coastguard Worker  }
36*6777b538SAndroid Build Coastguard Worker  s.module_name = 'absl'
37*6777b538SAndroid Build Coastguard Worker  s.header_mappings_dir = 'absl'
38*6777b538SAndroid Build Coastguard Worker  s.header_dir = 'absl'
39*6777b538SAndroid Build Coastguard Worker  s.libraries = 'c++'
40*6777b538SAndroid Build Coastguard Worker  s.compiler_flags = '-Wno-everything'
41*6777b538SAndroid Build Coastguard Worker  s.pod_target_xcconfig = {
42*6777b538SAndroid Build Coastguard Worker    'USER_HEADER_SEARCH_PATHS' => '$(inherited) "$(PODS_TARGET_SRCROOT)"',
43*6777b538SAndroid Build Coastguard Worker    'USE_HEADERMAP' => 'NO',
44*6777b538SAndroid Build Coastguard Worker    'ALWAYS_SEARCH_USER_PATHS' => 'NO',
45*6777b538SAndroid Build Coastguard Worker  }
46*6777b538SAndroid Build Coastguard Worker  s.ios.deployment_target = '9.0'
47*6777b538SAndroid Build Coastguard Worker  s.osx.deployment_target = '10.11'
48*6777b538SAndroid Build Coastguard Worker  s.tvos.deployment_target = '9.0'
49*6777b538SAndroid Build Coastguard Worker  s.watchos.deployment_target = '2.0'
50*6777b538SAndroid Build Coastguard Worker  s.subspec 'xcprivacy' do |ss|
51*6777b538SAndroid Build Coastguard Worker    ss.resource_bundles = {
52*6777b538SAndroid Build Coastguard Worker      ss.module_name => 'PrivacyInfo.xcprivacy',
53*6777b538SAndroid Build Coastguard Worker    }
54*6777b538SAndroid Build Coastguard Worker  end
55*6777b538SAndroid Build Coastguard Worker"""
56*6777b538SAndroid Build Coastguard Worker
57*6777b538SAndroid Build Coastguard Worker# Rule object representing the rule of Bazel BUILD.
58*6777b538SAndroid Build Coastguard WorkerRule = collections.namedtuple(
59*6777b538SAndroid Build Coastguard Worker    "Rule", "type name package srcs hdrs textual_hdrs deps visibility testonly")
60*6777b538SAndroid Build Coastguard Worker
61*6777b538SAndroid Build Coastguard Worker
62*6777b538SAndroid Build Coastguard Workerdef get_elem_value(elem, name):
63*6777b538SAndroid Build Coastguard Worker  """Returns the value of XML element with the given name."""
64*6777b538SAndroid Build Coastguard Worker  for child in elem:
65*6777b538SAndroid Build Coastguard Worker    if child.attrib.get("name") != name:
66*6777b538SAndroid Build Coastguard Worker      continue
67*6777b538SAndroid Build Coastguard Worker    if child.tag == "string":
68*6777b538SAndroid Build Coastguard Worker      return child.attrib.get("value")
69*6777b538SAndroid Build Coastguard Worker    if child.tag == "boolean":
70*6777b538SAndroid Build Coastguard Worker      return child.attrib.get("value") == "true"
71*6777b538SAndroid Build Coastguard Worker    if child.tag == "list":
72*6777b538SAndroid Build Coastguard Worker      return [nested_child.attrib.get("value") for nested_child in child]
73*6777b538SAndroid Build Coastguard Worker    raise "Cannot recognize tag: " + child.tag
74*6777b538SAndroid Build Coastguard Worker  return None
75*6777b538SAndroid Build Coastguard Worker
76*6777b538SAndroid Build Coastguard Worker
77*6777b538SAndroid Build Coastguard Workerdef normalize_paths(paths):
78*6777b538SAndroid Build Coastguard Worker  """Returns the list of normalized path."""
79*6777b538SAndroid Build Coastguard Worker  # e.g. ["//absl/strings:dir/header.h"] -> ["absl/strings/dir/header.h"]
80*6777b538SAndroid Build Coastguard Worker  return [path.lstrip("/").replace(":", "/") for path in paths]
81*6777b538SAndroid Build Coastguard Worker
82*6777b538SAndroid Build Coastguard Worker
83*6777b538SAndroid Build Coastguard Workerdef parse_rule(elem, package):
84*6777b538SAndroid Build Coastguard Worker  """Returns a rule from bazel XML rule."""
85*6777b538SAndroid Build Coastguard Worker  return Rule(
86*6777b538SAndroid Build Coastguard Worker      type=elem.attrib["class"],
87*6777b538SAndroid Build Coastguard Worker      name=get_elem_value(elem, "name"),
88*6777b538SAndroid Build Coastguard Worker      package=package,
89*6777b538SAndroid Build Coastguard Worker      srcs=normalize_paths(get_elem_value(elem, "srcs") or []),
90*6777b538SAndroid Build Coastguard Worker      hdrs=normalize_paths(get_elem_value(elem, "hdrs") or []),
91*6777b538SAndroid Build Coastguard Worker      textual_hdrs=normalize_paths(get_elem_value(elem, "textual_hdrs") or []),
92*6777b538SAndroid Build Coastguard Worker      deps=get_elem_value(elem, "deps") or [],
93*6777b538SAndroid Build Coastguard Worker      visibility=get_elem_value(elem, "visibility") or [],
94*6777b538SAndroid Build Coastguard Worker      testonly=get_elem_value(elem, "testonly") or False)
95*6777b538SAndroid Build Coastguard Worker
96*6777b538SAndroid Build Coastguard Worker
97*6777b538SAndroid Build Coastguard Workerdef read_build(package):
98*6777b538SAndroid Build Coastguard Worker  """Runs bazel query on given package file and returns all cc rules."""
99*6777b538SAndroid Build Coastguard Worker  result = subprocess.check_output(
100*6777b538SAndroid Build Coastguard Worker      ["bazel", "query", package + ":all", "--output", "xml"])
101*6777b538SAndroid Build Coastguard Worker  root = xml.etree.ElementTree.fromstring(result)
102*6777b538SAndroid Build Coastguard Worker  return [
103*6777b538SAndroid Build Coastguard Worker      parse_rule(elem, package)
104*6777b538SAndroid Build Coastguard Worker      for elem in root
105*6777b538SAndroid Build Coastguard Worker      if elem.tag == "rule" and elem.attrib["class"].startswith("cc_")
106*6777b538SAndroid Build Coastguard Worker  ]
107*6777b538SAndroid Build Coastguard Worker
108*6777b538SAndroid Build Coastguard Worker
109*6777b538SAndroid Build Coastguard Workerdef collect_rules(root_path):
110*6777b538SAndroid Build Coastguard Worker  """Collects and returns all rules from root path recursively."""
111*6777b538SAndroid Build Coastguard Worker  rules = []
112*6777b538SAndroid Build Coastguard Worker  for cur, _, _ in os.walk(root_path):
113*6777b538SAndroid Build Coastguard Worker    build_path = os.path.join(cur, "BUILD.bazel")
114*6777b538SAndroid Build Coastguard Worker    if os.path.exists(build_path):
115*6777b538SAndroid Build Coastguard Worker      rules.extend(read_build("//" + cur))
116*6777b538SAndroid Build Coastguard Worker  return rules
117*6777b538SAndroid Build Coastguard Worker
118*6777b538SAndroid Build Coastguard Worker
119*6777b538SAndroid Build Coastguard Workerdef relevant_rule(rule):
120*6777b538SAndroid Build Coastguard Worker  """Returns true if a given rule is relevant when generating a podspec."""
121*6777b538SAndroid Build Coastguard Worker  return (
122*6777b538SAndroid Build Coastguard Worker      # cc_library only (ignore cc_test, cc_binary)
123*6777b538SAndroid Build Coastguard Worker      rule.type == "cc_library" and
124*6777b538SAndroid Build Coastguard Worker      # ignore empty rule
125*6777b538SAndroid Build Coastguard Worker      (rule.hdrs + rule.textual_hdrs + rule.srcs) and
126*6777b538SAndroid Build Coastguard Worker      # ignore test-only rule
127*6777b538SAndroid Build Coastguard Worker      not rule.testonly)
128*6777b538SAndroid Build Coastguard Worker
129*6777b538SAndroid Build Coastguard Worker
130*6777b538SAndroid Build Coastguard Workerdef get_spec_var(depth):
131*6777b538SAndroid Build Coastguard Worker  """Returns the name of variable for spec with given depth."""
132*6777b538SAndroid Build Coastguard Worker  return "s" if depth == 0 else "s{}".format(depth)
133*6777b538SAndroid Build Coastguard Worker
134*6777b538SAndroid Build Coastguard Worker
135*6777b538SAndroid Build Coastguard Workerdef get_spec_name(label):
136*6777b538SAndroid Build Coastguard Worker  """Converts the label of bazel rule to the name of podspec."""
137*6777b538SAndroid Build Coastguard Worker  assert label.startswith("//absl/"), "{} doesn't start with //absl/".format(
138*6777b538SAndroid Build Coastguard Worker      label)
139*6777b538SAndroid Build Coastguard Worker  # e.g. //absl/apple/banana -> abseil/apple/banana
140*6777b538SAndroid Build Coastguard Worker  return "abseil/" + label[7:]
141*6777b538SAndroid Build Coastguard Worker
142*6777b538SAndroid Build Coastguard Worker
143*6777b538SAndroid Build Coastguard Workerdef write_podspec(f, rules, args):
144*6777b538SAndroid Build Coastguard Worker  """Writes a podspec from given rules and args."""
145*6777b538SAndroid Build Coastguard Worker  rule_dir = build_rule_directory(rules)["abseil"]
146*6777b538SAndroid Build Coastguard Worker  # Write root part with given arguments
147*6777b538SAndroid Build Coastguard Worker  spec = re.sub(r"\$\{(\w+)\}", lambda x: args[x.group(1)],
148*6777b538SAndroid Build Coastguard Worker                SPEC_TEMPLATE).lstrip()
149*6777b538SAndroid Build Coastguard Worker  f.write(spec)
150*6777b538SAndroid Build Coastguard Worker  # Write all target rules
151*6777b538SAndroid Build Coastguard Worker  write_podspec_map(f, rule_dir, 0)
152*6777b538SAndroid Build Coastguard Worker  f.write("end\n")
153*6777b538SAndroid Build Coastguard Worker
154*6777b538SAndroid Build Coastguard Worker
155*6777b538SAndroid Build Coastguard Workerdef build_rule_directory(rules):
156*6777b538SAndroid Build Coastguard Worker  """Builds a tree-style rule directory from given rules."""
157*6777b538SAndroid Build Coastguard Worker  rule_dir = {}
158*6777b538SAndroid Build Coastguard Worker  for rule in rules:
159*6777b538SAndroid Build Coastguard Worker    cur = rule_dir
160*6777b538SAndroid Build Coastguard Worker    for frag in get_spec_name(rule.package).split("/"):
161*6777b538SAndroid Build Coastguard Worker      cur = cur.setdefault(frag, {})
162*6777b538SAndroid Build Coastguard Worker    cur[rule.name] = rule
163*6777b538SAndroid Build Coastguard Worker  return rule_dir
164*6777b538SAndroid Build Coastguard Worker
165*6777b538SAndroid Build Coastguard Worker
166*6777b538SAndroid Build Coastguard Workerdef write_podspec_map(f, cur_map, depth):
167*6777b538SAndroid Build Coastguard Worker  """Writes podspec from rule map recursively."""
168*6777b538SAndroid Build Coastguard Worker  for key, value in sorted(cur_map.items()):
169*6777b538SAndroid Build Coastguard Worker    indent = "  " * (depth + 1)
170*6777b538SAndroid Build Coastguard Worker    f.write("{indent}{var0}.subspec '{key}' do |{var1}|\n".format(
171*6777b538SAndroid Build Coastguard Worker        indent=indent,
172*6777b538SAndroid Build Coastguard Worker        key=key,
173*6777b538SAndroid Build Coastguard Worker        var0=get_spec_var(depth),
174*6777b538SAndroid Build Coastguard Worker        var1=get_spec_var(depth + 1)))
175*6777b538SAndroid Build Coastguard Worker    if isinstance(value, dict):
176*6777b538SAndroid Build Coastguard Worker      write_podspec_map(f, value, depth + 1)
177*6777b538SAndroid Build Coastguard Worker    else:
178*6777b538SAndroid Build Coastguard Worker      write_podspec_rule(f, value, depth + 1)
179*6777b538SAndroid Build Coastguard Worker    f.write("{indent}end\n".format(indent=indent))
180*6777b538SAndroid Build Coastguard Worker
181*6777b538SAndroid Build Coastguard Worker
182*6777b538SAndroid Build Coastguard Workerdef write_podspec_rule(f, rule, depth):
183*6777b538SAndroid Build Coastguard Worker  """Writes podspec from given rule."""
184*6777b538SAndroid Build Coastguard Worker  indent = "  " * (depth + 1)
185*6777b538SAndroid Build Coastguard Worker  spec_var = get_spec_var(depth)
186*6777b538SAndroid Build Coastguard Worker  # Puts all files in hdrs, textual_hdrs, and srcs into source_files.
187*6777b538SAndroid Build Coastguard Worker  # Since CocoaPods treats header_files a bit differently from bazel,
188*6777b538SAndroid Build Coastguard Worker  # this won't generate a header_files field so that all source_files
189*6777b538SAndroid Build Coastguard Worker  # are considered as header files.
190*6777b538SAndroid Build Coastguard Worker  srcs = sorted(set(rule.hdrs + rule.textual_hdrs + rule.srcs))
191*6777b538SAndroid Build Coastguard Worker  write_indented_list(
192*6777b538SAndroid Build Coastguard Worker      f, "{indent}{var}.source_files = ".format(indent=indent, var=spec_var),
193*6777b538SAndroid Build Coastguard Worker      srcs)
194*6777b538SAndroid Build Coastguard Worker  # Writes dependencies of this rule.
195*6777b538SAndroid Build Coastguard Worker  for dep in sorted(rule.deps):
196*6777b538SAndroid Build Coastguard Worker    name = get_spec_name(dep.replace(":", "/"))
197*6777b538SAndroid Build Coastguard Worker    f.write("{indent}{var}.dependency '{dep}'\n".format(
198*6777b538SAndroid Build Coastguard Worker        indent=indent, var=spec_var, dep=name))
199*6777b538SAndroid Build Coastguard Worker  # Writes dependency to xcprivacy
200*6777b538SAndroid Build Coastguard Worker  f.write(
201*6777b538SAndroid Build Coastguard Worker      "{indent}{var}.dependency '{dep}'\n".format(
202*6777b538SAndroid Build Coastguard Worker          indent=indent, var=spec_var, dep="abseil/xcprivacy"
203*6777b538SAndroid Build Coastguard Worker      )
204*6777b538SAndroid Build Coastguard Worker  )
205*6777b538SAndroid Build Coastguard Worker
206*6777b538SAndroid Build Coastguard Worker
207*6777b538SAndroid Build Coastguard Workerdef write_indented_list(f, leading, values):
208*6777b538SAndroid Build Coastguard Worker  """Writes leading values in an indented style."""
209*6777b538SAndroid Build Coastguard Worker  f.write(leading)
210*6777b538SAndroid Build Coastguard Worker  f.write((",\n" + " " * len(leading)).join("'{}'".format(v) for v in values))
211*6777b538SAndroid Build Coastguard Worker  f.write("\n")
212*6777b538SAndroid Build Coastguard Worker
213*6777b538SAndroid Build Coastguard Worker
214*6777b538SAndroid Build Coastguard Workerdef generate(args):
215*6777b538SAndroid Build Coastguard Worker  """Generates a podspec file from all BUILD files under absl directory."""
216*6777b538SAndroid Build Coastguard Worker  rules = filter(relevant_rule, collect_rules("absl"))
217*6777b538SAndroid Build Coastguard Worker  with open(args.output, "wt") as f:
218*6777b538SAndroid Build Coastguard Worker    write_podspec(f, rules, vars(args))
219*6777b538SAndroid Build Coastguard Worker
220*6777b538SAndroid Build Coastguard Worker
221*6777b538SAndroid Build Coastguard Workerdef main():
222*6777b538SAndroid Build Coastguard Worker  parser = argparse.ArgumentParser(
223*6777b538SAndroid Build Coastguard Worker      description="Generates abseil.podspec from BUILD.bazel")
224*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
225*6777b538SAndroid Build Coastguard Worker      "-v", "--version", help="The version of podspec", required=True)
226*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
227*6777b538SAndroid Build Coastguard Worker      "-t",
228*6777b538SAndroid Build Coastguard Worker      "--tag",
229*6777b538SAndroid Build Coastguard Worker      default=None,
230*6777b538SAndroid Build Coastguard Worker      help="The name of git tag (default: version)")
231*6777b538SAndroid Build Coastguard Worker  parser.add_argument(
232*6777b538SAndroid Build Coastguard Worker      "-o",
233*6777b538SAndroid Build Coastguard Worker      "--output",
234*6777b538SAndroid Build Coastguard Worker      default="abseil.podspec",
235*6777b538SAndroid Build Coastguard Worker      help="The name of output file (default: abseil.podspec)")
236*6777b538SAndroid Build Coastguard Worker  args = parser.parse_args()
237*6777b538SAndroid Build Coastguard Worker  if args.tag is None:
238*6777b538SAndroid Build Coastguard Worker    args.tag = args.version
239*6777b538SAndroid Build Coastguard Worker  generate(args)
240*6777b538SAndroid Build Coastguard Worker
241*6777b538SAndroid Build Coastguard Worker
242*6777b538SAndroid Build Coastguard Workerif __name__ == "__main__":
243*6777b538SAndroid Build Coastguard Worker  main()
244