• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/usr/bin/env python
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 contextlib
9import errno
10import optparse
11import os
12import platform
13import re
14import subprocess
15import sys
16import tempfile
17
18SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
19REPO_ROOT = os.path.dirname(SCRIPT_DIR)
20
21
22class Platform(object):
23  """Represents a host/target platform."""
24  def __init__(self, platform):
25    self._platform = platform
26    if self._platform is not None:
27      return
28    self._platform = sys.platform
29    if self._platform.startswith('linux'):
30      self._platform = 'linux'
31    elif self._platform.startswith('darwin'):
32      self._platform = 'darwin'
33    elif self._platform.startswith('mingw'):
34      self._platform = 'mingw'
35    elif self._platform.startswith('win'):
36      self._platform = 'msvc'
37    elif self._platform.startswith('aix'):
38      self._platform = 'aix'
39    elif self._platform.startswith('fuchsia'):
40      self._platform = 'fuchsia'
41    elif self._platform.startswith('freebsd'):
42      self._platform = 'freebsd'
43    elif self._platform.startswith('openbsd'):
44      self._platform = 'openbsd'
45    elif self._platform.startswith('haiku'):
46      self._platform = 'haiku'
47
48  @staticmethod
49  def known_platforms():
50    return ['linux', 'darwin', 'mingw', 'msvc', 'aix', 'fuchsia', 'freebsd', 'openbsd', 'haiku']
51
52  def platform(self):
53    return self._platform
54
55  def is_linux(self):
56    return self._platform == 'linux'
57
58  def is_mingw(self):
59    return self._platform == 'mingw'
60
61  def is_msvc(self):
62    return self._platform == 'msvc'
63
64  def is_windows(self):
65    return self.is_mingw() or self.is_msvc()
66
67  def is_darwin(self):
68    return self._platform == 'darwin'
69
70  def is_aix(self):
71    return self._platform == 'aix'
72
73  def is_haiku(self):
74    return self._platform == 'haiku'
75
76  def is_posix(self):
77    return self._platform in ['linux', 'freebsd', 'darwin', 'aix', 'openbsd', 'haiku']
78
79
80def main(argv):
81  parser = optparse.OptionParser(description=sys.modules[__name__].__doc__)
82  parser.add_option('-d', '--debug', action='store_true',
83                    help='Do a debug build. Defaults to release build.')
84  parser.add_option('--platform',
85                    help='target platform (' +
86                         '/'.join(Platform.known_platforms()) + ')',
87                    choices=Platform.known_platforms())
88  parser.add_option('--host',
89                    help='host platform (' +
90                         '/'.join(Platform.known_platforms()) + ')',
91                    choices=Platform.known_platforms())
92  parser.add_option('--use-lto', action='store_true',
93                    help='Enable the use of LTO')
94  parser.add_option('--use-icf', action='store_true',
95                    help='Enable the use of Identical Code Folding')
96  parser.add_option('--no-last-commit-position', action='store_true',
97                    help='Do not generate last_commit_position.h.')
98  parser.add_option('--out-path',
99                    help='The path to generate the build files in.')
100  parser.add_option('--no-strip', action='store_true',
101                    help='Don\'t strip release build. Useful for profiling.')
102  parser.add_option('--no-static-libstdc++', action='store_true',
103                    default=False, dest='no_static_libstdcpp',
104                    help='Don\'t link libstdc++ statically')
105  options, args = parser.parse_args(argv)
106
107  if args:
108    parser.error('Unrecognized command line arguments: %s.' % ', '.join(args))
109
110  platform = Platform(options.platform)
111  if options.host:
112    host = Platform(options.host)
113  else:
114    host = platform
115
116  out_dir = options.out_path or os.path.join(REPO_ROOT, 'out')
117  if not os.path.isdir(out_dir):
118    os.makedirs(out_dir)
119  if not options.no_last_commit_position:
120    GenerateLastCommitPosition(host,
121                               os.path.join(out_dir, 'last_commit_position.h'))
122  WriteGNNinja(os.path.join(out_dir, 'build.ninja'), platform, host, options)
123  return 0
124
125
126def GenerateLastCommitPosition(host, header):
127  ROOT_TAG = 'initial-commit'
128  describe_output = subprocess.check_output(
129      ['git', 'describe', 'HEAD', '--match', ROOT_TAG], shell=host.is_windows(),
130      cwd=REPO_ROOT)
131  mo = re.match(ROOT_TAG + '-(\d+)-g([0-9a-f]+)', describe_output.decode())
132  if not mo:
133    raise ValueError(
134        'Unexpected output from git describe when generating version header')
135
136  contents = '''// Generated by build/gen.py.
137
138#ifndef OUT_LAST_COMMIT_POSITION_H_
139#define OUT_LAST_COMMIT_POSITION_H_
140
141#define LAST_COMMIT_POSITION_NUM %s
142#define LAST_COMMIT_POSITION "%s (%s)"
143
144#endif  // OUT_LAST_COMMIT_POSITION_H_
145''' % (mo.group(1), mo.group(1), mo.group(2))
146
147  # Only write/touch this file if the commit position has changed.
148  old_contents = ''
149  if os.path.isfile(header):
150    with open(header, 'r') as f:
151      old_contents = f.read()
152
153  if old_contents != contents:
154    with open(header, 'w') as f:
155      f.write(contents)
156
157
158def WriteGenericNinja(path, static_libraries, executables,
159                      cxx, ar, ld, platform, host, options,
160                      cflags=[], ldflags=[], libflags=[],
161                      include_dirs=[], solibs=[]):
162  ninja_header_lines = [
163    'cxx = ' + cxx,
164    'ar = ' + ar,
165    'ld = ' + ld,
166    '',
167    'rule regen',
168    '  command = %s ../build/gen.py%s' % (
169        sys.executable, ' -d' if options.debug else ''),
170    '  description = Regenerating ninja files',
171    '',
172    'build build.ninja: regen',
173    '  generator = 1',
174    '  depfile = build.ninja.d',
175    '',
176  ]
177
178
179  template_filename = os.path.join(SCRIPT_DIR, {
180      'msvc': 'build_win.ninja.template',
181      'mingw': 'build_linux.ninja.template',
182      'darwin': 'build_mac.ninja.template',
183      'linux': 'build_linux.ninja.template',
184      'freebsd': 'build_linux.ninja.template',
185      'aix': 'build_aix.ninja.template',
186      'openbsd': 'build_openbsd.ninja.template',
187      'haiku': 'build_haiku.ninja.template',
188  }[platform.platform()])
189
190  with open(template_filename) as f:
191    ninja_template = f.read()
192
193  if platform.is_windows():
194    executable_ext = '.exe'
195    library_ext = '.lib'
196    object_ext = '.obj'
197  else:
198    executable_ext = ''
199    library_ext = '.a'
200    object_ext = '.o'
201
202  def escape_path_ninja(path):
203      return path.replace('$ ', '$$ ').replace(' ', '$ ').replace(':', '$:')
204
205  def src_to_obj(path):
206    return escape_path_ninja('%s' % os.path.splitext(path)[0] + object_ext)
207
208  def library_to_a(library):
209    return '%s%s' % (library, library_ext)
210
211  ninja_lines = []
212  def build_source(src_file, settings):
213    ninja_lines.extend([
214        'build %s: cxx %s' % (src_to_obj(src_file),
215                              escape_path_ninja(
216                                  os.path.relpath(
217                                      os.path.join(REPO_ROOT, src_file),
218                                      os.path.dirname(path)))),
219        '  includes = %s' % ' '.join(
220            ['-I' + escape_path_ninja(dirname) for dirname in include_dirs]),
221        '  cflags = %s' % ' '.join(cflags),
222    ])
223
224  for library, settings in static_libraries.items():
225    for src_file in settings['sources']:
226      build_source(src_file, settings)
227
228    ninja_lines.append('build %s: alink_thin %s' % (
229        library_to_a(library),
230        ' '.join([src_to_obj(src_file) for src_file in settings['sources']])))
231    ninja_lines.append('  libflags = %s' % ' '.join(libflags))
232
233
234  for executable, settings in executables.items():
235    for src_file in settings['sources']:
236      build_source(src_file, settings)
237
238    ninja_lines.extend([
239      'build %s%s: link %s | %s' % (
240          executable, executable_ext,
241          ' '.join([src_to_obj(src_file) for src_file in settings['sources']]),
242          ' '.join([library_to_a(library) for library in settings['libs']])),
243      '  ldflags = %s' % ' '.join(ldflags),
244      '  solibs = %s' % ' '.join(solibs),
245      '  libs = %s' % ' '.join(
246          [library_to_a(library) for library in settings['libs']]),
247    ])
248
249  ninja_lines.append('')  # Make sure the file ends with a newline.
250
251  with open(path, 'w') as f:
252    f.write('\n'.join(ninja_header_lines))
253    f.write(ninja_template)
254    f.write('\n'.join(ninja_lines))
255
256  with open(path + '.d', 'w') as f:
257    f.write('build.ninja: ' +
258            os.path.relpath(os.path.join(SCRIPT_DIR, 'gen.py'),
259                            os.path.dirname(path)) + ' ' +
260            os.path.relpath(template_filename, os.path.dirname(path)) + '\n')
261
262
263def WriteGNNinja(path, platform, host, options):
264  if platform.is_msvc():
265    cxx = os.environ.get('CXX', 'cl.exe')
266    ld = os.environ.get('LD', 'link.exe')
267    ar = os.environ.get('AR', 'lib.exe')
268  elif platform.is_aix():
269    cxx = os.environ.get('CXX', 'g++')
270    ld = os.environ.get('LD', 'g++')
271    ar = os.environ.get('AR', 'ar -X64')
272  else:
273    cxx = os.environ.get('CXX', 'clang++')
274    ld = cxx
275    ar = os.environ.get('AR', 'ar')
276
277  cflags = os.environ.get('CFLAGS', '').split()
278  cflags += os.environ.get('CXXFLAGS', '').split()
279  ldflags = os.environ.get('LDFLAGS', '').split()
280  libflags = os.environ.get('LIBFLAGS', '').split()
281  include_dirs = [
282      os.path.relpath(os.path.join(REPO_ROOT, 'src'), os.path.dirname(path)),
283      '.',
284  ]
285  libs = []
286
287  if not platform.is_msvc():
288    if options.debug:
289      cflags.extend(['-O0', '-g'])
290    else:
291      cflags.append('-DNDEBUG')
292      cflags.append('-O3')
293      if options.no_strip:
294        cflags.append('-g')
295      ldflags.append('-O3')
296      # Use -fdata-sections and -ffunction-sections to place each function
297      # or data item into its own section so --gc-sections can eliminate any
298      # unused functions and data items.
299      cflags.extend(['-fdata-sections', '-ffunction-sections'])
300      ldflags.extend(['-fdata-sections', '-ffunction-sections'])
301      if platform.is_darwin():
302        ldflags.append('-Wl,-dead_strip')
303      elif not platform.is_aix():
304        # Garbage collection is done by default on aix.
305        ldflags.append('-Wl,--gc-sections')
306
307      # Omit all symbol information from the output file.
308      if options.no_strip is None:
309        if platform.is_darwin():
310          ldflags.append('-Wl,-S')
311        elif platform.is_aix():
312          ldflags.append('-Wl,-s')
313        else:
314          ldflags.append('-Wl,-strip-all')
315
316      # Enable identical code-folding.
317      if options.use_icf and not platform.is_darwin():
318        ldflags.append('-Wl,--icf=all')
319
320      if options.use_lto:
321        cflags.extend(['-flto', '-fwhole-program-vtables'])
322        ldflags.extend(['-flto', '-fwhole-program-vtables'])
323
324    cflags.extend([
325        '-D_FILE_OFFSET_BITS=64',
326        '-D__STDC_CONSTANT_MACROS', '-D__STDC_FORMAT_MACROS',
327        '-pthread',
328        '-pipe',
329        '-fno-exceptions',
330        '-fno-rtti',
331        '-fdiagnostics-color',
332        '-Wall',
333        '-Wextra',
334        '-Wno-unused-parameter',
335        '-std=c++17'
336    ])
337
338    if platform.is_linux() or platform.is_mingw():
339      ldflags.append('-Wl,--as-needed')
340
341      if not options.no_static_libstdcpp:
342        ldflags.append('-static-libstdc++')
343
344      # This is needed by libc++.
345      if not platform.is_mingw():
346        libs.append('-ldl')
347    elif platform.is_darwin():
348      min_mac_version_flag = '-mmacosx-version-min=10.9'
349      cflags.append(min_mac_version_flag)
350      ldflags.append(min_mac_version_flag)
351    elif platform.is_aix():
352      cflags.append('-maix64')
353      ldflags.append('-maix64')
354    elif platform.is_haiku():
355      cflags.append('-fPIC')
356      cflags.extend(['-D_BSD_SOURCE'])
357
358    if platform.is_posix() and not platform.is_haiku():
359      ldflags.append('-pthread')
360
361    if platform.is_mingw():
362      cflags.extend(['-DUNICODE',
363                     '-DNOMINMAX',
364                     '-DWIN32_LEAN_AND_MEAN',
365                     '-DWINVER=0x0A00',
366                     '-D_CRT_SECURE_NO_DEPRECATE',
367                     '-D_SCL_SECURE_NO_DEPRECATE',
368                     '-D_UNICODE',
369                     '-D_WIN32_WINNT=0x0A00',
370                     '-D_HAS_EXCEPTIONS=0'
371      ])
372  elif platform.is_msvc():
373    if not options.debug:
374      cflags.extend(['/O2', '/DNDEBUG', '/Zc:inline'])
375      ldflags.extend(['/OPT:REF'])
376
377      if options.use_icf:
378        libflags.extend(['/OPT:ICF'])
379      if options.use_lto:
380        cflags.extend(['/GL'])
381        libflags.extend(['/LTCG'])
382        ldflags.extend(['/LTCG'])
383
384    cflags.extend([
385        '/DNOMINMAX',
386        '/DUNICODE',
387        '/DWIN32_LEAN_AND_MEAN',
388        '/DWINVER=0x0A00',
389        '/D_CRT_SECURE_NO_DEPRECATE',
390        '/D_SCL_SECURE_NO_DEPRECATE',
391        '/D_UNICODE',
392        '/D_WIN32_WINNT=0x0A00',
393        '/FS',
394        '/W4',
395        '/WX',
396        '/Zi',
397        '/wd4099',
398        '/wd4100',
399        '/wd4127',
400        '/wd4244',
401        '/wd4267',
402        '/wd4505',
403        '/wd4838',
404        '/wd4996',
405        '/std:c++17',
406        '/GR-',
407        '/D_HAS_EXCEPTIONS=0',
408    ])
409
410    ldflags.extend(['/DEBUG', '/MACHINE:x64'])
411
412  static_libraries = {
413      'base': {'sources': [
414        'src/base/command_line.cc',
415        'src/base/environment.cc',
416        'src/base/files/file.cc',
417        'src/base/files/file_enumerator.cc',
418        'src/base/files/file_path.cc',
419        'src/base/files/file_path_constants.cc',
420        'src/base/files/file_util.cc',
421        'src/base/files/scoped_file.cc',
422        'src/base/files/scoped_temp_dir.cc',
423        'src/base/json/json_parser.cc',
424        'src/base/json/json_reader.cc',
425        'src/base/json/json_writer.cc',
426        'src/base/json/string_escape.cc',
427        'src/base/logging.cc',
428        'src/base/md5.cc',
429        'src/base/memory/ref_counted.cc',
430        'src/base/memory/weak_ptr.cc',
431        'src/base/sha1.cc',
432        'src/base/strings/string_number_conversions.cc',
433        'src/base/strings/string_split.cc',
434        'src/base/strings/string_util.cc',
435        'src/base/strings/string_util_constants.cc',
436        'src/base/strings/stringprintf.cc',
437        'src/base/strings/utf_string_conversion_utils.cc',
438        'src/base/strings/utf_string_conversions.cc',
439        'src/base/third_party/icu/icu_utf.cc',
440        'src/base/timer/elapsed_timer.cc',
441        'src/base/value_iterators.cc',
442        'src/base/values.cc',
443      ]},
444      'gn_lib': {'sources': [
445        'src/gn/action_target_generator.cc',
446        'src/gn/action_values.cc',
447        'src/gn/analyzer.cc',
448        'src/gn/args.cc',
449        'src/gn/binary_target_generator.cc',
450        'src/gn/build_settings.cc',
451        'src/gn/builder.cc',
452        'src/gn/builder_record.cc',
453        'src/gn/bundle_data.cc',
454        'src/gn/bundle_data_target_generator.cc',
455        'src/gn/bundle_file_rule.cc',
456        'src/gn/c_include_iterator.cc',
457        'src/gn/c_substitution_type.cc',
458        'src/gn/c_tool.cc',
459        'src/gn/command_analyze.cc',
460        'src/gn/command_args.cc',
461        'src/gn/command_check.cc',
462        'src/gn/command_clean.cc',
463        'src/gn/command_desc.cc',
464        'src/gn/command_format.cc',
465        'src/gn/command_gen.cc',
466        'src/gn/command_help.cc',
467        'src/gn/command_ls.cc',
468        'src/gn/command_meta.cc',
469        'src/gn/command_path.cc',
470        'src/gn/command_refs.cc',
471        'src/gn/commands.cc',
472        'src/gn/compile_commands_writer.cc',
473        'src/gn/config.cc',
474        'src/gn/config_values.cc',
475        'src/gn/config_values_extractors.cc',
476        'src/gn/config_values_generator.cc',
477        'src/gn/copy_target_generator.cc',
478        'src/gn/create_bundle_target_generator.cc',
479        'src/gn/deps_iterator.cc',
480        'src/gn/desc_builder.cc',
481        'src/gn/eclipse_writer.cc',
482        'src/gn/err.cc',
483        'src/gn/escape.cc',
484        'src/gn/exec_process.cc',
485        'src/gn/filesystem_utils.cc',
486        'src/gn/frameworks_utils.cc',
487        'src/gn/function_exec_script.cc',
488        'src/gn/function_foreach.cc',
489        'src/gn/function_forward_variables_from.cc',
490        'src/gn/function_get_label_info.cc',
491        'src/gn/function_get_path_info.cc',
492        'src/gn/function_get_target_outputs.cc',
493        'src/gn/function_process_file_template.cc',
494        'src/gn/function_read_file.cc',
495        'src/gn/function_rebase_path.cc',
496        'src/gn/function_set_default_toolchain.cc',
497        'src/gn/function_set_defaults.cc',
498        'src/gn/function_template.cc',
499        'src/gn/function_toolchain.cc',
500        'src/gn/function_write_file.cc',
501        'src/gn/functions.cc',
502        'src/gn/functions_target.cc',
503        'src/gn/general_tool.cc',
504        'src/gn/generated_file_target_generator.cc',
505        'src/gn/group_target_generator.cc',
506        'src/gn/header_checker.cc',
507        'src/gn/import_manager.cc',
508        'src/gn/inherited_libraries.cc',
509        'src/gn/input_conversion.cc',
510        'src/gn/input_file.cc',
511        'src/gn/input_file_manager.cc',
512        'src/gn/item.cc',
513        'src/gn/json_project_writer.cc',
514        'src/gn/label.cc',
515        'src/gn/label_pattern.cc',
516        'src/gn/lib_file.cc',
517        'src/gn/loader.cc',
518        'src/gn/location.cc',
519        'src/gn/metadata.cc',
520        'src/gn/metadata_walk.cc',
521        'src/gn/ninja_action_target_writer.cc',
522        'src/gn/ninja_binary_target_writer.cc',
523        'src/gn/ninja_build_writer.cc',
524        'src/gn/ninja_bundle_data_target_writer.cc',
525        'src/gn/ninja_c_binary_target_writer.cc',
526        'src/gn/ninja_copy_target_writer.cc',
527        'src/gn/ninja_create_bundle_target_writer.cc',
528        'src/gn/ninja_generated_file_target_writer.cc',
529        'src/gn/ninja_group_target_writer.cc',
530        'src/gn/ninja_rust_binary_target_writer.cc',
531        'src/gn/ninja_target_command_util.cc',
532        'src/gn/ninja_target_writer.cc',
533        'src/gn/ninja_toolchain_writer.cc',
534        'src/gn/ninja_utils.cc',
535        'src/gn/ninja_writer.cc',
536        'src/gn/operators.cc',
537        'src/gn/output_conversion.cc',
538        'src/gn/output_file.cc',
539        'src/gn/parse_node_value_adapter.cc',
540        'src/gn/parse_tree.cc',
541        'src/gn/parser.cc',
542        'src/gn/path_output.cc',
543        'src/gn/pattern.cc',
544        'src/gn/pool.cc',
545        'src/gn/qt_creator_writer.cc',
546        'src/gn/runtime_deps.cc',
547        'src/gn/rust_substitution_type.cc',
548        'src/gn/rust_tool.cc',
549        'src/gn/rust_values.cc',
550        'src/gn/rust_values_generator.cc',
551        'src/gn/rust_variables.cc',
552        'src/gn/scheduler.cc',
553        'src/gn/scope.cc',
554        'src/gn/scope_per_file_provider.cc',
555        'src/gn/settings.cc',
556        'src/gn/setup.cc',
557        'src/gn/source_dir.cc',
558        'src/gn/source_file.cc',
559        'src/gn/standard_out.cc',
560        'src/gn/string_atom.cc',
561        'src/gn/string_utils.cc',
562        'src/gn/substitution_list.cc',
563        'src/gn/substitution_pattern.cc',
564        'src/gn/substitution_type.cc',
565        'src/gn/substitution_writer.cc',
566        'src/gn/switches.cc',
567        'src/gn/target.cc',
568        'src/gn/target_generator.cc',
569        'src/gn/template.cc',
570        'src/gn/token.cc',
571        'src/gn/tokenizer.cc',
572        'src/gn/tool.cc',
573        'src/gn/toolchain.cc',
574        'src/gn/trace.cc',
575        'src/gn/value.cc',
576        'src/gn/value_extractors.cc',
577        'src/gn/variables.cc',
578        'src/gn/visibility.cc',
579        'src/gn/visual_studio_utils.cc',
580        'src/gn/visual_studio_writer.cc',
581        'src/gn/xcode_object.cc',
582        'src/gn/xcode_writer.cc',
583        'src/gn/xml_element_writer.cc',
584        'src/util/exe_path.cc',
585        'src/util/msg_loop.cc',
586        'src/util/semaphore.cc',
587        'src/util/sys_info.cc',
588        'src/util/ticks.cc',
589        'src/util/worker_pool.cc',
590      ]},
591  }
592
593  executables = {
594      'gn': {'sources': [ 'src/gn/gn_main.cc' ], 'libs': []},
595
596      'gn_unittests': { 'sources': [
597        'src/gn/action_target_generator_unittest.cc',
598        'src/gn/analyzer_unittest.cc',
599        'src/gn/args_unittest.cc',
600        'src/gn/builder_unittest.cc',
601        'src/gn/c_include_iterator_unittest.cc',
602        'src/gn/command_format_unittest.cc',
603        'src/gn/compile_commands_writer_unittest.cc',
604        'src/gn/config_unittest.cc',
605        'src/gn/config_values_extractors_unittest.cc',
606        'src/gn/escape_unittest.cc',
607        'src/gn/exec_process_unittest.cc',
608        'src/gn/filesystem_utils_unittest.cc',
609        'src/gn/frameworks_utils_unittest.cc',
610        'src/gn/function_foreach_unittest.cc',
611        'src/gn/function_forward_variables_from_unittest.cc',
612        'src/gn/function_get_label_info_unittest.cc',
613        'src/gn/function_get_path_info_unittest.cc',
614        'src/gn/function_get_target_outputs_unittest.cc',
615        'src/gn/function_process_file_template_unittest.cc',
616        'src/gn/function_rebase_path_unittest.cc',
617        'src/gn/function_template_unittest.cc',
618        'src/gn/function_toolchain_unittest.cc',
619        'src/gn/function_write_file_unittest.cc',
620        'src/gn/functions_target_rust_unittest.cc',
621        'src/gn/functions_target_unittest.cc',
622        'src/gn/functions_unittest.cc',
623        'src/gn/header_checker_unittest.cc',
624        'src/gn/inherited_libraries_unittest.cc',
625        'src/gn/input_conversion_unittest.cc',
626        'src/gn/json_project_writer_unittest.cc',
627        'src/gn/label_pattern_unittest.cc',
628        'src/gn/label_unittest.cc',
629        'src/gn/loader_unittest.cc',
630        'src/gn/metadata_unittest.cc',
631        'src/gn/metadata_walk_unittest.cc',
632        'src/gn/ninja_action_target_writer_unittest.cc',
633        'src/gn/ninja_binary_target_writer_unittest.cc',
634        'src/gn/ninja_build_writer_unittest.cc',
635        'src/gn/ninja_bundle_data_target_writer_unittest.cc',
636        'src/gn/ninja_c_binary_target_writer_unittest.cc',
637        'src/gn/ninja_copy_target_writer_unittest.cc',
638        'src/gn/ninja_create_bundle_target_writer_unittest.cc',
639        'src/gn/ninja_generated_file_target_writer_unittest.cc',
640        'src/gn/ninja_group_target_writer_unittest.cc',
641        'src/gn/ninja_rust_binary_target_writer_unittest.cc',
642        'src/gn/ninja_target_command_util_unittest.cc',
643        'src/gn/ninja_target_writer_unittest.cc',
644        'src/gn/ninja_toolchain_writer_unittest.cc',
645        'src/gn/operators_unittest.cc',
646        'src/gn/output_conversion_unittest.cc',
647        'src/gn/parse_tree_unittest.cc',
648        'src/gn/parser_unittest.cc',
649        'src/gn/path_output_unittest.cc',
650        'src/gn/pattern_unittest.cc',
651        'src/gn/runtime_deps_unittest.cc',
652        'src/gn/scope_per_file_provider_unittest.cc',
653        'src/gn/scope_unittest.cc',
654        'src/gn/setup_unittest.cc',
655        'src/gn/source_dir_unittest.cc',
656        'src/gn/source_file_unittest.cc',
657        'src/gn/string_atom_unittest.cc',
658        'src/gn/string_utils_unittest.cc',
659        'src/gn/substitution_pattern_unittest.cc',
660        'src/gn/substitution_writer_unittest.cc',
661        'src/gn/target_unittest.cc',
662        'src/gn/template_unittest.cc',
663        'src/gn/test_with_scheduler.cc',
664        'src/gn/test_with_scope.cc',
665        'src/gn/tokenizer_unittest.cc',
666        'src/gn/unique_vector_unittest.cc',
667        'src/gn/value_unittest.cc',
668        'src/gn/visibility_unittest.cc',
669        'src/gn/visual_studio_utils_unittest.cc',
670        'src/gn/visual_studio_writer_unittest.cc',
671        'src/gn/xcode_object_unittest.cc',
672        'src/gn/xml_element_writer_unittest.cc',
673        'src/util/test/gn_test.cc',
674      ], 'libs': []},
675  }
676
677  if platform.is_posix():
678    static_libraries['base']['sources'].extend([
679        'src/base/files/file_enumerator_posix.cc',
680        'src/base/files/file_posix.cc',
681        'src/base/files/file_util_posix.cc',
682        'src/base/posix/file_descriptor_shuffle.cc',
683        'src/base/posix/safe_strerror.cc',
684    ])
685
686  if platform.is_windows():
687    static_libraries['base']['sources'].extend([
688        'src/base/files/file_enumerator_win.cc',
689        'src/base/files/file_util_win.cc',
690        'src/base/files/file_win.cc',
691        'src/base/win/registry.cc',
692        'src/base/win/scoped_handle.cc',
693        'src/base/win/scoped_process_information.cc',
694    ])
695
696    if platform.is_msvc():
697      libs.extend([
698          'advapi32.lib',
699          'dbghelp.lib',
700          'kernel32.lib',
701          'ole32.lib',
702          'shell32.lib',
703          'user32.lib',
704          'userenv.lib',
705          'version.lib',
706          'winmm.lib',
707          'ws2_32.lib',
708          'Shlwapi.lib',
709      ])
710    else:
711      libs.extend([
712          '-ladvapi32',
713          '-ldbghelp',
714          '-lkernel32',
715          '-lole32',
716          '-lshell32',
717          '-luser32',
718          '-luserenv',
719          '-lversion',
720          '-lwinmm',
721          '-lws2_32',
722          '-lshlwapi',
723      ])
724
725
726  # we just build static libraries that GN needs
727  executables['gn']['libs'].extend(static_libraries.keys())
728  executables['gn_unittests']['libs'].extend(static_libraries.keys())
729
730  WriteGenericNinja(path, static_libraries, executables, cxx, ar, ld,
731                    platform, host, options, cflags, ldflags,
732                    libflags, include_dirs, libs)
733
734
735if __name__ == '__main__':
736  sys.exit(main(sys.argv[1:]))
737