blob: 68a95faa8b4fc90bcb77db6226e0ce230d6b4351 [file] [log] [blame]
Nico Weber09e0b382019-03-11 16:54:07 +00001# Copyright 2019 The Chromium 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
5# This file is imported by various thin wrappers (around gn, clang-format, ...),
6# so it's meant to import very quickly. To keep it that way don't add more
7# code, and even more importantly don't add more toplevel import statements.
8import os
9
10
11def FindGclientRoot(from_dir, filename='.gclient'):
12 """Tries to find the gclient root."""
13 real_from_dir = os.path.realpath(from_dir)
14 path = real_from_dir
15 while not os.path.exists(os.path.join(path, filename)):
16 split_path = os.path.split(path)
17 if not split_path[1]:
18 return None
19 path = split_path[0]
20
21 # If we did not find the file in the current directory, make sure we are in a
22 # sub directory that is controlled by this configuration.
23 if path != real_from_dir:
24 entries_filename = os.path.join(path, filename + '_entries')
25 if not os.path.exists(entries_filename):
26 import sys
27 # If .gclient_entries does not exist, a previous call to gclient sync
28 # might have failed. In that case, we cannot verify that the .gclient
29 # is the one we want to use. In order to not to cause too much trouble,
30 # just issue a warning and return the path anyway.
31 print >> sys.stderr, ("%s missing, %s file in parent directory %s might "
32 "not be the file you want to use." %
33 (entries_filename, filename, path))
34 return path
35 scope = {}
36 try:
37 import io
38 with io.open(entries_filename, encoding='utf-8') as f:
39 exec(f.read(), scope)
40 except SyntaxError, e:
41 SyntaxErrorToError(filename, e)
42 all_directories = scope['entries'].keys()
43 path_to_check = real_from_dir[len(path)+1:]
44 while path_to_check:
45 if path_to_check in all_directories:
46 return path
47 path_to_check = os.path.dirname(path_to_check)
48 return None
49
50 import logging
51 logging.info('Found gclient root at ' + path)
52 return path
53
54
55def GetPrimarySolutionPath():
56 """Returns the full path to the primary solution. (gclient_root + src)"""
57
58 gclient_root = FindGclientRoot(os.getcwd())
59 if not gclient_root:
60 # Some projects might not use .gclient. Try to see whether we're in a git
61 # checkout.
62 top_dir = [os.getcwd()]
63 def filter_fn(line):
64 repo_root_path = os.path.normpath(line.rstrip('\n'))
65 if os.path.exists(repo_root_path):
66 top_dir[0] = repo_root_path
67 try:
68 CheckCallAndFilter(["git", "rev-parse", "--show-toplevel"],
69 print_stdout=False, filter_fn=filter_fn)
70 except Exception:
71 pass
72 top_dir = top_dir[0]
73 if os.path.exists(os.path.join(top_dir, 'buildtools')):
74 return top_dir
75 return None
76
77 # Some projects' top directory is not named 'src'.
78 source_dir_name = GetGClientPrimarySolutionName(gclient_root) or 'src'
79 return os.path.join(gclient_root, source_dir_name)
80
81
82def GetBuildtoolsPath():
83 """Returns the full path to the buildtools directory.
84 This is based on the root of the checkout containing the current directory."""
85
86 # Overriding the build tools path by environment is highly unsupported and may
87 # break without warning. Do not rely on this for anything important.
88 override = os.environ.get('CHROMIUM_BUILDTOOLS_PATH')
89 if override is not None:
90 return override
91
92 primary_solution = GetPrimarySolutionPath()
93 if not primary_solution:
94 return None
95 buildtools_path = os.path.join(primary_solution, 'buildtools')
96 if not os.path.exists(buildtools_path):
97 # Buildtools may be in the gclient root.
98 gclient_root = FindGclientRoot(os.getcwd())
99 buildtools_path = os.path.join(gclient_root, 'buildtools')
100 return buildtools_path
101
102
103def GetBuildtoolsPlatformBinaryPath():
104 """Returns the full path to the binary directory for the current platform."""
105 buildtools_path = GetBuildtoolsPath()
106 if not buildtools_path:
107 return None
108
109 if sys.platform.startswith(('cygwin', 'win')):
110 subdir = 'win'
111 elif sys.platform == 'darwin':
112 subdir = 'mac'
113 elif sys.platform.startswith('linux'):
114 subdir = 'linux64'
115 else:
116 raise Error('Unknown platform: ' + sys.platform)
117 return os.path.join(buildtools_path, subdir)
118
119
120def GetExeSuffix():
121 """Returns '' or '.exe' depending on how executables work on this platform."""
122 if sys.platform.startswith(('cygwin', 'win')):
123 return '.exe'
124 return ''
125
126
127def GetGClientPrimarySolutionName(gclient_root_dir_path):
128 """Returns the name of the primary solution in the .gclient file specified."""
129 gclient_config_file = os.path.join(gclient_root_dir_path, '.gclient')
130 env = {}
131 execfile(gclient_config_file, env)
132 solutions = env.get('solutions', [])
133 if solutions:
134 return solutions[0].get('name')
135 return None