blob: 87a5c185ba7404e30ca196d75a1bce5840c3d18f [file] [log] [blame]
#!/usr/bin/python
"""Runs the bazel executable for the platform, passing args along."""
import os
import os.path
import re
import subprocess
import sys
import multiprocessing
def main():
workspace = find_workspace(os.path.dirname(os.path.realpath(__file__)))
if not workspace:
sys.exit('Must run %s within a workspace.' % os.path.basename(sys.argv[0]))
if sys.platform.startswith('linux'):
platform = 'linux-x86_64'
jdk_subdir = 'linux'
config = 'linux'
elif sys.platform == 'darwin':
platform = 'darwin-x86_64'
jdk_subdir = os.path.join('mac', 'Contents', 'Home')
config = 'darwin'
elif sys.platform == 'win32':
platform = 'windows-x86_64'
jdk_subdir = 'win64'
config = 'windows'
else:
sys.exit('Platform %s is not yet supported.' % sys.platform)
bazel = os.path.join(workspace, 'prebuilts', 'tools', platform, 'bazel',
'bazel-real')
args = sys.argv[1:]
command = bazel_command(args)
env = {}
env['JAVA_HOME'] = os.path.join(workspace, 'prebuilts', 'studio', 'jdk', jdk_subdir)
env['ANDROID_NDK_HOME'] = os.path.join(workspace, 'prebuilts', 'studio', 'sdk', config, 'ndk-bundle')
env['TERM'] = os.environ.get('TERM', '')
env['SHELL'] = os.environ.get('SHELL', '')
env['HOME'] = os.environ.get('HOME', '')
if 'QA_ANDROID_SDK_ROOT' in os.environ:
env['QA_ANDROID_SDK_ROOT'] = os.environ['QA_ANDROID_SDK_ROOT']
if sys.platform == 'darwin':
args.insert(0, '--watchfs')
if not os.path.exists('/Library/Developer/CommandLineTools'):
print('/Library/Developer/CommandLineTools does not exist. Please install it with '
'xcode-select --install')
sys.exit(1)
# This is needed for bazel to set itself up, even though we aren't using gcc.
env['CC'] = os.environ.get('GCC', '/usr/bin/gcc')
elif sys.platform == 'win32':
# We don't need the tools to be installed locally if you're building remotely.
# This isn't really the correct check, since --config=remote is just an alias for a bunch of other
# settings. But in practice that's how you get into remote mode, so it should be good enough for now
# at least.
if (command in ['build', 'test'] and
(not '--config=remote' in args and not '--config=dynamic' in args)):
if (not os.path.exists('C:\\Program Files (x86)\\Microsoft Visual Studio\\2019\\BuildTools\\VC\\Tools\\MSVC\\14.26.28801') or
not os.path.exists('C:\\Program Files (x86)\\Windows Kits\\10\\lib\\10.0.18362.0')):
print('You must have MSVC Buildtools version 14.26.28801 and Windows SDK 10.0.18362.0 installed.\n'
'An installer for these is available at go/studio-msvc-tools.')
sys.exit(1)
define_env(env, 'BAZEL_SH', 'C:\\tools\\msys64\\usr\\bin\\bash.exe',
'***NOTE***: Bazel for Windows currently hardcodes "C:\\tools\\msys64", but we\n' +
'could not find an installation of msys at this path on your machine.\n' +
'Move your installation there if you already have it or\n' +
'install it there from http://www.msys2.org.\n' +
'Make sure to change the path to C:\\tools\\msys64\n' +
'\n' +
'See also: https://github.com/bazelbuild/bazel/issues/2447')
# Bazel for windows requires a couple of extra env vars be set
# SYSTEMROOT must be defined to run a win .exe; otherwise, subprocess.call
# will hang.
env['SYSTEMROOT'] = 'C:\\Windows'
env['TMP'] = os.environ.get('TMP','')
env['PATH'] = os.environ.get('PATH','')
env['USERPROFILE'] = os.environ.get('USERPROFILE', '')
else: # Linux
env['CC'] = os.environ.get('GCC', '/usr/bin/gcc')
if command == 'info' and bazel_command_index(args) == len(args) - 1:
print("bazel-cpu-count: " + str(count_bazel_CPUs()))
bazelrc_arg = '--bazelrc=%s' % os.path.join(workspace, 'tools',
'base', 'bazel',
config + '.bazel.rc')
sys.exit(subprocess.call([bazel, bazelrc_arg] + args, env=env))
def define_env(env, var, value, msg=None):
prev = os.environ.get(var)
if prev:
if not os.path.exists(value):
print('{} is set to {}, but it does not exist'.format(var, value))
sys.exit(1)
env[var] = prev
elif os.path.exists(value):
env[var] = value
else:
print('Cannot find {} while trying to set "{}"'.format(value, var))
if msg:
print(msg)
else:
print('Make sure {} exists, or set "{}" manually to the correct value.'.format(value, var))
sys.exit(1)
def find_workspace(path):
if os.path.isfile(os.path.join(path, 'WORKSPACE')):
return path
else:
parent = os.path.dirname(path)
return None if parent == path else find_workspace(parent)
"""
Returns the command index, which is the first non-option argument.
https://bazel.build/versions/master/docs/command-line-reference.html
"""
def bazel_command_index(args):
for i in range(len(args)):
if not args[i].startswith('-'):
return i
return None
"""
Returns the command itself, or None if not defined.
"""
def bazel_command(args):
index = bazel_command_index(args)
if index is None:
return None
return args[index]
"""
Calculates the CPU count like bazel. Only used for
information purposes. See:
https://github.com/bazelbuild/bazel/blob/master/src/main/java/com/google/devtools/build/lib/actions/LocalHostCapacity.java#L39
"""
def count_bazel_CPUs():
if sys.platform == 'darwin':
logical = int(os.popen2("sysctl -n hw.logicalcpu")[1].read())
physical = int(os.popen2("sysctl -n hw.physicalcpu")[1].read())
elif sys.platform == 'win32':
logical = physical = multiprocessing.cpu_count()
else: # Linux
logical = int(os.popen2("cat /proc/cpuinfo | grep \"^processor\" | wc -l")[1].read())
cpu_count = int(os.popen2("cat /proc/cpuinfo | grep \"^physical id\" | sort -u | wc -l")[1].read())
core_count = int(os.popen2("cat /proc/cpuinfo | grep \"^core id\" | sort -u | wc -l")[1].read())
physical = (cpu_count if cpu_count else logical) * (core_count if core_count else 1)
hyperthreading = (logical != physical);
return logical * (0.6 if hyperthreading else 1.0)
if __name__ == '__main__':
main()