3 """This script generates abseil.podspec from all BUILD.bazel files.
5 This is expected to run on abseil git repository with Bazel 1.0 on Linux.
6 It recursively analyzes BUILD.bazel files using query command of Bazel to
7 dump its build rules in XML format. From these rules, it constructs podspec
16 import xml.etree.ElementTree
20 # This file has been automatically generated from a script.
21 # Please make modifications to `abseil.podspec.gen.py` instead.
24 s.version = '${version}'
25 s.summary = 'Abseil Common Libraries (C++) from Google'
26 s.homepage = 'https://abseil.io'
27 s.license = 'Apache License, Version 2.0'
28 s.authors = { 'Abseil Team' => 'abseil-io@googlegroups.com' }
30 :git => 'https://github.com/abseil/abseil-cpp.git',
33 s.module_name = 'absl'
34 s.header_mappings_dir = 'absl'
37 s.compiler_flags = '-Wno-everything'
38 s.pod_target_xcconfig = {
39 'USER_HEADER_SEARCH_PATHS' => '$(inherited) "$(PODS_TARGET_SRCROOT)"',
40 'USE_HEADERMAP' => 'NO',
41 'ALWAYS_SEARCH_USER_PATHS' => 'NO',
43 s.ios.deployment_target = '9.0'
44 s.osx.deployment_target = '10.10'
45 s.tvos.deployment_target = '9.0'
46 s.watchos.deployment_target = '2.0'
50 Rule = collections.namedtuple(
51 "Rule",
"type name package srcs hdrs textual_hdrs deps visibility testonly")
55 """Returns the value of XML element with the given name."""
57 if child.attrib.get(
"name") != name:
59 if child.tag ==
"string":
60 return child.attrib.get(
"value")
61 if child.tag ==
"boolean":
62 return child.attrib.get(
"value") ==
"true"
63 if child.tag ==
"list":
64 return [nested_child.attrib.get(
"value")
for nested_child
in child]
65 raise "Cannot recognize tag: " + child.tag
70 """Returns the list of normalized path."""
72 return [path.lstrip(
"/").replace(
":",
"/")
for path
in paths]
76 """Returns a rule from bazel XML rule."""
78 type=elem.attrib[
"class"],
90 """Runs bazel query on given package file and returns all cc rules."""
91 result = subprocess.check_output(
92 [
"bazel",
"query", package +
":all",
"--output",
"xml"])
93 root = xml.etree.ElementTree.fromstring(result)
97 if elem.tag ==
"rule" and elem.attrib[
"class"].startswith(
"cc_")
102 """Collects and returns all rules from root path recursively."""
104 for cur, _, _
in os.walk(root_path):
105 build_path = os.path.join(cur,
"BUILD.bazel")
106 if os.path.exists(build_path):
112 """Returns true if a given rule is relevant when generating a podspec."""
115 rule.type ==
"cc_library" and
117 (rule.hdrs + rule.textual_hdrs + rule.srcs)
and
123 """Returns the name of variable for spec with given depth."""
124 return "s" if depth == 0
else "s{}".
format(depth)
128 """Converts the label of bazel rule to the name of podspec."""
129 assert label.startswith(
"//absl/"),
"{} doesn't start with //absl/".
format(
132 return "abseil/" + label[7:]
136 """Writes a podspec from given rules and args."""
139 spec = re.sub(
r"\$\{(\w+)\}",
lambda x: args[x.group(1)],
140 SPEC_TEMPLATE).lstrip()
148 """Builds a tree-style rule directory from given rules."""
153 cur = cur.setdefault(frag, {})
154 cur[rule.name] = rule
159 """Writes podspec from rule map recursively."""
160 for key, value
in sorted(cur_map.items()):
161 indent =
" " * (depth + 1)
162 f.write(
"{indent}{var0}.subspec '{key}' do |{var1}|\n".
format(
167 if isinstance(value, dict):
171 f.write(
"{indent}end\n".
format(indent=indent))
175 """Writes podspec from given rule."""
176 indent =
" " * (depth + 1)
182 srcs = sorted(
set(rule.hdrs + rule.textual_hdrs + rule.srcs))
184 f,
"{indent}{var}.source_files = ".
format(indent=indent, var=spec_var),
187 for dep
in sorted(rule.deps):
189 f.write(
"{indent}{var}.dependency '{dep}'\n".
format(
190 indent=indent, var=spec_var, dep=name))
194 """Writes leading values in an indented style."""
196 f.write((
",\n" +
" " *
len(leading)).join(
"'{}'".
format(v)
for v
in values))
201 """Generates a podspec file from all BUILD files under absl directory."""
203 with open(args.output,
"wt")
as f:
208 parser = argparse.ArgumentParser(
209 description=
"Generates abseil.podspec from BUILD.bazel")
211 "-v",
"--version", help=
"The version of podspec", required=
True)
216 help=
"The name of git tag (default: version)")
220 default=
"abseil.podspec",
221 help=
"The name of output file (default: abseil.podspec)")
222 args = parser.parse_args()
224 args.tag = args.version
228 if __name__ ==
"__main__":