xref: /aosp_15_r20/external/cronet/build/toolchain/ios/swiftc.py (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1*6777b538SAndroid Build Coastguard Worker# Copyright 2023 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker# Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker# found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Workerimport argparse
6*6777b538SAndroid Build Coastguard Workerimport collections
7*6777b538SAndroid Build Coastguard Workerimport contextlib
8*6777b538SAndroid Build Coastguard Workerimport hashlib
9*6777b538SAndroid Build Coastguard Workerimport io
10*6777b538SAndroid Build Coastguard Workerimport json
11*6777b538SAndroid Build Coastguard Workerimport multiprocessing
12*6777b538SAndroid Build Coastguard Workerimport os
13*6777b538SAndroid Build Coastguard Workerimport re
14*6777b538SAndroid Build Coastguard Workerimport shutil
15*6777b538SAndroid Build Coastguard Workerimport subprocess
16*6777b538SAndroid Build Coastguard Workerimport sys
17*6777b538SAndroid Build Coastguard Workerimport tempfile
18*6777b538SAndroid Build Coastguard Worker
19*6777b538SAndroid Build Coastguard Worker
20*6777b538SAndroid Build Coastguard Workerclass ArgumentForwarder(object):
21*6777b538SAndroid Build Coastguard Worker  """Class used to abstract forwarding arguments from to the swiftc compiler.
22*6777b538SAndroid Build Coastguard Worker
23*6777b538SAndroid Build Coastguard Worker  Arguments:
24*6777b538SAndroid Build Coastguard Worker    - arg_name: string corresponding to the argument to pass to the compiler
25*6777b538SAndroid Build Coastguard Worker    - arg_join: function taking the compiler name and returning whether the
26*6777b538SAndroid Build Coastguard Worker                argument value is attached to the argument or separated
27*6777b538SAndroid Build Coastguard Worker    - to_swift: function taking the argument value and returning whether it
28*6777b538SAndroid Build Coastguard Worker                must be passed to the swift compiler
29*6777b538SAndroid Build Coastguard Worker    - to_clang: function taking the argument value and returning whether it
30*6777b538SAndroid Build Coastguard Worker                must be passed to the clang compiler
31*6777b538SAndroid Build Coastguard Worker  """
32*6777b538SAndroid Build Coastguard Worker
33*6777b538SAndroid Build Coastguard Worker  def __init__(self, arg_name, arg_join, to_swift, to_clang):
34*6777b538SAndroid Build Coastguard Worker    self._arg_name = arg_name
35*6777b538SAndroid Build Coastguard Worker    self._arg_join = arg_join
36*6777b538SAndroid Build Coastguard Worker    self._to_swift = to_swift
37*6777b538SAndroid Build Coastguard Worker    self._to_clang = to_clang
38*6777b538SAndroid Build Coastguard Worker
39*6777b538SAndroid Build Coastguard Worker  def forward(self, swiftc_args, values, target_triple):
40*6777b538SAndroid Build Coastguard Worker    if not values:
41*6777b538SAndroid Build Coastguard Worker      return
42*6777b538SAndroid Build Coastguard Worker
43*6777b538SAndroid Build Coastguard Worker    is_catalyst = target_triple.endswith('macabi')
44*6777b538SAndroid Build Coastguard Worker    for value in values:
45*6777b538SAndroid Build Coastguard Worker      if self._to_swift(value):
46*6777b538SAndroid Build Coastguard Worker        if self._arg_join('swift'):
47*6777b538SAndroid Build Coastguard Worker          swiftc_args.append(f'{self._arg_name}{value}')
48*6777b538SAndroid Build Coastguard Worker        else:
49*6777b538SAndroid Build Coastguard Worker          swiftc_args.append(self._arg_name)
50*6777b538SAndroid Build Coastguard Worker          swiftc_args.append(value)
51*6777b538SAndroid Build Coastguard Worker
52*6777b538SAndroid Build Coastguard Worker      if self._to_clang(value) and not is_catalyst:
53*6777b538SAndroid Build Coastguard Worker        if self._arg_join('clang'):
54*6777b538SAndroid Build Coastguard Worker          swiftc_args.append('-Xcc')
55*6777b538SAndroid Build Coastguard Worker          swiftc_args.append(f'{self._arg_name}{value}')
56*6777b538SAndroid Build Coastguard Worker        else:
57*6777b538SAndroid Build Coastguard Worker          swiftc_args.append('-Xcc')
58*6777b538SAndroid Build Coastguard Worker          swiftc_args.append(self._arg_name)
59*6777b538SAndroid Build Coastguard Worker          swiftc_args.append('-Xcc')
60*6777b538SAndroid Build Coastguard Worker          swiftc_args.append(value)
61*6777b538SAndroid Build Coastguard Worker
62*6777b538SAndroid Build Coastguard Worker
63*6777b538SAndroid Build Coastguard Workerclass IncludeArgumentForwarder(ArgumentForwarder):
64*6777b538SAndroid Build Coastguard Worker  """Argument forwarder for -I and -isystem."""
65*6777b538SAndroid Build Coastguard Worker
66*6777b538SAndroid Build Coastguard Worker  def __init__(self, arg_name):
67*6777b538SAndroid Build Coastguard Worker    ArgumentForwarder.__init__(self,
68*6777b538SAndroid Build Coastguard Worker                               arg_name,
69*6777b538SAndroid Build Coastguard Worker                               arg_join=lambda _: len(arg_name) == 1,
70*6777b538SAndroid Build Coastguard Worker                               to_swift=lambda _: arg_name != '-isystem',
71*6777b538SAndroid Build Coastguard Worker                               to_clang=lambda _: True)
72*6777b538SAndroid Build Coastguard Worker
73*6777b538SAndroid Build Coastguard Worker
74*6777b538SAndroid Build Coastguard Workerclass FrameworkArgumentForwarder(ArgumentForwarder):
75*6777b538SAndroid Build Coastguard Worker  """Argument forwarder for -F and -Fsystem."""
76*6777b538SAndroid Build Coastguard Worker
77*6777b538SAndroid Build Coastguard Worker  def __init__(self, arg_name):
78*6777b538SAndroid Build Coastguard Worker    ArgumentForwarder.__init__(self,
79*6777b538SAndroid Build Coastguard Worker                               arg_name,
80*6777b538SAndroid Build Coastguard Worker                               arg_join=lambda _: len(arg_name) == 1,
81*6777b538SAndroid Build Coastguard Worker                               to_swift=lambda _: True,
82*6777b538SAndroid Build Coastguard Worker                               to_clang=lambda _: True)
83*6777b538SAndroid Build Coastguard Worker
84*6777b538SAndroid Build Coastguard Worker
85*6777b538SAndroid Build Coastguard Workerclass DefineArgumentForwarder(ArgumentForwarder):
86*6777b538SAndroid Build Coastguard Worker  """Argument forwarder for -D."""
87*6777b538SAndroid Build Coastguard Worker
88*6777b538SAndroid Build Coastguard Worker  def __init__(self, arg_name):
89*6777b538SAndroid Build Coastguard Worker    ArgumentForwarder.__init__(self,
90*6777b538SAndroid Build Coastguard Worker                               arg_name,
91*6777b538SAndroid Build Coastguard Worker                               arg_join=lambda _: _ == 'clang',
92*6777b538SAndroid Build Coastguard Worker                               to_swift=lambda _: '=' not in _,
93*6777b538SAndroid Build Coastguard Worker                               to_clang=lambda _: True)
94*6777b538SAndroid Build Coastguard Worker
95*6777b538SAndroid Build Coastguard Worker
96*6777b538SAndroid Build Coastguard Worker# Dictionary mapping argument names to their ArgumentForwarder.
97*6777b538SAndroid Build Coastguard WorkerARGUMENT_FORWARDER_FOR_ATTR = (
98*6777b538SAndroid Build Coastguard Worker    ('include_dirs', IncludeArgumentForwarder('-I')),
99*6777b538SAndroid Build Coastguard Worker    ('system_include_dirs', IncludeArgumentForwarder('-isystem')),
100*6777b538SAndroid Build Coastguard Worker    ('framework_dirs', FrameworkArgumentForwarder('-F')),
101*6777b538SAndroid Build Coastguard Worker    ('system_framework_dirs', FrameworkArgumentForwarder('-Fsystem')),
102*6777b538SAndroid Build Coastguard Worker    ('defines', DefineArgumentForwarder('-D')),
103*6777b538SAndroid Build Coastguard Worker)
104*6777b538SAndroid Build Coastguard Worker
105*6777b538SAndroid Build Coastguard Worker# Regexp used to parse #import lines.
106*6777b538SAndroid Build Coastguard WorkerIMPORT_LINE_REGEXP = re.compile('#import "([^"]*)"')
107*6777b538SAndroid Build Coastguard Worker
108*6777b538SAndroid Build Coastguard Worker
109*6777b538SAndroid Build Coastguard Workerclass FileWriter(contextlib.AbstractContextManager):
110*6777b538SAndroid Build Coastguard Worker  """
111*6777b538SAndroid Build Coastguard Worker  FileWriter is a file-like object that only write data to disk if changed.
112*6777b538SAndroid Build Coastguard Worker
113*6777b538SAndroid Build Coastguard Worker  This object implements the context manager protocols and thus can be used
114*6777b538SAndroid Build Coastguard Worker  in a with-clause. The data is written to disk when the context is exited,
115*6777b538SAndroid Build Coastguard Worker  and only if the content is different from current file content.
116*6777b538SAndroid Build Coastguard Worker
117*6777b538SAndroid Build Coastguard Worker    with FileWriter(path) as stream:
118*6777b538SAndroid Build Coastguard Worker      stream.write('...')
119*6777b538SAndroid Build Coastguard Worker
120*6777b538SAndroid Build Coastguard Worker  If the with-clause ends with an exception, no data is written to the disk
121*6777b538SAndroid Build Coastguard Worker  and any existing file is left untouched.
122*6777b538SAndroid Build Coastguard Worker  """
123*6777b538SAndroid Build Coastguard Worker
124*6777b538SAndroid Build Coastguard Worker  def __init__(self, filepath, encoding='utf8'):
125*6777b538SAndroid Build Coastguard Worker    self._stringio = io.StringIO()
126*6777b538SAndroid Build Coastguard Worker    self._filepath = filepath
127*6777b538SAndroid Build Coastguard Worker    self._encoding = encoding
128*6777b538SAndroid Build Coastguard Worker
129*6777b538SAndroid Build Coastguard Worker  def __exit__(self, exc_type, exc_value, traceback):
130*6777b538SAndroid Build Coastguard Worker    if exc_type or exc_value or traceback:
131*6777b538SAndroid Build Coastguard Worker      return
132*6777b538SAndroid Build Coastguard Worker
133*6777b538SAndroid Build Coastguard Worker    new_content = self._stringio.getvalue()
134*6777b538SAndroid Build Coastguard Worker    if os.path.exists(self._filepath):
135*6777b538SAndroid Build Coastguard Worker      with open(self._filepath, encoding=self._encoding) as stream:
136*6777b538SAndroid Build Coastguard Worker        old_content = stream.read()
137*6777b538SAndroid Build Coastguard Worker
138*6777b538SAndroid Build Coastguard Worker      if old_content == new_content:
139*6777b538SAndroid Build Coastguard Worker        return
140*6777b538SAndroid Build Coastguard Worker
141*6777b538SAndroid Build Coastguard Worker    with open(self._filepath, 'w', encoding=self._encoding) as stream:
142*6777b538SAndroid Build Coastguard Worker      stream.write(new_content)
143*6777b538SAndroid Build Coastguard Worker
144*6777b538SAndroid Build Coastguard Worker  def write(self, data):
145*6777b538SAndroid Build Coastguard Worker    self._stringio.write(data)
146*6777b538SAndroid Build Coastguard Worker
147*6777b538SAndroid Build Coastguard Worker
148*6777b538SAndroid Build Coastguard Worker@contextlib.contextmanager
149*6777b538SAndroid Build Coastguard Workerdef existing_directory(path):
150*6777b538SAndroid Build Coastguard Worker  """Returns a context manager wrapping an existing directory."""
151*6777b538SAndroid Build Coastguard Worker  yield path
152*6777b538SAndroid Build Coastguard Worker
153*6777b538SAndroid Build Coastguard Worker
154*6777b538SAndroid Build Coastguard Workerdef create_stamp_file(path):
155*6777b538SAndroid Build Coastguard Worker  """Writes an empty stamp file at path."""
156*6777b538SAndroid Build Coastguard Worker  with FileWriter(path) as stream:
157*6777b538SAndroid Build Coastguard Worker    stream.write('')
158*6777b538SAndroid Build Coastguard Worker
159*6777b538SAndroid Build Coastguard Worker
160*6777b538SAndroid Build Coastguard Workerdef create_build_cache_dir(args, build_signature):
161*6777b538SAndroid Build Coastguard Worker  """Creates the build cache directory according to `args`.
162*6777b538SAndroid Build Coastguard Worker
163*6777b538SAndroid Build Coastguard Worker  This function returns an object that implements the context manager
164*6777b538SAndroid Build Coastguard Worker  protocol and thus can be used in a with-clause. If -derived-data-dir
165*6777b538SAndroid Build Coastguard Worker  argument is not used, the returned directory is a temporary directory
166*6777b538SAndroid Build Coastguard Worker  that will be deleted when the with-clause is exited.
167*6777b538SAndroid Build Coastguard Worker  """
168*6777b538SAndroid Build Coastguard Worker  if not args.derived_data_dir:
169*6777b538SAndroid Build Coastguard Worker    return tempfile.TemporaryDirectory()
170*6777b538SAndroid Build Coastguard Worker
171*6777b538SAndroid Build Coastguard Worker  # The derived data cache can be quite large, so delete any obsolete
172*6777b538SAndroid Build Coastguard Worker  # files or directories.
173*6777b538SAndroid Build Coastguard Worker  stamp_name = f'{args.module_name}.stamp'
174*6777b538SAndroid Build Coastguard Worker  if os.path.isdir(args.derived_data_dir):
175*6777b538SAndroid Build Coastguard Worker    for name in os.listdir(args.derived_data_dir):
176*6777b538SAndroid Build Coastguard Worker      if name not in (build_signature, stamp_name):
177*6777b538SAndroid Build Coastguard Worker        path = os.path.join(args.derived_data_dir, name)
178*6777b538SAndroid Build Coastguard Worker        if os.path.isdir(path):
179*6777b538SAndroid Build Coastguard Worker          shutil.rmtree(path)
180*6777b538SAndroid Build Coastguard Worker        else:
181*6777b538SAndroid Build Coastguard Worker          os.unlink(path)
182*6777b538SAndroid Build Coastguard Worker
183*6777b538SAndroid Build Coastguard Worker  ensure_directory(args.derived_data_dir)
184*6777b538SAndroid Build Coastguard Worker  create_stamp_file(os.path.join(args.derived_data_dir, stamp_name))
185*6777b538SAndroid Build Coastguard Worker
186*6777b538SAndroid Build Coastguard Worker  return existing_directory(
187*6777b538SAndroid Build Coastguard Worker      ensure_directory(os.path.join(args.derived_data_dir, build_signature)))
188*6777b538SAndroid Build Coastguard Worker
189*6777b538SAndroid Build Coastguard Worker
190*6777b538SAndroid Build Coastguard Workerdef ensure_directory(path):
191*6777b538SAndroid Build Coastguard Worker  """Creates directory at `path` if it does not exists."""
192*6777b538SAndroid Build Coastguard Worker  if not os.path.isdir(path):
193*6777b538SAndroid Build Coastguard Worker    os.makedirs(path)
194*6777b538SAndroid Build Coastguard Worker  return path
195*6777b538SAndroid Build Coastguard Worker
196*6777b538SAndroid Build Coastguard Worker
197*6777b538SAndroid Build Coastguard Workerdef build_signature(env, args):
198*6777b538SAndroid Build Coastguard Worker  """Generates the build signature from `env` and `args`.
199*6777b538SAndroid Build Coastguard Worker
200*6777b538SAndroid Build Coastguard Worker  This allow re-using the derived data dir between builds while still
201*6777b538SAndroid Build Coastguard Worker  forcing the data to be recreated from scratch in case of significant
202*6777b538SAndroid Build Coastguard Worker  changes to the build settings (different arguments or tool versions).
203*6777b538SAndroid Build Coastguard Worker  """
204*6777b538SAndroid Build Coastguard Worker  m = hashlib.sha1()
205*6777b538SAndroid Build Coastguard Worker  for key in sorted(env):
206*6777b538SAndroid Build Coastguard Worker    if key.endswith('_VERSION') or key == 'DEVELOPER_DIR':
207*6777b538SAndroid Build Coastguard Worker      m.update(f'{key}={env[key]}'.encode('utf8'))
208*6777b538SAndroid Build Coastguard Worker  for i, arg in enumerate(args):
209*6777b538SAndroid Build Coastguard Worker    m.update(f'{i}={arg}'.encode('utf8'))
210*6777b538SAndroid Build Coastguard Worker  return m.hexdigest()
211*6777b538SAndroid Build Coastguard Worker
212*6777b538SAndroid Build Coastguard Worker
213*6777b538SAndroid Build Coastguard Workerdef generate_source_output_file_map_fragment(args, filename):
214*6777b538SAndroid Build Coastguard Worker  """Generates source OutputFileMap.json fragment according to `args`.
215*6777b538SAndroid Build Coastguard Worker
216*6777b538SAndroid Build Coastguard Worker  Create the fragment for a single .swift source file for OutputFileMap.
217*6777b538SAndroid Build Coastguard Worker  The output depends on whether -whole-module-optimization argument is
218*6777b538SAndroid Build Coastguard Worker  used or not.
219*6777b538SAndroid Build Coastguard Worker  """
220*6777b538SAndroid Build Coastguard Worker  assert os.path.splitext(filename)[1] == '.swift', filename
221*6777b538SAndroid Build Coastguard Worker  basename = os.path.splitext(os.path.basename(filename))[0]
222*6777b538SAndroid Build Coastguard Worker  rel_name = os.path.join(args.target_out_dir, basename)
223*6777b538SAndroid Build Coastguard Worker  out_name = rel_name
224*6777b538SAndroid Build Coastguard Worker
225*6777b538SAndroid Build Coastguard Worker  fragment = {
226*6777b538SAndroid Build Coastguard Worker      'index-unit-output-path': f'/{rel_name}.o',
227*6777b538SAndroid Build Coastguard Worker      'object': f'{out_name}.o',
228*6777b538SAndroid Build Coastguard Worker  }
229*6777b538SAndroid Build Coastguard Worker
230*6777b538SAndroid Build Coastguard Worker  if not args.whole_module_optimization:
231*6777b538SAndroid Build Coastguard Worker    fragment.update({
232*6777b538SAndroid Build Coastguard Worker        'const-values': f'{out_name}.swiftconstvalues',
233*6777b538SAndroid Build Coastguard Worker        'dependencies': f'{out_name}.d',
234*6777b538SAndroid Build Coastguard Worker        'diagnostics': f'{out_name}.dia',
235*6777b538SAndroid Build Coastguard Worker        'swift-dependencies': f'{out_name}.swiftdeps',
236*6777b538SAndroid Build Coastguard Worker    })
237*6777b538SAndroid Build Coastguard Worker
238*6777b538SAndroid Build Coastguard Worker  return fragment
239*6777b538SAndroid Build Coastguard Worker
240*6777b538SAndroid Build Coastguard Worker
241*6777b538SAndroid Build Coastguard Workerdef generate_module_output_file_map_fragment(args):
242*6777b538SAndroid Build Coastguard Worker  """Generates module OutputFileMap.json fragment according to `args`.
243*6777b538SAndroid Build Coastguard Worker
244*6777b538SAndroid Build Coastguard Worker  Create the fragment for the module itself for OutputFileMap. The output
245*6777b538SAndroid Build Coastguard Worker  depends on whether -whole-module-optimization argument is used or not.
246*6777b538SAndroid Build Coastguard Worker  """
247*6777b538SAndroid Build Coastguard Worker  out_name = os.path.join(args.target_out_dir, args.module_name)
248*6777b538SAndroid Build Coastguard Worker
249*6777b538SAndroid Build Coastguard Worker  if args.whole_module_optimization:
250*6777b538SAndroid Build Coastguard Worker    fragment = {
251*6777b538SAndroid Build Coastguard Worker        'const-values': f'{out_name}.swiftconstvalues',
252*6777b538SAndroid Build Coastguard Worker        'dependencies': f'{out_name}.d',
253*6777b538SAndroid Build Coastguard Worker        'diagnostics': f'{out_name}.dia',
254*6777b538SAndroid Build Coastguard Worker        'swift-dependencies': f'{out_name}.swiftdeps',
255*6777b538SAndroid Build Coastguard Worker    }
256*6777b538SAndroid Build Coastguard Worker  else:
257*6777b538SAndroid Build Coastguard Worker    fragment = {
258*6777b538SAndroid Build Coastguard Worker        'emit-module-dependencies': f'{out_name}.d',
259*6777b538SAndroid Build Coastguard Worker        'emit-module-diagnostics': f'{out_name}.dia',
260*6777b538SAndroid Build Coastguard Worker        'swift-dependencies': f'{out_name}.swiftdeps',
261*6777b538SAndroid Build Coastguard Worker    }
262*6777b538SAndroid Build Coastguard Worker
263*6777b538SAndroid Build Coastguard Worker  return fragment
264*6777b538SAndroid Build Coastguard Worker
265*6777b538SAndroid Build Coastguard Worker
266*6777b538SAndroid Build Coastguard Workerdef generate_output_file_map(args):
267*6777b538SAndroid Build Coastguard Worker  """Generates OutputFileMap.json according to `args`.
268*6777b538SAndroid Build Coastguard Worker
269*6777b538SAndroid Build Coastguard Worker  Returns the mapping as a python dictionary that can be serialized to
270*6777b538SAndroid Build Coastguard Worker  disk as JSON.
271*6777b538SAndroid Build Coastguard Worker  """
272*6777b538SAndroid Build Coastguard Worker  output_file_map = {'': generate_module_output_file_map_fragment(args)}
273*6777b538SAndroid Build Coastguard Worker  for filename in args.sources:
274*6777b538SAndroid Build Coastguard Worker    fragment = generate_source_output_file_map_fragment(args, filename)
275*6777b538SAndroid Build Coastguard Worker    output_file_map[filename] = fragment
276*6777b538SAndroid Build Coastguard Worker  return output_file_map
277*6777b538SAndroid Build Coastguard Worker
278*6777b538SAndroid Build Coastguard Worker
279*6777b538SAndroid Build Coastguard Workerdef fix_generated_header(header_path, output_path, src_dir, gen_dir):
280*6777b538SAndroid Build Coastguard Worker  """Fix the Objective-C header generated by the Swift compiler.
281*6777b538SAndroid Build Coastguard Worker
282*6777b538SAndroid Build Coastguard Worker  The Swift compiler assumes that the generated Objective-C header will be
283*6777b538SAndroid Build Coastguard Worker  imported from code compiled with module support enabled (-fmodules). The
284*6777b538SAndroid Build Coastguard Worker  generated code thus uses @import and provides no fallback if modules are
285*6777b538SAndroid Build Coastguard Worker  not enabled.
286*6777b538SAndroid Build Coastguard Worker
287*6777b538SAndroid Build Coastguard Worker  The Swift compiler also uses absolute path when including the bridging
288*6777b538SAndroid Build Coastguard Worker  header or another module's generated header. This causes issues with the
289*6777b538SAndroid Build Coastguard Worker  distributed compiler (i.e. reclient or siso) who expects all paths to be
290*6777b538SAndroid Build Coastguard Worker  relative to the build directory
291*6777b538SAndroid Build Coastguard Worker
292*6777b538SAndroid Build Coastguard Worker  This method fix the generated header to use relative path for #import
293*6777b538SAndroid Build Coastguard Worker  and to use #import instead of @import when using system frameworks.
294*6777b538SAndroid Build Coastguard Worker
295*6777b538SAndroid Build Coastguard Worker  The header is read at `header_path` and written to `output_path`.
296*6777b538SAndroid Build Coastguard Worker  """
297*6777b538SAndroid Build Coastguard Worker
298*6777b538SAndroid Build Coastguard Worker  header_contents = []
299*6777b538SAndroid Build Coastguard Worker  with open(header_path, 'r', encoding='utf8') as header_file:
300*6777b538SAndroid Build Coastguard Worker
301*6777b538SAndroid Build Coastguard Worker    imports_section = None
302*6777b538SAndroid Build Coastguard Worker    for line in header_file:
303*6777b538SAndroid Build Coastguard Worker      # Handle #import lines.
304*6777b538SAndroid Build Coastguard Worker      match = IMPORT_LINE_REGEXP.match(line)
305*6777b538SAndroid Build Coastguard Worker      if match:
306*6777b538SAndroid Build Coastguard Worker        import_path = match.group(1)
307*6777b538SAndroid Build Coastguard Worker        for root in (gen_dir, src_dir):
308*6777b538SAndroid Build Coastguard Worker          if import_path.startswith(root):
309*6777b538SAndroid Build Coastguard Worker            import_path = os.path.relpath(import_path, root)
310*6777b538SAndroid Build Coastguard Worker        if import_path != match.group(1):
311*6777b538SAndroid Build Coastguard Worker          span = match.span(1)
312*6777b538SAndroid Build Coastguard Worker          line = line[:span[0]] + import_path + line[span[1]:]
313*6777b538SAndroid Build Coastguard Worker
314*6777b538SAndroid Build Coastguard Worker      # Handle @import lines.
315*6777b538SAndroid Build Coastguard Worker      if line.startswith('#if __has_feature(objc_modules)'):
316*6777b538SAndroid Build Coastguard Worker        assert imports_section is None
317*6777b538SAndroid Build Coastguard Worker        imports_section = (len(header_contents) + 1, 1)
318*6777b538SAndroid Build Coastguard Worker      elif imports_section:
319*6777b538SAndroid Build Coastguard Worker        section_start, nesting_level = imports_section
320*6777b538SAndroid Build Coastguard Worker        if line.startswith('#if'):
321*6777b538SAndroid Build Coastguard Worker          imports_section = (section_start, nesting_level + 1)
322*6777b538SAndroid Build Coastguard Worker        elif line.startswith('#endif'):
323*6777b538SAndroid Build Coastguard Worker          if nesting_level > 1:
324*6777b538SAndroid Build Coastguard Worker            imports_section = (section_start, nesting_level - 1)
325*6777b538SAndroid Build Coastguard Worker          else:
326*6777b538SAndroid Build Coastguard Worker            imports_section = None
327*6777b538SAndroid Build Coastguard Worker            section_end = len(header_contents)
328*6777b538SAndroid Build Coastguard Worker            header_contents.append('#else\n')
329*6777b538SAndroid Build Coastguard Worker            for index in range(section_start, section_end):
330*6777b538SAndroid Build Coastguard Worker              l = header_contents[index]
331*6777b538SAndroid Build Coastguard Worker              if l.startswith('@import'):
332*6777b538SAndroid Build Coastguard Worker                name = l.split()[1].split(';')[0]
333*6777b538SAndroid Build Coastguard Worker                if name != 'ObjectiveC':
334*6777b538SAndroid Build Coastguard Worker                  header_contents.append(f'#import <{name}/{name}.h>\n')
335*6777b538SAndroid Build Coastguard Worker              else:
336*6777b538SAndroid Build Coastguard Worker                header_contents.append(l)
337*6777b538SAndroid Build Coastguard Worker
338*6777b538SAndroid Build Coastguard Worker      header_contents.append(line)
339*6777b538SAndroid Build Coastguard Worker
340*6777b538SAndroid Build Coastguard Worker  with FileWriter(output_path) as header_file:
341*6777b538SAndroid Build Coastguard Worker    for line in header_contents:
342*6777b538SAndroid Build Coastguard Worker      header_file.write(line)
343*6777b538SAndroid Build Coastguard Worker
344*6777b538SAndroid Build Coastguard Worker
345*6777b538SAndroid Build Coastguard Workerdef invoke_swift_compiler(args, extras_args, build_cache_dir, output_file_map):
346*6777b538SAndroid Build Coastguard Worker  """Invokes Swift compiler to compile module according to `args`.
347*6777b538SAndroid Build Coastguard Worker
348*6777b538SAndroid Build Coastguard Worker  The `build_cache_dir` and `output_file_map` should be path to existing
349*6777b538SAndroid Build Coastguard Worker  directory to use for writing intermediate build artifact (optionally
350*6777b538SAndroid Build Coastguard Worker  a temporary directory) and path to $module-OutputFileMap.json file that
351*6777b538SAndroid Build Coastguard Worker  lists the outputs to generate for the module and each source file.
352*6777b538SAndroid Build Coastguard Worker
353*6777b538SAndroid Build Coastguard Worker  If -fix-module-imports argument is passed, the generated header for the
354*6777b538SAndroid Build Coastguard Worker  module is written to a temporary location and then modified to replace
355*6777b538SAndroid Build Coastguard Worker  @import by corresponding #import.
356*6777b538SAndroid Build Coastguard Worker  """
357*6777b538SAndroid Build Coastguard Worker
358*6777b538SAndroid Build Coastguard Worker  # Write the $module.SwiftFileList file.
359*6777b538SAndroid Build Coastguard Worker  swift_file_list_path = os.path.join(args.target_out_dir,
360*6777b538SAndroid Build Coastguard Worker                                      f'{args.module_name}.SwiftFileList')
361*6777b538SAndroid Build Coastguard Worker
362*6777b538SAndroid Build Coastguard Worker  with FileWriter(swift_file_list_path) as stream:
363*6777b538SAndroid Build Coastguard Worker    for filename in sorted(args.sources):
364*6777b538SAndroid Build Coastguard Worker      stream.write(f'"{filename}"\n')
365*6777b538SAndroid Build Coastguard Worker
366*6777b538SAndroid Build Coastguard Worker  header_path = args.header_path
367*6777b538SAndroid Build Coastguard Worker  if args.fix_generated_header:
368*6777b538SAndroid Build Coastguard Worker    header_path = os.path.join(build_cache_dir, os.path.basename(header_path))
369*6777b538SAndroid Build Coastguard Worker
370*6777b538SAndroid Build Coastguard Worker  swiftc_args = [
371*6777b538SAndroid Build Coastguard Worker      '-parse-as-library',
372*6777b538SAndroid Build Coastguard Worker      '-module-name',
373*6777b538SAndroid Build Coastguard Worker      args.module_name,
374*6777b538SAndroid Build Coastguard Worker      f'@{swift_file_list_path}',
375*6777b538SAndroid Build Coastguard Worker      '-sdk',
376*6777b538SAndroid Build Coastguard Worker      args.sdk_path,
377*6777b538SAndroid Build Coastguard Worker      '-target',
378*6777b538SAndroid Build Coastguard Worker      args.target_triple,
379*6777b538SAndroid Build Coastguard Worker      '-swift-version',
380*6777b538SAndroid Build Coastguard Worker      args.swift_version,
381*6777b538SAndroid Build Coastguard Worker      '-c',
382*6777b538SAndroid Build Coastguard Worker      '-output-file-map',
383*6777b538SAndroid Build Coastguard Worker      output_file_map,
384*6777b538SAndroid Build Coastguard Worker      '-save-temps',
385*6777b538SAndroid Build Coastguard Worker      '-no-color-diagnostics',
386*6777b538SAndroid Build Coastguard Worker      '-serialize-diagnostics',
387*6777b538SAndroid Build Coastguard Worker      '-emit-dependencies',
388*6777b538SAndroid Build Coastguard Worker      '-emit-module',
389*6777b538SAndroid Build Coastguard Worker      '-emit-module-path',
390*6777b538SAndroid Build Coastguard Worker      os.path.join(args.target_out_dir, f'{args.module_name}.swiftmodule'),
391*6777b538SAndroid Build Coastguard Worker      '-emit-objc-header',
392*6777b538SAndroid Build Coastguard Worker      '-emit-objc-header-path',
393*6777b538SAndroid Build Coastguard Worker      header_path,
394*6777b538SAndroid Build Coastguard Worker      '-working-directory',
395*6777b538SAndroid Build Coastguard Worker      os.getcwd(),
396*6777b538SAndroid Build Coastguard Worker      '-index-store-path',
397*6777b538SAndroid Build Coastguard Worker      ensure_directory(os.path.join(build_cache_dir, 'Index.noindex')),
398*6777b538SAndroid Build Coastguard Worker      '-module-cache-path',
399*6777b538SAndroid Build Coastguard Worker      ensure_directory(os.path.join(build_cache_dir, 'ModuleCache.noindex')),
400*6777b538SAndroid Build Coastguard Worker      '-pch-output-dir',
401*6777b538SAndroid Build Coastguard Worker      ensure_directory(os.path.join(build_cache_dir, 'PrecompiledHeaders')),
402*6777b538SAndroid Build Coastguard Worker  ]
403*6777b538SAndroid Build Coastguard Worker
404*6777b538SAndroid Build Coastguard Worker  # Handle optional -bridge-header flag.
405*6777b538SAndroid Build Coastguard Worker  if args.bridge_header:
406*6777b538SAndroid Build Coastguard Worker    swiftc_args.extend(('-import-objc-header', args.bridge_header))
407*6777b538SAndroid Build Coastguard Worker
408*6777b538SAndroid Build Coastguard Worker  # Handle swift const values extraction.
409*6777b538SAndroid Build Coastguard Worker  swiftc_args.extend(['-emit-const-values'])
410*6777b538SAndroid Build Coastguard Worker  swiftc_args.extend([
411*6777b538SAndroid Build Coastguard Worker      '-Xfrontend',
412*6777b538SAndroid Build Coastguard Worker      '-const-gather-protocols-file',
413*6777b538SAndroid Build Coastguard Worker      '-Xfrontend',
414*6777b538SAndroid Build Coastguard Worker      args.const_gather_protocols_file,
415*6777b538SAndroid Build Coastguard Worker  ])
416*6777b538SAndroid Build Coastguard Worker
417*6777b538SAndroid Build Coastguard Worker  # Handle -I, -F, -isystem, -Fsystem and -D arguments.
418*6777b538SAndroid Build Coastguard Worker  for (attr_name, forwarder) in ARGUMENT_FORWARDER_FOR_ATTR:
419*6777b538SAndroid Build Coastguard Worker    forwarder.forward(swiftc_args, getattr(args, attr_name), args.target_triple)
420*6777b538SAndroid Build Coastguard Worker
421*6777b538SAndroid Build Coastguard Worker  # Handle -whole-module-optimization flag.
422*6777b538SAndroid Build Coastguard Worker  num_threads = max(1, multiprocessing.cpu_count() // 2)
423*6777b538SAndroid Build Coastguard Worker  if args.whole_module_optimization:
424*6777b538SAndroid Build Coastguard Worker    swiftc_args.extend([
425*6777b538SAndroid Build Coastguard Worker        '-whole-module-optimization',
426*6777b538SAndroid Build Coastguard Worker        '-no-emit-module-separately-wmo',
427*6777b538SAndroid Build Coastguard Worker        '-num-threads',
428*6777b538SAndroid Build Coastguard Worker        f'{num_threads}',
429*6777b538SAndroid Build Coastguard Worker    ])
430*6777b538SAndroid Build Coastguard Worker  else:
431*6777b538SAndroid Build Coastguard Worker    swiftc_args.extend([
432*6777b538SAndroid Build Coastguard Worker        '-enable-batch-mode',
433*6777b538SAndroid Build Coastguard Worker        '-incremental',
434*6777b538SAndroid Build Coastguard Worker        '-experimental-emit-module-separately',
435*6777b538SAndroid Build Coastguard Worker        '-disable-cmo',
436*6777b538SAndroid Build Coastguard Worker        f'-j{num_threads}',
437*6777b538SAndroid Build Coastguard Worker    ])
438*6777b538SAndroid Build Coastguard Worker
439*6777b538SAndroid Build Coastguard Worker  swift_toolchain_path = args.swift_toolchain_path
440*6777b538SAndroid Build Coastguard Worker  if not swift_toolchain_path:
441*6777b538SAndroid Build Coastguard Worker    swift_toolchain_path = os.path.join(os.path.dirname(args.sdk_path),
442*6777b538SAndroid Build Coastguard Worker                                        'XcodeDefault.xctoolchain')
443*6777b538SAndroid Build Coastguard Worker    if not os.path.isdir(swift_toolchain_path):
444*6777b538SAndroid Build Coastguard Worker      swift_toolchain_path = ''
445*6777b538SAndroid Build Coastguard Worker
446*6777b538SAndroid Build Coastguard Worker  command = [f'{swift_toolchain_path}/usr/bin/swiftc'] + swiftc_args
447*6777b538SAndroid Build Coastguard Worker  if extras_args:
448*6777b538SAndroid Build Coastguard Worker    command.extend(extras_args)
449*6777b538SAndroid Build Coastguard Worker
450*6777b538SAndroid Build Coastguard Worker  process = subprocess.Popen(command)
451*6777b538SAndroid Build Coastguard Worker  process.communicate()
452*6777b538SAndroid Build Coastguard Worker
453*6777b538SAndroid Build Coastguard Worker  if process.returncode:
454*6777b538SAndroid Build Coastguard Worker    sys.exit(process.returncode)
455*6777b538SAndroid Build Coastguard Worker
456*6777b538SAndroid Build Coastguard Worker  if args.fix_generated_header:
457*6777b538SAndroid Build Coastguard Worker    fix_generated_header(header_path,
458*6777b538SAndroid Build Coastguard Worker                         args.header_path,
459*6777b538SAndroid Build Coastguard Worker                         src_dir=os.path.abspath(args.src_dir) + os.path.sep,
460*6777b538SAndroid Build Coastguard Worker                         gen_dir=os.path.abspath(args.gen_dir) + os.path.sep)
461*6777b538SAndroid Build Coastguard Worker
462*6777b538SAndroid Build Coastguard Worker
463*6777b538SAndroid Build Coastguard Workerdef generate_depfile(args, output_file_map):
464*6777b538SAndroid Build Coastguard Worker  """Generates compilation depfile according to `args`.
465*6777b538SAndroid Build Coastguard Worker
466*6777b538SAndroid Build Coastguard Worker  Parses all intermediate depfile generated by the Swift compiler and
467*6777b538SAndroid Build Coastguard Worker  replaces absolute path by relative paths (since ninja compares paths
468*6777b538SAndroid Build Coastguard Worker  as strings and does not resolve relative paths to absolute).
469*6777b538SAndroid Build Coastguard Worker
470*6777b538SAndroid Build Coastguard Worker  Converts path to the SDK and toolchain files to the sdk/xcode_link
471*6777b538SAndroid Build Coastguard Worker  symlinks if possible and available.
472*6777b538SAndroid Build Coastguard Worker  """
473*6777b538SAndroid Build Coastguard Worker  xcode_paths = {}
474*6777b538SAndroid Build Coastguard Worker  if os.path.islink(args.sdk_path):
475*6777b538SAndroid Build Coastguard Worker    xcode_links = os.path.dirname(args.sdk_path)
476*6777b538SAndroid Build Coastguard Worker    for link_name in os.listdir(xcode_links):
477*6777b538SAndroid Build Coastguard Worker      link_path = os.path.join(xcode_links, link_name)
478*6777b538SAndroid Build Coastguard Worker      if os.path.islink(link_path):
479*6777b538SAndroid Build Coastguard Worker        xcode_paths[os.path.realpath(link_path) + os.sep] = link_path + os.sep
480*6777b538SAndroid Build Coastguard Worker
481*6777b538SAndroid Build Coastguard Worker  out_dir = os.getcwd() + os.path.sep
482*6777b538SAndroid Build Coastguard Worker  src_dir = os.path.abspath(args.src_dir) + os.path.sep
483*6777b538SAndroid Build Coastguard Worker
484*6777b538SAndroid Build Coastguard Worker  depfile_content = collections.defaultdict(set)
485*6777b538SAndroid Build Coastguard Worker  for value in output_file_map.values():
486*6777b538SAndroid Build Coastguard Worker    partial_depfile_path = value.get('dependencies', None)
487*6777b538SAndroid Build Coastguard Worker    if partial_depfile_path:
488*6777b538SAndroid Build Coastguard Worker      with open(partial_depfile_path, encoding='utf8') as stream:
489*6777b538SAndroid Build Coastguard Worker        for line in stream:
490*6777b538SAndroid Build Coastguard Worker          output, inputs = line.split(' : ', 2)
491*6777b538SAndroid Build Coastguard Worker          output = os.path.relpath(output, out_dir)
492*6777b538SAndroid Build Coastguard Worker
493*6777b538SAndroid Build Coastguard Worker          # The depfile format uses '\' to quote space in filename. Split the
494*6777b538SAndroid Build Coastguard Worker          # list of file while respecting this convention.
495*6777b538SAndroid Build Coastguard Worker          for path in re.split(r'(?<!\\) ', inputs):
496*6777b538SAndroid Build Coastguard Worker            for xcode_path in xcode_paths:
497*6777b538SAndroid Build Coastguard Worker              if path.startswith(xcode_path):
498*6777b538SAndroid Build Coastguard Worker                path = xcode_paths[xcode_path] + path[len(xcode_path):]
499*6777b538SAndroid Build Coastguard Worker            if path.startswith(src_dir) or path.startswith(out_dir):
500*6777b538SAndroid Build Coastguard Worker              path = os.path.relpath(path, out_dir)
501*6777b538SAndroid Build Coastguard Worker            depfile_content[output].add(path)
502*6777b538SAndroid Build Coastguard Worker
503*6777b538SAndroid Build Coastguard Worker  with FileWriter(args.depfile_path) as stream:
504*6777b538SAndroid Build Coastguard Worker    for output, inputs in sorted(depfile_content.items()):
505*6777b538SAndroid Build Coastguard Worker      stream.write(f'{output}: {" ".join(sorted(inputs))}\n')
506*6777b538SAndroid Build Coastguard Worker
507*6777b538SAndroid Build Coastguard Worker
508*6777b538SAndroid Build Coastguard Workerdef compile_module(args, extras_args, build_signature):
509*6777b538SAndroid Build Coastguard Worker  """Compiles Swift module according to `args`."""
510*6777b538SAndroid Build Coastguard Worker  for path in (args.target_out_dir, os.path.dirname(args.header_path)):
511*6777b538SAndroid Build Coastguard Worker    ensure_directory(path)
512*6777b538SAndroid Build Coastguard Worker
513*6777b538SAndroid Build Coastguard Worker  # Write the $module-OutputFileMap.json file.
514*6777b538SAndroid Build Coastguard Worker  output_file_map = generate_output_file_map(args)
515*6777b538SAndroid Build Coastguard Worker  output_file_map_path = os.path.join(args.target_out_dir,
516*6777b538SAndroid Build Coastguard Worker                                      f'{args.module_name}-OutputFileMap.json')
517*6777b538SAndroid Build Coastguard Worker
518*6777b538SAndroid Build Coastguard Worker  with FileWriter(output_file_map_path) as stream:
519*6777b538SAndroid Build Coastguard Worker    json.dump(output_file_map, stream, indent=' ', sort_keys=True)
520*6777b538SAndroid Build Coastguard Worker
521*6777b538SAndroid Build Coastguard Worker  # Invoke Swift compiler.
522*6777b538SAndroid Build Coastguard Worker  with create_build_cache_dir(args, build_signature) as build_cache_dir:
523*6777b538SAndroid Build Coastguard Worker    invoke_swift_compiler(args,
524*6777b538SAndroid Build Coastguard Worker                          extras_args,
525*6777b538SAndroid Build Coastguard Worker                          build_cache_dir=build_cache_dir,
526*6777b538SAndroid Build Coastguard Worker                          output_file_map=output_file_map_path)
527*6777b538SAndroid Build Coastguard Worker
528*6777b538SAndroid Build Coastguard Worker  # Generate the depfile.
529*6777b538SAndroid Build Coastguard Worker  generate_depfile(args, output_file_map)
530*6777b538SAndroid Build Coastguard Worker
531*6777b538SAndroid Build Coastguard Worker
532*6777b538SAndroid Build Coastguard Workerdef main(args):
533*6777b538SAndroid Build Coastguard Worker  parser = argparse.ArgumentParser(allow_abbrev=False, add_help=False)
534*6777b538SAndroid Build Coastguard Worker
535*6777b538SAndroid Build Coastguard Worker  # Required arguments.
536*6777b538SAndroid Build Coastguard Worker  parser.add_argument('--module-name',
537*6777b538SAndroid Build Coastguard Worker                      required=True,
538*6777b538SAndroid Build Coastguard Worker                      help='name of the Swift module')
539*6777b538SAndroid Build Coastguard Worker
540*6777b538SAndroid Build Coastguard Worker  parser.add_argument('--src-dir',
541*6777b538SAndroid Build Coastguard Worker                      required=True,
542*6777b538SAndroid Build Coastguard Worker                      help='path to the source directory')
543*6777b538SAndroid Build Coastguard Worker
544*6777b538SAndroid Build Coastguard Worker  parser.add_argument('--gen-dir',
545*6777b538SAndroid Build Coastguard Worker                      required=True,
546*6777b538SAndroid Build Coastguard Worker                      help='path to the gen directory root')
547*6777b538SAndroid Build Coastguard Worker
548*6777b538SAndroid Build Coastguard Worker  parser.add_argument('--target-out-dir',
549*6777b538SAndroid Build Coastguard Worker                      required=True,
550*6777b538SAndroid Build Coastguard Worker                      help='path to the object directory')
551*6777b538SAndroid Build Coastguard Worker
552*6777b538SAndroid Build Coastguard Worker  parser.add_argument('--header-path',
553*6777b538SAndroid Build Coastguard Worker                      required=True,
554*6777b538SAndroid Build Coastguard Worker                      help='path to the generated header file')
555*6777b538SAndroid Build Coastguard Worker
556*6777b538SAndroid Build Coastguard Worker  parser.add_argument('--bridge-header',
557*6777b538SAndroid Build Coastguard Worker                      required=True,
558*6777b538SAndroid Build Coastguard Worker                      help='path to the Objective-C bridge header file')
559*6777b538SAndroid Build Coastguard Worker
560*6777b538SAndroid Build Coastguard Worker  parser.add_argument('--depfile-path',
561*6777b538SAndroid Build Coastguard Worker                      required=True,
562*6777b538SAndroid Build Coastguard Worker                      help='path to the output dependency file')
563*6777b538SAndroid Build Coastguard Worker
564*6777b538SAndroid Build Coastguard Worker  parser.add_argument('--const-gather-protocols-file',
565*6777b538SAndroid Build Coastguard Worker                      required=True,
566*6777b538SAndroid Build Coastguard Worker                      help='path to file containing const values protocols')
567*6777b538SAndroid Build Coastguard Worker
568*6777b538SAndroid Build Coastguard Worker  # Optional arguments.
569*6777b538SAndroid Build Coastguard Worker  parser.add_argument('--derived-data-dir',
570*6777b538SAndroid Build Coastguard Worker                      help='path to the derived data directory')
571*6777b538SAndroid Build Coastguard Worker
572*6777b538SAndroid Build Coastguard Worker  parser.add_argument('--fix-generated-header',
573*6777b538SAndroid Build Coastguard Worker                      default=False,
574*6777b538SAndroid Build Coastguard Worker                      action='store_true',
575*6777b538SAndroid Build Coastguard Worker                      help='fix imports in generated header')
576*6777b538SAndroid Build Coastguard Worker
577*6777b538SAndroid Build Coastguard Worker  parser.add_argument('--swift-toolchain-path',
578*6777b538SAndroid Build Coastguard Worker                      default='',
579*6777b538SAndroid Build Coastguard Worker                      help='path to the Swift toolchain to use')
580*6777b538SAndroid Build Coastguard Worker
581*6777b538SAndroid Build Coastguard Worker  parser.add_argument('--whole-module-optimization',
582*6777b538SAndroid Build Coastguard Worker                      default=False,
583*6777b538SAndroid Build Coastguard Worker                      action='store_true',
584*6777b538SAndroid Build Coastguard Worker                      help='enable whole module optimisation')
585*6777b538SAndroid Build Coastguard Worker
586*6777b538SAndroid Build Coastguard Worker  # Required arguments (forwarded to the Swift compiler).
587*6777b538SAndroid Build Coastguard Worker  parser.add_argument('-target',
588*6777b538SAndroid Build Coastguard Worker                      required=True,
589*6777b538SAndroid Build Coastguard Worker                      dest='target_triple',
590*6777b538SAndroid Build Coastguard Worker                      help='generate code for the given target')
591*6777b538SAndroid Build Coastguard Worker
592*6777b538SAndroid Build Coastguard Worker  parser.add_argument('-sdk',
593*6777b538SAndroid Build Coastguard Worker                      required=True,
594*6777b538SAndroid Build Coastguard Worker                      dest='sdk_path',
595*6777b538SAndroid Build Coastguard Worker                      help='path to the iOS SDK')
596*6777b538SAndroid Build Coastguard Worker
597*6777b538SAndroid Build Coastguard Worker  # Optional arguments (forwarded to the Swift compiler).
598*6777b538SAndroid Build Coastguard Worker  parser.add_argument('-I',
599*6777b538SAndroid Build Coastguard Worker                      action='append',
600*6777b538SAndroid Build Coastguard Worker                      dest='include_dirs',
601*6777b538SAndroid Build Coastguard Worker                      help='add directory to header search path')
602*6777b538SAndroid Build Coastguard Worker
603*6777b538SAndroid Build Coastguard Worker  parser.add_argument('-isystem',
604*6777b538SAndroid Build Coastguard Worker                      action='append',
605*6777b538SAndroid Build Coastguard Worker                      dest='system_include_dirs',
606*6777b538SAndroid Build Coastguard Worker                      help='add directory to system header search path')
607*6777b538SAndroid Build Coastguard Worker
608*6777b538SAndroid Build Coastguard Worker  parser.add_argument('-F',
609*6777b538SAndroid Build Coastguard Worker                      action='append',
610*6777b538SAndroid Build Coastguard Worker                      dest='framework_dirs',
611*6777b538SAndroid Build Coastguard Worker                      help='add directory to framework search path')
612*6777b538SAndroid Build Coastguard Worker
613*6777b538SAndroid Build Coastguard Worker  parser.add_argument('-Fsystem',
614*6777b538SAndroid Build Coastguard Worker                      action='append',
615*6777b538SAndroid Build Coastguard Worker                      dest='system_framework_dirs',
616*6777b538SAndroid Build Coastguard Worker                      help='add directory to system framework search path')
617*6777b538SAndroid Build Coastguard Worker
618*6777b538SAndroid Build Coastguard Worker  parser.add_argument('-D',
619*6777b538SAndroid Build Coastguard Worker                      action='append',
620*6777b538SAndroid Build Coastguard Worker                      dest='defines',
621*6777b538SAndroid Build Coastguard Worker                      help='add preprocessor define')
622*6777b538SAndroid Build Coastguard Worker
623*6777b538SAndroid Build Coastguard Worker  parser.add_argument('-swift-version',
624*6777b538SAndroid Build Coastguard Worker                      default='5',
625*6777b538SAndroid Build Coastguard Worker                      help='version of the Swift language')
626*6777b538SAndroid Build Coastguard Worker
627*6777b538SAndroid Build Coastguard Worker  parser.add_argument('-file-compilation-dir',
628*6777b538SAndroid Build Coastguard Worker                      help='compilation directory to embed in debug info')
629*6777b538SAndroid Build Coastguard Worker
630*6777b538SAndroid Build Coastguard Worker  # Positional arguments.
631*6777b538SAndroid Build Coastguard Worker  parser.add_argument('sources',
632*6777b538SAndroid Build Coastguard Worker                      nargs='+',
633*6777b538SAndroid Build Coastguard Worker                      help='Swift source files to compile')
634*6777b538SAndroid Build Coastguard Worker
635*6777b538SAndroid Build Coastguard Worker  parsed, extras = parser.parse_known_args(args)
636*6777b538SAndroid Build Coastguard Worker  compile_module(parsed, extras, build_signature(os.environ, args))
637*6777b538SAndroid Build Coastguard Worker
638*6777b538SAndroid Build Coastguard Worker
639*6777b538SAndroid Build Coastguard Workerif __name__ == '__main__':
640*6777b538SAndroid Build Coastguard Worker  sys.exit(main(sys.argv[1:]))
641