| #!/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', '16.1.4479499') |
| env['TERM'] = os.environ.get('TERM', '') |
| env['SHELL'] = os.environ.get('SHELL', '') |
| env['HOME'] = os.environ.get('HOME', '') |
| env['DISPLAY'] = os.environ.get('DISPLAY', '') |
| 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() |