11cb0ef41Sopenharmony_ci# Copyright 2015 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci# Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci# found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_cifrom __future__ import print_function
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ciimport sys
81cb0ef41Sopenharmony_ciimport os
91cb0ef41Sopenharmony_ciimport itertools
101cb0ef41Sopenharmony_ciimport re
111cb0ef41Sopenharmony_ci
121cb0ef41Sopenharmony_citry:
131cb0ef41Sopenharmony_ci  from exceptions import RuntimeError
141cb0ef41Sopenharmony_ciexcept ImportError:
151cb0ef41Sopenharmony_ci  pass
161cb0ef41Sopenharmony_ci
171cb0ef41Sopenharmony_ci
181cb0ef41Sopenharmony_cidef GetNinjaOutputDirectory(v8_root, configuration=None):
191cb0ef41Sopenharmony_ci  """Returns <v8_root>/<output_dir>/(Release|Debug|<other>).
201cb0ef41Sopenharmony_ci
211cb0ef41Sopenharmony_ci  The configuration chosen is the one most recently generated/built, but can be
221cb0ef41Sopenharmony_ci  overriden via the <configuration> parameter. Detects a custom output_dir
231cb0ef41Sopenharmony_ci  specified by GYP_GENERATOR_FLAGS."""
241cb0ef41Sopenharmony_ci
251cb0ef41Sopenharmony_ci  output_dirs = []
261cb0ef41Sopenharmony_ci
271cb0ef41Sopenharmony_ci  generator_flags = os.getenv('GYP_GENERATOR_FLAGS', '').split(' ')
281cb0ef41Sopenharmony_ci  for flag in generator_flags:
291cb0ef41Sopenharmony_ci    name_value = flag.split('=', 1)
301cb0ef41Sopenharmony_ci    if (len(name_value) == 2 and name_value[0] == 'output_dir' and
311cb0ef41Sopenharmony_ci        os.path.isdir(os.path.join(v8_root, name_value[1]))):
321cb0ef41Sopenharmony_ci      output_dirs = [name_value[1]]
331cb0ef41Sopenharmony_ci
341cb0ef41Sopenharmony_ci  if configuration:
351cb0ef41Sopenharmony_ci    output_dir = 'out' if len(output_dirs) == 0 else output_dirs[-1]
361cb0ef41Sopenharmony_ci    return os.path.join(os.path.join(v8_root, output_dir), configuration)
371cb0ef41Sopenharmony_ci
381cb0ef41Sopenharmony_ci  if not output_dirs:
391cb0ef41Sopenharmony_ci    for f in os.listdir(v8_root):
401cb0ef41Sopenharmony_ci      if re.match(r'out(\b|_)', f):
411cb0ef41Sopenharmony_ci        if os.path.isdir(os.path.join(v8_root, f)):
421cb0ef41Sopenharmony_ci          output_dirs.append(f)
431cb0ef41Sopenharmony_ci
441cb0ef41Sopenharmony_ci  def generate_paths():
451cb0ef41Sopenharmony_ci    for out_dir in output_dirs:
461cb0ef41Sopenharmony_ci      out_path = os.path.join(v8_root, out_dir)
471cb0ef41Sopenharmony_ci      for config in os.listdir(out_path):
481cb0ef41Sopenharmony_ci        path = os.path.join(out_path, config)
491cb0ef41Sopenharmony_ci        if os.path.exists(os.path.join(path, 'build.ninja')):
501cb0ef41Sopenharmony_ci          yield path
511cb0ef41Sopenharmony_ci
521cb0ef41Sopenharmony_ci  def approx_directory_mtime(path):
531cb0ef41Sopenharmony_ci    # This is a heuristic; don't recurse into subdirectories.
541cb0ef41Sopenharmony_ci    paths = [path] + [os.path.join(path, f) for f in os.listdir(path)]
551cb0ef41Sopenharmony_ci    return max(filter(None, [safe_mtime(p) for p in paths]))
561cb0ef41Sopenharmony_ci
571cb0ef41Sopenharmony_ci  def safe_mtime(path):
581cb0ef41Sopenharmony_ci    try:
591cb0ef41Sopenharmony_ci      return os.path.getmtime(path)
601cb0ef41Sopenharmony_ci    except OSError:
611cb0ef41Sopenharmony_ci      return None
621cb0ef41Sopenharmony_ci
631cb0ef41Sopenharmony_ci  try:
641cb0ef41Sopenharmony_ci    return max(generate_paths(), key=approx_directory_mtime)
651cb0ef41Sopenharmony_ci  except ValueError:
661cb0ef41Sopenharmony_ci    raise RuntimeError('Unable to find a valid ninja output directory.')
671cb0ef41Sopenharmony_ci
681cb0ef41Sopenharmony_ci
691cb0ef41Sopenharmony_ciif __name__ == '__main__':
701cb0ef41Sopenharmony_ci  if len(sys.argv) != 2:
711cb0ef41Sopenharmony_ci    raise RuntimeError('Expected a single path argument.')
721cb0ef41Sopenharmony_ci  print(GetNinjaOutputDirectory(sys.argv[1]))
73