blob: 998a0b39c4cd5a182a3c10545f9ed17778a7c4b3 [file] [log] [blame]
# Copyright 2019 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
# This file is imported by various thin wrappers (around gn, clang-format, ...),
# so it's meant to import very quickly. To keep it that way don't add more
# code, and even more importantly don't add more toplevel import statements,
# particularly for modules that are not builtin (see sys.builtin_modules_names,
# os isn't built in, but it's essential to this file).
from __future__ import print_function
import gclient_utils
import logging
import os
import subprocess2
import sys
def FindGclientRoot(from_dir, filename='.gclient'):
"""Tries to find the gclient root."""
real_from_dir = os.path.realpath(from_dir)
path = real_from_dir
while not os.path.exists(os.path.join(path, filename)):
split_path = os.path.split(path)
if not split_path[1]:
return None
path = split_path[0]
logging.info('Found gclient root at ' + path)
if path == real_from_dir:
return path
# If we did not find the file in the current directory, make sure we are in a
# sub directory that is controlled by this configuration.
entries_filename = os.path.join(path, filename + '_entries')
if not os.path.exists(entries_filename):
# If .gclient_entries does not exist, a previous call to gclient sync
# might have failed. In that case, we cannot verify that the .gclient
# is the one we want to use. In order to not to cause too much trouble,
# just issue a warning and return the path anyway.
print(
"%s missing, %s file in parent directory %s might not be the file "
"you want to use." % (entries_filename, filename, path),
file=sys.stderr)
return path
entries_content = gclient_utils.FileRead(entries_filename)
scope = {}
try:
exec(entries_content, scope)
except (SyntaxError, Exception) as e:
gclient_utils.SyntaxErrorToError(filename, e)
all_directories = scope['entries'].keys()
path_to_check = os.path.relpath(real_from_dir, path)
while path_to_check:
if path_to_check in all_directories:
return path
path_to_check = os.path.dirname(path_to_check)
return None
def GetPrimarySolutionPath():
"""Returns the full path to the primary solution. (gclient_root + src)"""
gclient_root = FindGclientRoot(os.getcwd())
if gclient_root:
# Some projects' top directory is not named 'src'.
source_dir_name = GetGClientPrimarySolutionName(gclient_root) or 'src'
return os.path.join(gclient_root, source_dir_name)
# Some projects might not use .gclient. Try to see whether we're in a git
# checkout that contains a 'buildtools' subdir.
top_dir = os.getcwd()
try:
top_dir = subprocess2.check_output(
['git', 'rev-parse', '--show-toplevel'])
if sys.version_info.major == 3:
top_dir = top_dir.decode('utf-8', 'replace')
top_dir = os.path.normpath(top_dir.strip())
except subprocess2.CalledProcessError:
pass
if os.path.exists(os.path.join(top_dir, 'buildtools')):
return top_dir
return None
def GetBuildtoolsPath():
"""Returns the full path to the buildtools directory.
This is based on the root of the checkout containing the current directory."""
# Overriding the build tools path by environment is highly unsupported and may
# break without warning. Do not rely on this for anything important.
override = os.environ.get('CHROMIUM_BUILDTOOLS_PATH')
if override is not None:
return override
primary_solution = GetPrimarySolutionPath()
if not primary_solution:
return None
buildtools_path = os.path.join(primary_solution, 'buildtools')
if os.path.exists(buildtools_path):
return buildtools_path
# buildtools may be in the gclient root.
gclient_root = FindGclientRoot(os.getcwd())
buildtools_path = os.path.join(gclient_root, 'buildtools')
if os.path.exists(buildtools_path):
return buildtools_path
return None
def GetBuildtoolsPlatformBinaryPath():
"""Returns the full path to the binary directory for the current platform."""
buildtools_path = GetBuildtoolsPath()
if not buildtools_path:
return None
if sys.platform.startswith(('cygwin', 'win')):
subdir = 'win'
elif sys.platform == 'darwin':
subdir = 'mac'
elif sys.platform.startswith('linux'):
subdir = 'linux64'
else:
raise gclient_utils.Error('Unknown platform: ' + sys.platform)
return os.path.join(buildtools_path, subdir)
def GetExeSuffix():
"""Returns '' or '.exe' depending on how executables work on this platform."""
if sys.platform.startswith(('cygwin', 'win')):
return '.exe'
return ''
def GetGClientPrimarySolutionName(gclient_root_dir_path):
"""Returns the name of the primary solution in the .gclient file specified."""
gclient_config_file = os.path.join(gclient_root_dir_path, '.gclient')
gclient_config_contents = gclient_utils.FileRead(gclient_config_file)
env = {}
exec(gclient_config_contents, env)
solutions = env.get('solutions', [])
if solutions:
return solutions[0].get('name')
return None