| # 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 |