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