1# Copyright 2015 the V8 project authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5from __future__ import print_function
6
7import sys
8import os
9import itertools
10import re
11
12try:
13  from exceptions import RuntimeError
14except ImportError:
15  pass
16
17
18def GetNinjaOutputDirectory(v8_root, configuration=None):
19  """Returns <v8_root>/<output_dir>/(Release|Debug|<other>).
20
21  The configuration chosen is the one most recently generated/built, but can be
22  overriden via the <configuration> parameter. Detects a custom output_dir
23  specified by GYP_GENERATOR_FLAGS."""
24
25  output_dirs = []
26
27  generator_flags = os.getenv('GYP_GENERATOR_FLAGS', '').split(' ')
28  for flag in generator_flags:
29    name_value = flag.split('=', 1)
30    if (len(name_value) == 2 and name_value[0] == 'output_dir' and
31        os.path.isdir(os.path.join(v8_root, name_value[1]))):
32      output_dirs = [name_value[1]]
33
34  if configuration:
35    output_dir = 'out' if len(output_dirs) == 0 else output_dirs[-1]
36    return os.path.join(os.path.join(v8_root, output_dir), configuration)
37
38  if not output_dirs:
39    for f in os.listdir(v8_root):
40      if re.match(r'out(\b|_)', f):
41        if os.path.isdir(os.path.join(v8_root, f)):
42          output_dirs.append(f)
43
44  def generate_paths():
45    for out_dir in output_dirs:
46      out_path = os.path.join(v8_root, out_dir)
47      for config in os.listdir(out_path):
48        path = os.path.join(out_path, config)
49        if os.path.exists(os.path.join(path, 'build.ninja')):
50          yield path
51
52  def approx_directory_mtime(path):
53    # This is a heuristic; don't recurse into subdirectories.
54    paths = [path] + [os.path.join(path, f) for f in os.listdir(path)]
55    return max(filter(None, [safe_mtime(p) for p in paths]))
56
57  def safe_mtime(path):
58    try:
59      return os.path.getmtime(path)
60    except OSError:
61      return None
62
63  try:
64    return max(generate_paths(), key=approx_directory_mtime)
65  except ValueError:
66    raise RuntimeError('Unable to find a valid ninja output directory.')
67
68
69if __name__ == '__main__':
70  if len(sys.argv) != 2:
71    raise RuntimeError('Expected a single path argument.')
72  print(GetNinjaOutputDirectory(sys.argv[1]))
73