xref: /third_party/gn/build/gen.py (revision 6d528ed9)
1#!/usr/bin/env python3
2# Copyright 2014 The Chromium Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Generates build.ninja that will build GN."""
7
8import argparse
9import os
10import platform
11import re
12import shlex
13import subprocess
14import sys
15
16# IMPORTANT: This script is also executed as python2 on
17# GN's CI builders.
18
19try:  # py3
20    from shlex import quote as shell_quote
21except ImportError:  # py2
22    from pipes import quote as shell_quote
23
24SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
25REPO_ROOT = os.path.dirname(SCRIPT_DIR)
26
27class Platform(object):
28  """Represents a host/target platform."""
29  def __init__(self, platform):
30    self._platform = platform
31    if self._platform is not None:
32      return
33    self._platform = sys.platform
34    if self._platform.startswith('linux'):
35      self._platform = 'linux'
36    elif self._platform.startswith('darwin'):
37      self._platform = 'darwin'
38    elif self._platform.startswith('mingw'):
39      self._platform = 'mingw'
40    elif self._platform.startswith('msys'):
41      self._platform = 'msys'
42    elif self._platform.startswith('win'):
43      self._platform = 'msvc'
44    elif self._platform.startswith('aix'):
45      self._platform = 'aix'
46    elif self._platform.startswith('fuchsia'):
47      self._platform = 'fuchsia'
48    elif self._platform.startswith('freebsd'):
49      self._platform = 'freebsd'
50    elif self._platform.startswith('netbsd'):
51      self._platform = 'netbsd'
52    elif self._platform.startswith('openbsd'):
53      self._platform = 'openbsd'
54    elif self._platform.startswith('haiku'):
55      self._platform = 'haiku'
56    elif self._platform.startswith('sunos'):
57      self._platform = 'solaris'
58    elif self._platform.startswith('zos'):
59      self._platform = 'zos'
60    elif self._platform.startswith('serenity'):
61      self._platform = 'serenity'
62
63  @staticmethod
64  def known_platforms():
65    return ['linux', 'darwin', 'mingw', 'msys', 'msvc', 'aix', 'fuchsia', 'freebsd', 'netbsd', 'openbsd', 'haiku', 'solaris', 'zos', 'serenity']
66
67  def platform(self):
68    return self._platform
69
70  def is_linux(self):
71    return self._platform == 'linux'
72
73  def is_mingw(self):
74    return self._platform == 'mingw'
75
76  def is_msys(self):
77    return self._platform == 'msys'
78
79  def is_msvc(self):
80    return self._platform == 'msvc'
81
82  def is_windows(self):
83    return self.is_mingw() or self.is_msvc()
84
85  def is_darwin(self):
86    return self._platform == 'darwin'
87
88  def is_aix(self):
89    return self._platform == 'aix'
90
91  def is_haiku(self):
92    return self._platform == 'haiku'
93
94  def is_solaris(self):
95    return self._platform == 'solaris'
96
97  def is_posix(self):
98    return self._platform in ['linux', 'freebsd', 'darwin', 'aix', 'openbsd', 'haiku', 'solaris', 'msys', 'netbsd', 'serenity']
99
100  def is_zos(self):
101    return self._platform == 'zos'
102
103  def is_serenity(self):
104    return self_.platform == 'serenity'
105
106class ArgumentsList:
107  """Helper class to accumulate ArgumentParser argument definitions
108  and be able to regenerate a corresponding command-line to be
109  written in the generated Ninja file for the 'regen' rule.
110  """
111  def __init__(self):
112    self._arguments = []
113
114  def add(self, *args, **kwargs):
115    """Add an argument definition, use as argparse.ArgumentParser.add_argument()."""
116    self._arguments.append((args, kwargs))
117
118  def add_to_parser(self, parser):
119    """Add all known arguments to parser."""
120    for args, kwargs in self._arguments:
121      parser.add_argument(*args, **kwargs)
122
123  def gen_command_line_args(self, parser_arguments):
124    """Generate a gen.py argument list to be embedded in a Ninja file."""
125    result = []
126    for args, kwargs in self._arguments:
127      if len(args) == 2:
128        long_option = args[1]
129      else:
130        long_option = args[0]
131      dest = kwargs.get('dest', None)
132      if dest is None:
133        assert long_option.startswith('--')
134        dest = long_option[2:].replace('-', '_')
135
136      if getattr(parser_arguments, dest, None) is None:
137        # This was not set on the command-line so skip it.
138        continue
139
140      action = kwargs.get('action', None)
141      if action == 'store_true':
142        if getattr(parser_arguments, dest):
143          result.append(long_option)
144      elif action == 'store' or action is None:
145        result.append('%s=%s' % (long_option, getattr(parser_arguments, dest)))
146      elif action == 'append':
147        for item in getattr(parser_arguments, dest):
148          result.append('%s=%s' % (long_option, item))
149      else:
150        assert action is None, "Unsupported action " + action
151    if platform.system() == "Windows":
152      return ' '.join(result)
153    else:
154      return ' '.join(shell_quote(item) for item in result)
155
156
157def main(argv):
158  parser = argparse.ArgumentParser(description=sys.modules[__name__].__doc__)
159  args_list = ArgumentsList()
160
161  args_list.add('-d', '--debug', action='store_true',
162                    help='Do a debug build. Defaults to release build.')
163  args_list.add('--platform',
164                    help='target platform (' +
165                         '/'.join(Platform.known_platforms()) + ')',
166                    choices=Platform.known_platforms())
167  args_list.add('--host',
168                    help='host platform (' +
169                         '/'.join(Platform.known_platforms()) + ')',
170                    choices=Platform.known_platforms())
171  args_list.add('--use-lto', action='store_true',
172                    help='Enable the use of LTO')
173  args_list.add('--use-icf', action='store_true',
174                    help='Enable the use of Identical Code Folding')
175  args_list.add('--use-asan', action='store_true',
176                    help='Enable the use of AddressSanitizer')
177  args_list.add('--use-ubsan', action='store_true',
178                    help='Enable the use of UndefinedBehaviorSanitizer')
179  args_list.add('--no-last-commit-position', action='store_true',
180                    help='Do not generate last_commit_position.h.')
181  args_list.add('--out-path', type=str,
182                    default=os.path.join(REPO_ROOT, 'out'),
183                    help='The path to generate the build files in.')
184  args_list.add('--no-strip', action='store_true',
185                    help='Don\'t strip release build. Useful for profiling.')
186  args_list.add('--no-static-libstdc++', action='store_true',
187                    default=False, dest='no_static_libstdcpp',
188                    help='Don\'t link libstdc++ statically')
189  args_list.add('--link-lib',
190                    action='append',
191                    metavar='LINK_LIB',
192                    default=[],
193                    dest='link_libs',
194                    help=('Add a library to the final executable link. ' +
195                          'LINK_LIB must be the path to a static or shared ' +
196                          'library, or \'-l<name>\' on POSIX systems. Can be ' +
197                          'used multiple times. Useful to link custom malloc ' +
198                          'or cpu profiling libraries.'))
199  args_list.add('--allow-warnings', action='store_true', default=False,
200                    help=('Allow compiler warnings, don\'t treat them as '
201                          'errors.'))
202  if sys.platform == 'zos':
203    args_list.add('--zoslib-dir',
204                      action='store',
205                      default='../third_party/zoslib',
206                      dest='zoslib_dir',
207                      help=('Specify the path of ZOSLIB directory, to link ' +
208                            'with <ZOSLIB_DIR>/install/lib/libzoslib.a, and ' +
209                            'add -I<ZOSLIB_DIR>/install/include to the compile ' +
210                            'commands. See README.md for details.'))
211
212  args_list.add_to_parser(parser)
213  options = parser.parse_args(argv)
214
215  platform = Platform(options.platform)
216  if options.host:
217    host = Platform(options.host)
218  else:
219    host = platform
220
221  out_dir = options.out_path or os.path.join(REPO_ROOT, 'out')
222  if not os.path.isdir(out_dir):
223    os.makedirs(out_dir)
224  if not options.no_last_commit_position:
225    GenerateLastCommitPosition(host,
226                               os.path.join(out_dir, 'last_commit_position.h'))
227  WriteGNNinja(os.path.join(out_dir, 'build.ninja'), platform, host, options, args_list)
228  return 0
229
230
231def is_gcc(cxx):
232  """Return True iff the compiler at `cxx` is GCC based."""
233  ret = subprocess.run(
234      f'{cxx} -dM -E -',
235      shell=True,
236      stdin=subprocess.DEVNULL,
237      text=True,
238      capture_output=True)
239
240  return ret.returncode == 0 and "#define __GNUC__" in ret.stdout and not "#define __clang__" in ret.stdout
241
242
243def GenerateLastCommitPosition(host, header):
244  year = "2023"
245  commitID = "d823fd85"
246  contents = '''// Generated by build/gen.py.
247
248#ifndef OUT_LAST_COMMIT_POSITION_H_
249#define OUT_LAST_COMMIT_POSITION_H_
250
251#define LAST_COMMIT_POSITION_NUM %s
252#define LAST_COMMIT_POSITION "%s (%s)"
253
254#endif  // OUT_LAST_COMMIT_POSITION_H_
255''' % (year, year, commitID)
256  with open(header, 'w') as f:
257    f.write(contents)
258
259
260def WriteGenericNinja(path, static_libraries, executables,
261                      cxx, ar, ld, platform, host, options,
262                      args_list, cflags=[], ldflags=[],
263                      libflags=[], include_dirs=[], solibs=[]):
264  args = args_list.gen_command_line_args(options)
265  if args:
266    args = " " + args
267
268  ninja_header_lines = [
269    'cxx = ' + cxx,
270    'ar = ' + ar,
271    'ld = ' + ld,
272    '',
273    'rule regen',
274    '  command = %s ../build/gen.py%s' % (sys.executable, args),
275    '  description = Regenerating ninja files',
276    '',
277    'build build.ninja: regen',
278    '  generator = 1',
279    '  depfile = build.ninja.d',
280    '',
281  ]
282
283
284  template_filename = os.path.join(SCRIPT_DIR, {
285      'msvc': 'build_win.ninja.template',
286      'mingw': 'build_linux.ninja.template',
287      'msys': 'build_linux.ninja.template',
288      'darwin': 'build_mac.ninja.template',
289      'linux': 'build_linux.ninja.template',
290      'freebsd': 'build_linux.ninja.template',
291      'aix': 'build_aix.ninja.template',
292      'openbsd': 'build_openbsd.ninja.template',
293      'haiku': 'build_haiku.ninja.template',
294      'solaris': 'build_linux.ninja.template',
295      'netbsd': 'build_linux.ninja.template',
296      'zos': 'build_zos.ninja.template',
297      'serenity': 'build_linux.ninja.template',
298  }[platform.platform()])
299
300  with open(template_filename) as f:
301    ninja_template = f.read()
302
303  if platform.is_windows():
304    executable_ext = '.exe'
305    library_ext = '.lib'
306    object_ext = '.obj'
307  else:
308    executable_ext = ''
309    library_ext = '.a'
310    object_ext = '.o'
311
312  def escape_path_ninja(path):
313      return path.replace('$ ', '$$ ').replace(' ', '$ ').replace(':', '$:')
314
315  def src_to_obj(path):
316    return escape_path_ninja('%s' % os.path.splitext(path)[0] + object_ext)
317
318  def library_to_a(library):
319    return '%s%s' % (library, library_ext)
320
321  ninja_lines = []
322  def build_source(src_file, settings):
323    ninja_lines.extend([
324        'build %s: cxx %s' % (src_to_obj(src_file),
325                              escape_path_ninja(
326                                  os.path.relpath(
327                                      os.path.join(REPO_ROOT, src_file),
328                                      os.path.dirname(path)))),
329        '  includes = %s' % ' '.join(
330            ['-I' + escape_path_ninja(dirname) for dirname in include_dirs]),
331        '  cflags = %s' % ' '.join(cflags),
332    ])
333
334  for library, settings in static_libraries.items():
335    for src_file in settings['sources']:
336      build_source(src_file, settings)
337
338    ninja_lines.append('build %s: alink_thin %s' % (
339        library_to_a(library),
340        ' '.join([src_to_obj(src_file) for src_file in settings['sources']])))
341    ninja_lines.append('  libflags = %s' % ' '.join(libflags))
342
343
344  for executable, settings in executables.items():
345    for src_file in settings['sources']:
346      build_source(src_file, settings)
347
348    ninja_lines.extend([
349      'build %s%s: link %s | %s' % (
350          executable, executable_ext,
351          ' '.join([src_to_obj(src_file) for src_file in settings['sources']]),
352          ' '.join([library_to_a(library) for library in settings['libs']])),
353      '  ldflags = %s' % ' '.join(ldflags),
354      '  solibs = %s' % ' '.join(solibs),
355      '  libs = %s' % ' '.join(
356          [library_to_a(library) for library in settings['libs']]),
357    ])
358
359  ninja_lines.append('')  # Make sure the file ends with a newline.
360
361  with open(path, 'w') as f:
362    f.write('\n'.join(ninja_header_lines))
363    f.write(ninja_template)
364    f.write('\n'.join(ninja_lines))
365
366  with open(path + '.d', 'w') as f:
367    f.write('build.ninja: ' +
368            os.path.relpath(os.path.join(SCRIPT_DIR, 'gen.py'),
369                            os.path.dirname(path)) + ' ' +
370            os.path.relpath(template_filename, os.path.dirname(path)) + '\n')
371
372
373def WriteGNNinja(path, platform, host, options, args_list):
374  if platform.is_msvc():
375    cxx = os.environ.get('CXX', 'cl.exe')
376    ld = os.environ.get('LD', 'link.exe')
377    ar = os.environ.get('AR', 'lib.exe')
378  elif platform.is_aix():
379    cxx = os.environ.get('CXX', 'g++')
380    ld = os.environ.get('LD', 'g++')
381    ar = os.environ.get('AR', 'ar -X64')
382  elif platform.is_msys() or platform.is_mingw():
383    cxx = os.environ.get('CXX', 'g++')
384    ld = os.environ.get('LD', 'g++')
385    ar = os.environ.get('AR', 'ar')
386  else:
387    cxx = os.environ.get('CXX', 'clang++')
388    ld = cxx
389    ar = os.environ.get('AR', 'ar')
390
391  cflags = os.environ.get('CFLAGS', '').split()
392  cflags += os.environ.get('CXXFLAGS', '').split()
393  ldflags = os.environ.get('LDFLAGS', '').split()
394  libflags = os.environ.get('LIBFLAGS', '').split()
395  include_dirs = [
396      os.path.relpath(os.path.join(REPO_ROOT, 'src'), os.path.dirname(path)),
397      '.',
398  ]
399  if platform.is_zos():
400    include_dirs += [ options.zoslib_dir + '/install/include' ]
401
402  libs = []
403
404  if not platform.is_msvc():
405    if options.debug:
406      cflags.extend(['-O0', '-g'])
407      # Enable libc++ or libstdc++ assertions in debug mode.
408      # Just set both macros to avoid detecting the C++ runtime being used.
409      # Currently disabled on MacOS since this results in linking errors at the
410      # moment, due to what looks like an XCode-specific Clang packaging error.
411      if not platform.is_darwin():
412        cflags.extend(['-D_LIBCPP_DEBUG=1', '-D_GLIBCXX_DEBUG=1'])
413    else:
414      cflags.append('-DNDEBUG')
415      cflags.append('-O3')
416      if options.no_strip:
417        cflags.append('-g')
418      ldflags.append('-O3')
419      # Use -fdata-sections and -ffunction-sections to place each function
420      # or data item into its own section so --gc-sections can eliminate any
421      # unused functions and data items.
422      cflags.extend(['-fdata-sections', '-ffunction-sections'])
423      ldflags.extend(['-fdata-sections', '-ffunction-sections'])
424      if platform.is_darwin():
425        ldflags.append('-Wl,-dead_strip')
426      elif not platform.is_aix() and not platform.is_solaris() and not platform.is_zos():
427        # Garbage collection is done by default on aix, and option is unsupported on z/OS.
428        ldflags.append('-Wl,--gc-sections')
429
430      # Omit all symbol information from the output file.
431      if options.no_strip is None:
432        if platform.is_darwin():
433          ldflags.append('-Wl,-S')
434        elif platform.is_aix():
435          ldflags.append('-Wl,-s')
436        elif platform.is_solaris():
437          ldflags.append('-Wl,--strip-all')
438        elif not platform.is_zos():
439          # /bin/ld on z/OS doesn't have an equivalent option.
440          ldflags.append('-Wl,-strip-all')
441
442      # Enable identical code-folding.
443      if options.use_icf and not platform.is_darwin():
444        ldflags.append('-Wl,--icf=all')
445
446      if options.use_lto:
447        cflags.extend(['-flto', '-fwhole-program-vtables'])
448        ldflags.extend(['-flto', '-fwhole-program-vtables'])
449
450    if options.use_asan:
451      cflags.append('-fsanitize=address')
452      ldflags.append('-fsanitize=address')
453
454    if options.use_ubsan:
455      cflags.append('-fsanitize=undefined')
456      ldflags.append('-fsanitize=undefined')
457
458    if not options.allow_warnings:
459      cflags.append('-Werror')
460
461    cflags.extend([
462        '-D_FILE_OFFSET_BITS=64',
463        '-D__STDC_CONSTANT_MACROS', '-D__STDC_FORMAT_MACROS',
464        '-pthread',
465        '-pipe',
466        '-fno-exceptions',
467        '-fno-rtti',
468        '-fdiagnostics-color',
469        '-Wall',
470        '-Wextra',
471        '-Wno-unused-parameter',
472        '-Wextra-semi',
473        '-Wundef',
474        '-std=c++20'
475    ])
476
477    if is_gcc(cxx):
478      cflags.append('-Wno-redundant-move')
479      # https://gcc.gnu.org/bugzilla/show_bug.cgi?id=104336
480      cflags.append('-Wno-restrict')
481    # flags not supported by gcc/g++.
482    else:
483      cflags.extend(['-Wrange-loop-analysis', '-Wextra-semi-stmt'])
484
485    if platform.is_linux() or platform.is_mingw() or platform.is_msys():
486      ldflags.append('-Wl,--as-needed')
487
488      if not options.no_static_libstdcpp:
489        ldflags.append('-static-libstdc++')
490
491      if platform.is_linux():
492        ldflags.append('-Wl,-z,relro,-z,now')
493
494      if platform.is_mingw() or platform.is_msys():
495        cflags.remove('-std=c++20')
496        cflags.extend([
497          '-Wno-deprecated-copy',
498          '-Wno-implicit-fallthrough',
499          '-Wno-redundant-move',
500          '-Wno-unused-variable',
501          '-Wno-format',             # Use of %llx, which is supported by _UCRT, false positive
502          '-Wno-strict-aliasing',    # Dereferencing punned pointer
503          '-Wno-cast-function-type', # Casting FARPROC to RegDeleteKeyExPtr
504          '-std=gnu++20',
505        ])
506      else:
507        # This is needed by libc++.
508        libs.append('-ldl')
509    elif platform.is_darwin():
510      min_mac_version_flag = '-mmacosx-version-min=10.9'
511      cflags.append(min_mac_version_flag)
512      ldflags.append(min_mac_version_flag)
513    elif platform.is_aix():
514      cflags.append('-maix64')
515      ldflags.append('-maix64')
516    elif platform.is_haiku():
517      cflags.append('-fPIC')
518      cflags.extend(['-D_BSD_SOURCE'])
519    elif platform.is_zos():
520      cflags.append('-fzos-le-char-mode=ascii')
521      cflags.append('-Wno-unused-function')
522      cflags.append('-D_OPEN_SYS_FILE_EXT')
523      cflags.append('-DPATH_MAX=1024')
524      cflags.append('-DZOSLIB_OVERRIDE_CLIB')
525
526    if platform.is_posix() and not platform.is_haiku():
527      ldflags.append('-pthread')
528
529    if platform.is_mingw() or platform.is_msys():
530      cflags.extend(['-DUNICODE',
531                     '-DNOMINMAX',
532                     '-DWIN32_LEAN_AND_MEAN',
533                     '-DWINVER=0x0A00',
534                     '-D_CRT_SECURE_NO_DEPRECATE',
535                     '-D_SCL_SECURE_NO_DEPRECATE',
536                     '-D_UNICODE',
537                     '-D_WIN32_WINNT=0x0A00',
538                     '-D_HAS_EXCEPTIONS=0'
539      ])
540  elif platform.is_msvc():
541    if not options.debug:
542      cflags.extend(['/O2', '/DNDEBUG', '/Zc:inline'])
543      ldflags.extend(['/OPT:REF'])
544
545      if options.use_icf:
546        libflags.extend(['/OPT:ICF'])
547      if options.use_lto:
548        cflags.extend(['/GL'])
549        libflags.extend(['/LTCG'])
550        ldflags.extend(['/LTCG'])
551
552    if not options.allow_warnings:
553      cflags.append('/WX')
554
555    cflags.extend([
556        '/DNOMINMAX',
557        '/DUNICODE',
558        '/DWIN32_LEAN_AND_MEAN',
559        '/DWINVER=0x0A00',
560        '/D_CRT_SECURE_NO_DEPRECATE',
561        '/D_SCL_SECURE_NO_DEPRECATE',
562        '/D_UNICODE',
563        '/D_WIN32_WINNT=0x0A00',
564        '/FS',
565        '/W4',
566        '/WX',
567        '/Zi',
568        '/wd4099',
569        '/wd4100',
570        '/wd4127',
571        '/wd4244',
572        '/wd4267',
573        '/wd4505',
574        '/wd4838',
575        '/wd4996',
576        '/std:c++20',
577        '/GR-',
578        '/D_HAS_EXCEPTIONS=0',
579    ])
580
581    win_manifest = os.path.relpath(
582      os.path.join(REPO_ROOT, "build/windows.manifest.xml"), options.out_path)
583    ldflags.extend(['/DEBUG', '/MACHINE:x64', '/MANIFEST:EMBED',
584                    f'/MANIFESTINPUT:{win_manifest}'])
585
586  static_libraries = {
587      'base': {'sources': [
588        'src/base/command_line.cc',
589        'src/base/environment.cc',
590        'src/base/files/file.cc',
591        'src/base/files/file_enumerator.cc',
592        'src/base/files/file_path.cc',
593        'src/base/files/file_path_constants.cc',
594        'src/base/files/file_util.cc',
595        'src/base/files/scoped_file.cc',
596        'src/base/files/scoped_temp_dir.cc',
597        'src/base/json/json_parser.cc',
598        'src/base/json/json_reader.cc',
599        'src/base/json/json_writer.cc',
600        'src/base/json/string_escape.cc',
601        'src/base/logging.cc',
602        'src/base/md5.cc',
603        'src/base/memory/ref_counted.cc',
604        'src/base/memory/weak_ptr.cc',
605        'src/base/sha1.cc',
606        'src/base/strings/string_number_conversions.cc',
607        'src/base/strings/string_split.cc',
608        'src/base/strings/string_util.cc',
609        'src/base/strings/string_util_constants.cc',
610        'src/base/strings/stringprintf.cc',
611        'src/base/strings/utf_string_conversion_utils.cc',
612        'src/base/strings/utf_string_conversions.cc',
613        'src/base/third_party/icu/icu_utf.cc',
614        'src/base/timer/elapsed_timer.cc',
615        'src/base/value_iterators.cc',
616        'src/base/values.cc',
617      ]},
618      'gn_lib': {'sources': [
619        'src/gn/action_target_generator.cc',
620        'src/gn/action_values.cc',
621        'src/gn/analyzer.cc',
622        'src/gn/args.cc',
623        'src/gn/binary_target_generator.cc',
624        'src/gn/build_settings.cc',
625        'src/gn/builder.cc',
626        'src/gn/builder_record.cc',
627        'src/gn/bundle_data.cc',
628        'src/gn/bundle_data_target_generator.cc',
629        'src/gn/bundle_file_rule.cc',
630        'src/gn/builtin_tool.cc',
631        'src/gn/c_include_iterator.cc',
632        'src/gn/c_substitution_type.cc',
633        'src/gn/c_tool.cc',
634        'src/gn/command_analyze.cc',
635        'src/gn/command_args.cc',
636        'src/gn/command_check.cc',
637        'src/gn/command_clean.cc',
638        'src/gn/command_clean_stale.cc',
639        'src/gn/command_desc.cc',
640        'src/gn/command_format.cc',
641        'src/gn/command_gen.cc',
642        'src/gn/command_help.cc',
643        'src/gn/command_ls.cc',
644        'src/gn/command_meta.cc',
645        'src/gn/command_outputs.cc',
646        'src/gn/command_path.cc',
647        'src/gn/command_refs.cc',
648        'src/gn/commands.cc',
649        'src/gn/compile_commands_writer.cc',
650        'src/gn/rust_project_writer.cc',
651        'src/gn/config.cc',
652        'src/gn/config_values.cc',
653        'src/gn/config_values_extractors.cc',
654        'src/gn/config_values_generator.cc',
655        'src/gn/copy_target_generator.cc',
656        'src/gn/create_bundle_target_generator.cc',
657        'src/gn/deps_iterator.cc',
658        'src/gn/desc_builder.cc',
659        'src/gn/eclipse_writer.cc',
660        'src/gn/err.cc',
661        'src/gn/escape.cc',
662        'src/gn/exec_process.cc',
663        'src/gn/filesystem_utils.cc',
664        'src/gn/file_writer.cc',
665        'src/gn/frameworks_utils.cc',
666        'src/gn/function_exec_script.cc',
667        'src/gn/function_filter.cc',
668        'src/gn/function_filter_labels.cc',
669        'src/gn/function_foreach.cc',
670        'src/gn/function_forward_variables_from.cc',
671        'src/gn/function_get_label_info.cc',
672        'src/gn/function_get_path_info.cc',
673        'src/gn/function_get_target_outputs.cc',
674        'src/gn/function_label_matches.cc',
675        'src/gn/invoke_python.cc',
676        'src/gn/function_process_file_template.cc',
677        'src/gn/function_read_file.cc',
678        'src/gn/function_rebase_path.cc',
679        'src/gn/function_set_default_toolchain.cc',
680        'src/gn/function_set_defaults.cc',
681        'src/gn/function_template.cc',
682        'src/gn/function_toolchain.cc',
683        'src/gn/function_write_file.cc',
684        'src/gn/functions.cc',
685        'src/gn/functions_target.cc',
686        'src/gn/general_tool.cc',
687        'src/gn/generated_file_target_generator.cc',
688        'src/gn/group_target_generator.cc',
689        'src/gn/header_checker.cc',
690        'src/gn/import_manager.cc',
691        'src/gn/inherited_libraries.cc',
692        "src/gn/innerapis_publicinfo_generator.cc",
693        'src/gn/input_conversion.cc',
694        'src/gn/input_file.cc',
695        'src/gn/input_file_manager.cc',
696        'src/gn/item.cc',
697        'src/gn/json_project_writer.cc',
698        'src/gn/label.cc',
699        'src/gn/label_pattern.cc',
700        'src/gn/lib_file.cc',
701        'src/gn/loader.cc',
702        'src/gn/location.cc',
703        'src/gn/metadata.cc',
704        'src/gn/metadata_walk.cc',
705        'src/gn/ninja_action_target_writer.cc',
706        'src/gn/ninja_binary_target_writer.cc',
707        'src/gn/ninja_build_writer.cc',
708        'src/gn/ninja_bundle_data_target_writer.cc',
709        'src/gn/ninja_c_binary_target_writer.cc',
710        'src/gn/ninja_copy_target_writer.cc',
711        'src/gn/ninja_create_bundle_target_writer.cc',
712        'src/gn/ninja_generated_file_target_writer.cc',
713        'src/gn/ninja_group_target_writer.cc',
714        'src/gn/ninja_outputs_writer.cc',
715        'src/gn/ninja_rust_binary_target_writer.cc',
716        'src/gn/ninja_target_command_util.cc',
717        'src/gn/ninja_target_writer.cc',
718        'src/gn/ninja_toolchain_writer.cc',
719        'src/gn/ninja_tools.cc',
720        'src/gn/ninja_utils.cc',
721        'src/gn/ninja_writer.cc',
722        'src/gn/ohos_components.cc',
723        "src/gn/ohos_components_checker.cc",
724        "src/gn/ohos_components_mapping.cc",
725        'src/gn/ohos_variables.cc',
726        'src/gn/operators.cc',
727        'src/gn/output_conversion.cc',
728        'src/gn/output_file.cc',
729        'src/gn/parse_node_value_adapter.cc',
730        'src/gn/parse_tree.cc',
731        'src/gn/parser.cc',
732        'src/gn/path_output.cc',
733        'src/gn/pattern.cc',
734        'src/gn/pool.cc',
735        'src/gn/qt_creator_writer.cc',
736        'src/gn/resolved_target_data.cc',
737        'src/gn/runtime_deps.cc',
738        'src/gn/rust_substitution_type.cc',
739        'src/gn/rust_tool.cc',
740        'src/gn/rust_values.cc',
741        'src/gn/rust_values_generator.cc',
742        'src/gn/rust_variables.cc',
743        'src/gn/scheduler.cc',
744        'src/gn/scope.cc',
745        'src/gn/scope_per_file_provider.cc',
746        'src/gn/settings.cc',
747        'src/gn/setup.cc',
748        'src/gn/source_dir.cc',
749        'src/gn/source_file.cc',
750        'src/gn/standard_out.cc',
751        'src/gn/string_atom.cc',
752        'src/gn/string_output_buffer.cc',
753        'src/gn/string_utils.cc',
754        'src/gn/substitution_list.cc',
755        'src/gn/substitution_pattern.cc',
756        'src/gn/substitution_type.cc',
757        'src/gn/substitution_writer.cc',
758        'src/gn/swift_values.cc',
759        'src/gn/swift_values_generator.cc',
760        'src/gn/swift_variables.cc',
761        'src/gn/switches.cc',
762        'src/gn/target.cc',
763        'src/gn/target_generator.cc',
764        'src/gn/template.cc',
765        'src/gn/token.cc',
766        'src/gn/tokenizer.cc',
767        'src/gn/tool.cc',
768        'src/gn/toolchain.cc',
769        'src/gn/trace.cc',
770        'src/gn/value.cc',
771        'src/gn/value_extractors.cc',
772        'src/gn/variables.cc',
773        'src/gn/version.cc',
774        'src/gn/visibility.cc',
775        'src/gn/visual_studio_utils.cc',
776        'src/gn/visual_studio_writer.cc',
777        'src/gn/xcode_object.cc',
778        'src/gn/xcode_writer.cc',
779        'src/gn/xml_element_writer.cc',
780        'src/util/atomic_write.cc',
781        'src/util/exe_path.cc',
782        'src/util/msg_loop.cc',
783        'src/util/semaphore.cc',
784        'src/util/sys_info.cc',
785        'src/util/ticks.cc',
786        'src/util/worker_pool.cc',
787      ]},
788  }
789
790  executables = {
791      'gn': {'sources': [ 'src/gn/gn_main.cc' ], 'libs': []},
792
793      'gn_unittests': { 'sources': [
794        'src/gn/action_target_generator_unittest.cc',
795        'src/gn/analyzer_unittest.cc',
796        'src/gn/args_unittest.cc',
797        'src/gn/builder_record_map_unittest.cc',
798        'src/gn/builder_unittest.cc',
799        'src/gn/bundle_data_unittest.cc',
800        'src/gn/c_include_iterator_unittest.cc',
801        'src/gn/command_format_unittest.cc',
802        'src/gn/commands_unittest.cc',
803        'src/gn/compile_commands_writer_unittest.cc',
804        'src/gn/config_unittest.cc',
805        'src/gn/config_values_extractors_unittest.cc',
806        'src/gn/escape_unittest.cc',
807        'src/gn/exec_process_unittest.cc',
808        'src/gn/filesystem_utils_unittest.cc',
809        'src/gn/file_writer_unittest.cc',
810        'src/gn/frameworks_utils_unittest.cc',
811        'src/gn/function_filter_unittest.cc',
812        'src/gn/function_filter_labels_unittest.cc',
813        'src/gn/function_foreach_unittest.cc',
814        'src/gn/function_forward_variables_from_unittest.cc',
815        'src/gn/function_get_label_info_unittest.cc',
816        'src/gn/function_get_path_info_unittest.cc',
817        'src/gn/function_get_target_outputs_unittest.cc',
818        'src/gn/function_label_matches_unittest.cc',
819        'src/gn/function_process_file_template_unittest.cc',
820        'src/gn/function_rebase_path_unittest.cc',
821        'src/gn/function_template_unittest.cc',
822        'src/gn/function_toolchain_unittest.cc',
823        'src/gn/function_write_file_unittest.cc',
824        'src/gn/functions_target_rust_unittest.cc',
825        'src/gn/functions_target_unittest.cc',
826        'src/gn/functions_unittest.cc',
827        'src/gn/hash_table_base_unittest.cc',
828        'src/gn/header_checker_unittest.cc',
829        'src/gn/immutable_vector_unittest.cc',
830        'src/gn/inherited_libraries_unittest.cc',
831        'src/gn/input_conversion_unittest.cc',
832        'src/gn/json_project_writer_unittest.cc',
833        'src/gn/rust_project_writer_unittest.cc',
834        'src/gn/rust_project_writer_helpers_unittest.cc',
835        'src/gn/label_pattern_unittest.cc',
836        'src/gn/label_unittest.cc',
837        'src/gn/loader_unittest.cc',
838        'src/gn/metadata_unittest.cc',
839        'src/gn/metadata_walk_unittest.cc',
840        'src/gn/ninja_action_target_writer_unittest.cc',
841        'src/gn/ninja_binary_target_writer_unittest.cc',
842        'src/gn/ninja_build_writer_unittest.cc',
843        'src/gn/ninja_bundle_data_target_writer_unittest.cc',
844        'src/gn/ninja_c_binary_target_writer_unittest.cc',
845        'src/gn/ninja_copy_target_writer_unittest.cc',
846        'src/gn/ninja_create_bundle_target_writer_unittest.cc',
847        'src/gn/ninja_generated_file_target_writer_unittest.cc',
848        'src/gn/ninja_group_target_writer_unittest.cc',
849        'src/gn/ninja_outputs_writer_unittest.cc',
850        'src/gn/ninja_rust_binary_target_writer_unittest.cc',
851        'src/gn/ninja_target_command_util_unittest.cc',
852        'src/gn/ninja_target_writer_unittest.cc',
853        'src/gn/ninja_toolchain_writer_unittest.cc',
854        'src/gn/ohos_components_unittest.cc',
855        'src/gn/operators_unittest.cc',
856        'src/gn/output_conversion_unittest.cc',
857        'src/gn/parse_tree_unittest.cc',
858        'src/gn/parser_unittest.cc',
859        'src/gn/path_output_unittest.cc',
860        'src/gn/pattern_unittest.cc',
861        'src/gn/pointer_set_unittest.cc',
862        'src/gn/resolved_target_data_unittest.cc',
863        'src/gn/resolved_target_deps_unittest.cc',
864        'src/gn/runtime_deps_unittest.cc',
865        'src/gn/scope_per_file_provider_unittest.cc',
866        'src/gn/scope_unittest.cc',
867        'src/gn/setup_unittest.cc',
868        'src/gn/source_dir_unittest.cc',
869        'src/gn/source_file_unittest.cc',
870        'src/gn/string_atom_unittest.cc',
871        'src/gn/string_output_buffer_unittest.cc',
872        'src/gn/string_utils_unittest.cc',
873        'src/gn/substitution_pattern_unittest.cc',
874        'src/gn/substitution_writer_unittest.cc',
875        'src/gn/tagged_pointer_unittest.cc',
876        'src/gn/target_unittest.cc',
877        'src/gn/target_public_pair_unittest.cc',
878        'src/gn/template_unittest.cc',
879        'src/gn/test_with_scheduler.cc',
880        'src/gn/test_with_scope.cc',
881        'src/gn/tokenizer_unittest.cc',
882        'src/gn/unique_vector_unittest.cc',
883        'src/gn/value_unittest.cc',
884        'src/gn/vector_utils_unittest.cc',
885        'src/gn/version_unittest.cc',
886        'src/gn/visibility_unittest.cc',
887        'src/gn/visual_studio_utils_unittest.cc',
888        'src/gn/visual_studio_writer_unittest.cc',
889        'src/gn/xcode_object_unittest.cc',
890        'src/gn/xml_element_writer_unittest.cc',
891        'src/util/atomic_write_unittest.cc',
892        'src/util/test/gn_test.cc',
893      ], 'libs': []},
894  }
895
896  if platform.is_posix() or platform.is_zos():
897    static_libraries['base']['sources'].extend([
898        'src/base/files/file_enumerator_posix.cc',
899        'src/base/files/file_posix.cc',
900        'src/base/files/file_util_posix.cc',
901        'src/base/posix/file_descriptor_shuffle.cc',
902        'src/base/posix/safe_strerror.cc',
903    ])
904
905  if platform.is_zos():
906    libs.extend([ options.zoslib_dir + '/install/lib/libzoslib.a' ])
907
908  if platform.is_windows():
909    static_libraries['base']['sources'].extend([
910        'src/base/files/file_enumerator_win.cc',
911        'src/base/files/file_util_win.cc',
912        'src/base/files/file_win.cc',
913        'src/base/win/registry.cc',
914        'src/base/win/scoped_handle.cc',
915        'src/base/win/scoped_process_information.cc',
916    ])
917
918    if platform.is_msvc():
919      libs.extend([
920          'advapi32.lib',
921          'dbghelp.lib',
922          'kernel32.lib',
923          'ole32.lib',
924          'shell32.lib',
925          'user32.lib',
926          'userenv.lib',
927          'version.lib',
928          'winmm.lib',
929          'ws2_32.lib',
930          'Shlwapi.lib',
931      ])
932    else:
933      libs.extend([
934          '-ladvapi32',
935          '-ldbghelp',
936          '-lkernel32',
937          '-lole32',
938          '-lshell32',
939          '-luser32',
940          '-luserenv',
941          '-lversion',
942          '-lwinmm',
943          '-lws2_32',
944          '-lshlwapi',
945      ])
946
947
948  libs.extend(options.link_libs)
949
950  # we just build static libraries that GN needs
951  executables['gn']['libs'].extend(static_libraries.keys())
952  executables['gn_unittests']['libs'].extend(static_libraries.keys())
953
954  WriteGenericNinja(path, static_libraries, executables, cxx, ar, ld,
955                    platform, host, options, args_list,
956                    cflags, ldflags, libflags, include_dirs, libs)
957
958if __name__ == '__main__':
959  sys.exit(main(sys.argv[1:]))
960