blob: b99aee1cfda46944b84258b04e7bec73d1404b23 [file] [log] [blame] [edit]
# Copyright 2020 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.
import multiprocessing
import sys
from recipe_engine import recipe_api
class BuildUtilApi(recipe_api.RecipeApi):
"""Gn and Ninja wrapper functions."""
def __init__(self, *args, **kwargs):
super(BuildUtilApi, self).__init__(*args, **kwargs)
self.use_goma = True
self.use_rbe = False
def run_gn(self, gn_args, checkout_path):
"""Run a gn command with the given arguments.
Args:
gn_args(list): A list of strings to be passed to the gn command.
checkout_path(Path): A path object with the checkout location.
"""
gn_cmd = ['python3', checkout_path.join('flutter/tools/gn')]
self.use_goma = '--no-goma' not in gn_args
self.use_rbe = '--rbe' in gn_args
if self.m.properties.get('no_lto', False) and '--no-lto' not in gn_args:
gn_args += ('--no-lto',)
gn_cmd.extend(gn_args)
if self.use_goma:
env = {'GOMA_DIR': self.m.goma.goma_dir}
# Some gn configurations expect depot_tools in path. e.g. vs_studio
# tool_chain update script.
with self.m.goma(), self.m.context(env=env), self.m.depot_tools.on_path():
self.m.step('gn %s' % ' '.join(gn_args), gn_cmd)
else:
with self.m.depot_tools.on_path():
self.m.step('gn %s' % ' '.join(gn_args), gn_cmd)
def _calculate_j_value(self):
"""Calculates concurrent jobs value for the current machine."""
cores = multiprocessing.cpu_count()
# For non goma builds, set -j to the number of cores.
if not self.use_goma:
return 5 if self._test_data.enabled else cores
# Assume simultaneous multithreading and therefore half as many cores as
# logical processors.
cores //= 2
default_core_multiplier = 80
j_value = cores * default_core_multiplier
if self.m.platform.is_win:
# On windows, j value higher than 1000 does not improve build
# performance.
j_value = min(j_value, 1000)
elif self.m.platform.is_mac:
# On macOS, j value higher than 800 causes 'Too many open files' error
# (crbug.com/936864).
j_value = min(j_value, 800)
return 200 if self._test_data.enabled else j_value
def _build_rbe(self, config, checkout_path, targets, tool, rbe_working_path):
"""Builds using ninja and rbe.
Args:
config(str): A string with the configuration to build.
checkout_path(Path): A path object with the checkout location.
targets(list): A list of strings with the ninja targets to build.
tool(path): Path to the ninja tool.
rbe_working_path(path): Path to the rbe working directory.
"""
assert rbe_working_path
build_dir = checkout_path.join('out/%s' % config)
rbe_jobs = self.m.properties.get('rbe_jobs') or self._calculate_j_value()
ninja_args = [tool, '-j', rbe_jobs, '-C', build_dir]
ninja_args.extend(targets)
with self.m.rbe(working_path=rbe_working_path
), self.m.depot_tools.on_path():
name = 'build %s' % ' '.join([config] + list(targets))
self.m.step(name, ninja_args)
def _build_goma(self, config, checkout_path, targets, tool):
"""Builds using ninja and goma.
Args:
config(str): A string with the configuration to build.
checkout_path(Path): A path object with the checkout location.
targets(list): A list of strings with the ninja targets to build.
"""
build_dir = checkout_path.join('out/%s' % config)
goma_jobs = self.m.properties.get('goma_jobs') or self._calculate_j_value()
ninja_args = [tool, '-j', goma_jobs, '-C', build_dir]
ninja_args.extend(targets)
with self.m.goma(), self.m.depot_tools.on_path():
name = 'build %s' % ' '.join([config] + list(targets))
self.m.step(name, ninja_args)
def _build_no_goma(self, config, checkout_path, targets, tool):
"""Builds using ninja without goma.
Args:
config(str): A string with the configuration to build.
checkout_path(Path): A path object with the checkout location.
targets(list): A list of string with the ninja targets to build.
"""
build_dir = checkout_path.join('out/%s' % config)
concurrent_jobs = self.m.properties.get('concurrent_jobs'
) or self._calculate_j_value()
ninja_args = [tool, '-C', build_dir, '-j', concurrent_jobs]
ninja_args.extend(targets)
with self.m.depot_tools.on_path():
name = 'build %s' % ' '.join([config] + list(targets))
self.m.step(name, ninja_args)
def build(self, config, checkout_path, targets, rbe_working_path=None):
"""Builds using ninja.
Args:
config(str): A string with the configuration to build.
checkout_path(Path): A path object with the checkout location.
targets(list): A list of string with the ninja targets to build.
rbe_working_path(path): Path to rbe working directory.
"""
ninja_path = checkout_path.join('flutter', 'third_party', 'ninja', 'ninja')
if self.use_rbe:
self._build_rbe(
config, checkout_path, targets, ninja_path, rbe_working_path
)
else:
if self.use_goma:
self._build_goma(config, checkout_path, targets, ninja_path)
else:
self._build_no_goma(config, checkout_path, targets, ninja_path)