blob: 9ac3db23c2e93f42164e997107f638d6a96b987e [file] [log] [blame]
Bruce Dawsonebebd952017-05-31 14:24:38 -07001# Copyright (c) 2017 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"""
6This script (intended to be invoked by autoninja or autoninja.bat) detects
7whether a build is using goma. If so it runs with a large -j value, and
8otherwise it chooses a small one. This auto-adjustment makes using goma simpler
9and safer, and avoids errors that can cause slow goma builds or swap-storms
10on non-goma builds.
11"""
12
Raul Tambre80ee78e2019-05-06 22:41:05 +000013from __future__ import print_function
14
Bruce Dawsonebebd952017-05-31 14:24:38 -070015import multiprocessing
16import os
17import re
18import sys
19
Yoshisato Yanagisawa4b497072018-11-07 02:52:33 +000020SCRIPT_DIR = os.path.dirname(os.path.realpath(__file__))
21
Yoshisato Yanagisawa0db62fc2018-11-01 01:09:53 +000022# The -t tools are incompatible with -j
Bruce Dawson1f767e12017-07-07 15:10:37 -070023t_specified = False
Bruce Dawsonebebd952017-05-31 14:24:38 -070024j_specified = False
25output_dir = '.'
Bruce Dawsonf3b4f062017-09-07 17:22:26 -070026input_args = sys.argv
27# On Windows the autoninja.bat script passes along the arguments enclosed in
28# double quotes. This prevents multiple levels of parsing of the special '^'
29# characters needed when compiling a single file but means that this script gets
30# called with a single argument containing all of the actual arguments,
31# separated by spaces. When this case is detected we need to do argument
32# splitting ourselves. This means that arguments containing actual spaces are
33# not supported by autoninja, but that is not a real limitation.
34if (sys.platform.startswith('win') and len(sys.argv) == 2 and
35 input_args[1].count(' ') > 0):
36 input_args = sys.argv[:1] + sys.argv[1].split()
Yoshisato Yanagisawaf66e5512018-11-15 00:40:39 +000037
38# Ninja uses getopt_long, which allow to intermix non-option arguments.
39# To leave non supported parameters untouched, we do not use getopt.
Bruce Dawsonf3b4f062017-09-07 17:22:26 -070040for index, arg in enumerate(input_args[1:]):
Yoshisato Yanagisawaf66e5512018-11-15 00:40:39 +000041 if arg.startswith('-j'):
Bruce Dawsonebebd952017-05-31 14:24:38 -070042 j_specified = True
Yoshisato Yanagisawaf66e5512018-11-15 00:40:39 +000043 if arg.startswith('-t'):
Bruce Dawson1f767e12017-07-07 15:10:37 -070044 t_specified = True
Bruce Dawsonebebd952017-05-31 14:24:38 -070045 if arg == '-C':
Bruce Dawsonf3b4f062017-09-07 17:22:26 -070046 # + 1 to get the next argument and +1 because we trimmed off input_args[0]
47 output_dir = input_args[index + 2]
Bruce Dawson6af3aa82018-10-03 16:39:42 +000048 elif arg.startswith('-C'):
49 # Support -Cout/Default
50 output_dir = arg[2:]
Bruce Dawsonebebd952017-05-31 14:24:38 -070051
52use_goma = False
53try:
Bruce Dawson85c75022018-04-17 17:49:06 -070054 # If GOMA_DISABLED is set (to anything) then gomacc will use the local
55 # compiler instead of doing a goma compile. This is convenient if you want
56 # to briefly disable goma. It avoids having to rebuild the world when
57 # transitioning between goma/non-goma builds. However, it is not as fast as
58 # doing a "normal" non-goma build because an extra process is created for each
59 # compile step. Checking this environment variable ensures that autoninja uses
60 # an appropriate -j value in this situation.
61 if 'GOMA_DISABLED' not in os.environ:
62 with open(os.path.join(output_dir, 'args.gn')) as file_handle:
63 for line in file_handle:
64 # This regex pattern copied from create_installer_archive.py
Bruce Dawson56add622019-04-30 21:07:56 +000065 m = re.match(r'^\s*use_goma\s*=\s*true(\s*$|\s*#.*$)', line)
Bruce Dawson85c75022018-04-17 17:49:06 -070066 if m:
67 use_goma = True
Bruce Dawsonebebd952017-05-31 14:24:38 -070068except IOError:
69 pass
70
Yoshisato Yanagisawa4b497072018-11-07 02:52:33 +000071# Specify ninja.exe on Windows so that ninja.bat can call autoninja and not
72# be called back.
73ninja_exe = 'ninja.exe' if sys.platform.startswith('win') else 'ninja'
Allen Bauer75fa8552018-11-07 22:43:39 +000074ninja_exe_path = os.path.join(SCRIPT_DIR, ninja_exe)
75
Yoshisato Yanagisawa4b497072018-11-07 02:52:33 +000076# Use absolute path for ninja path,
77# or fail to execute ninja if depot_tools is not in PATH.
Allen Bauer75fa8552018-11-07 22:43:39 +000078args = [ninja_exe_path] + input_args[1:]
Bruce Dawsonebebd952017-05-31 14:24:38 -070079
80num_cores = multiprocessing.cpu_count()
Bruce Dawson1f767e12017-07-07 15:10:37 -070081if not j_specified and not t_specified:
Bruce Dawsonebebd952017-05-31 14:24:38 -070082 if use_goma:
83 args.append('-j')
Takuto Ikuta1206a352019-02-07 22:18:08 +000084 core_multiplier = int(os.environ.get("NINJA_CORE_MULTIPLIER", "40"))
85 j_value = num_cores * core_multiplier
86
87 if sys.platform.startswith('win'):
88 # On windows, j value higher than 1000 does not improve build performance.
89 j_value = min(j_value, 1000)
Takuto Ikutada4dbf82019-03-04 03:21:58 +000090 elif sys.platform == 'darwin':
91 # On Mac, j value higher than 500 causes 'Too many open files' error
92 # (crbug.com/936864).
93 j_value = min(j_value, 500)
Takuto Ikuta1206a352019-02-07 22:18:08 +000094
95 args.append('%d' % j_value)
Bruce Dawsonebebd952017-05-31 14:24:38 -070096 else:
97 core_addition = os.environ.get("NINJA_CORE_ADDITION")
98 if core_addition:
99 core_addition = int(core_addition)
100 args.append('-j')
101 args.append('%d' % (num_cores + core_addition))
102
Yoshisato Yanagisawa43a35d22018-11-15 03:00:51 +0000103# On Windows, fully quote the path so that the command processor doesn't think
104# the whole output is the command.
105# On Linux and Mac, if people put depot_tools in directories with ' ',
106# shell would misunderstand ' ' as a path separation.
107# TODO(yyanagisawa): provide proper quating for Windows.
108# see https://cs.chromium.org/chromium/src/tools/mb/mb.py
109for i in range(len(args)):
110 if (i == 0 and sys.platform.startswith('win')) or ' ' in args[i]:
111 args[i] = '"%s"' % args[i].replace('"', '\\"')
112
Raul Tambre80ee78e2019-05-06 22:41:05 +0000113print(' '.join(args))