build_podspecs.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. #!/usr/bin/env python3
  2. # Copyright 2020, gRPC Authors All rights reserved.
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. import os
  16. import json
  17. import random
  18. import string
  19. import argparse
  20. class Dependency:
  21. def __init__(self, name, version='s.version.to_s', use_verbatim_version=True):
  22. self.name = name
  23. self.version = version
  24. self.use_verbatim_version = use_verbatim_version
  25. def as_podspec(self):
  26. indent=' '
  27. if self.use_verbatim_version:
  28. return indent + "s.dependency '%s', %s\n" % (self.name, self.version)
  29. return indent + "s.dependency '%s', '%s'\n" % (self.name, self.version)
  30. class Pod:
  31. def __init__(self, name, module_name, version, description, dependencies=None, is_plugins_pod=False):
  32. self.name = name
  33. self.module_name = module_name
  34. self.version = version
  35. self.is_plugins_pod = is_plugins_pod
  36. if dependencies is None:
  37. dependencies = []
  38. self.dependencies = dependencies
  39. self.description = description
  40. def add_dependency(self, dependency):
  41. self.dependencies.append(dependency)
  42. def as_podspec(self):
  43. print('\n')
  44. print('Building Podspec for %s' % self.name)
  45. print('-' * 80)
  46. indent=' ' * 4
  47. podspec = "Pod::Spec.new do |s|\n\n"
  48. podspec += indent + "s.name = '%s'\n" % self.name
  49. if not self.is_plugins_pod:
  50. podspec += indent + "s.module_name = '%s'\n" % self.module_name
  51. podspec += indent + "s.version = '%s'\n" % self.version
  52. podspec += indent + "s.license = { :type => 'Apache 2.0', :file => 'LICENSE' }\n"
  53. podspec += indent + "s.summary = '%s'\n" % self.description
  54. podspec += indent + "s.homepage = 'https://www.grpc.io'\n"
  55. podspec += indent + "s.authors = { 'The gRPC contributors' => \'grpc-packages@google.com' }\n\n"
  56. podspec += indent + "s.swift_version = '5.2'\n"
  57. podspec += indent + "s.ios.deployment_target = '10.0'\n"
  58. podspec += indent + "s.osx.deployment_target = '10.12'\n"
  59. podspec += indent + "s.tvos.deployment_target = '10.0'\n"
  60. podspec += indent + "s.watchos.deployment_target = '6.0'\n"
  61. if self.is_plugins_pod:
  62. podspec += indent + "s.source = { :http => \"https://github.com/grpc/grpc-swift/releases/download/#{s.version}/protoc-grpc-swift-plugins-#{s.version}.zip\"}\n\n"
  63. podspec += indent + "s.preserve_paths = '*'\n"
  64. else:
  65. podspec += indent + "s.source = { :git => \"https://github.com/grpc/grpc-swift.git\", :tag => s.version }\n\n"
  66. podspec += indent + "s.source_files = 'Sources/%s/**/*.{swift,c,h}'\n" % (self.module_name)
  67. podspec += "\n" if len(self.dependencies) > 0 else ""
  68. for dep in self.dependencies:
  69. podspec += dep.as_podspec()
  70. podspec += "\nend"
  71. return podspec
  72. class PodManager:
  73. def __init__(self, directory, version, should_publish):
  74. self.directory = directory
  75. self.version = version
  76. self.should_publish = should_publish
  77. def write(self, pod, contents):
  78. print(' Writing to %s/%s.podspec ' % (self.directory, pod))
  79. with open('%s/%s.podspec' % (self.directory, pod), 'w') as podspec_file:
  80. podspec_file.write(contents)
  81. def publish(self, pod_name):
  82. os.system('pod repo update')
  83. print(' Publishing %s.podspec' % (pod_name))
  84. os.system('pod trunk push --synchronous %s/%s.podspec' % (self.directory, pod_name))
  85. def build_pods(self):
  86. cgrpczlib_pod = Pod(
  87. 'CGRPCZlib',
  88. 'CGRPCZlib',
  89. self.version,
  90. 'Compression library that provides in-memory compression and decompression functions'
  91. )
  92. grpc_pod = Pod(
  93. 'gRPC-Swift',
  94. 'GRPC',
  95. self.version,
  96. 'Swift gRPC code generator plugin and runtime library',
  97. get_grpc_deps()
  98. )
  99. grpc_plugins_pod = Pod(
  100. 'gRPC-Swift-Plugins',
  101. '',
  102. self.version,
  103. 'Swift gRPC code generator plugin binaries',
  104. [],
  105. is_plugins_pod=True
  106. )
  107. grpc_pod.add_dependency(Dependency(cgrpczlib_pod.name))
  108. grpc_plugins_pod.add_dependency(Dependency(grpc_pod.name))
  109. return [cgrpczlib_pod, grpc_pod, grpc_plugins_pod]
  110. def go(self, start_from):
  111. pods = self.build_pods()
  112. if start_from:
  113. pods = pods[list(pod.name for pod in pods).index(start_from):]
  114. # Create .podspec files and publish
  115. for target in pods:
  116. self.write(target.name, target.as_podspec())
  117. if self.should_publish:
  118. self.publish(target.name)
  119. else:
  120. print(' Skipping Publishing...')
  121. def process_package(string):
  122. pod_mappings = {
  123. 'swift-log': 'Logging',
  124. 'swift-nio': 'SwiftNIO',
  125. 'swift-nio-extras': 'SwiftNIOExtras',
  126. 'swift-nio-http2': 'SwiftNIOHTTP2',
  127. 'swift-nio-ssl': 'SwiftNIOSSL',
  128. 'swift-nio-transport-services': 'SwiftNIOTransportServices',
  129. 'SwiftProtobuf': 'SwiftProtobuf'
  130. }
  131. return pod_mappings[string]
  132. def get_grpc_deps():
  133. with open('Package.resolved') as package:
  134. data = json.load(package)
  135. deps = []
  136. for obj in data['object']['pins']:
  137. package = process_package(obj['package'])
  138. version = obj['state']['version']
  139. next_major_version = int(version.split('.')[0]) + 1
  140. deps.append(Dependency(package, '\'>= {}\', \'< {}\''.format(version, next_major_version)))
  141. return deps
  142. def dir_path(path):
  143. if os.path.isdir(path):
  144. return path
  145. raise NotADirectoryError(path)
  146. def main():
  147. parser = argparse.ArgumentParser(description='Build Podspec files for gRPC Swift')
  148. parser.add_argument(
  149. '-p',
  150. '--path',
  151. type=dir_path,
  152. help='The directory where generated podspec files will be saved. If not passed, defaults to the current working directory.'
  153. )
  154. parser.add_argument(
  155. '-u',
  156. '--upload',
  157. action='store_true',
  158. help='Determines if the newly built Podspec files should be pushed.'
  159. )
  160. parser.add_argument(
  161. '-f',
  162. '--start-from',
  163. help='The name of the Podspec to start from.'
  164. )
  165. parser.add_argument('version')
  166. args = parser.parse_args()
  167. should_publish = args.upload
  168. version = args.version
  169. path = args.path
  170. start_from = args.start_from
  171. if not path:
  172. path = os.getcwd()
  173. pod_manager = PodManager(path, version, should_publish)
  174. pod_manager.go(start_from)
  175. return 0
  176. if __name__ == "__main__":
  177. main()