1# Copyright 2016 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
6# pylint: disable=W0201
7
8
9from recipe_engine import recipe_api
10
11
12CONFIG_DEBUG = 'Debug'
13CONFIG_RELEASE = 'Release'
14
15
16class SkiaVarsApi(recipe_api.RecipeApi):
17
18  def make_path(self, *path):
19    """Return a Path object for the given path."""
20    key  = 'custom_%s' % '_'.join(path)
21    self.m.path.c.base_paths[key] = tuple(path)
22    return self.m.path[key]
23
24  def setup(self):
25    """Prepare the variables."""
26    # Setup
27    self.builder_name = self.m.properties['buildername']
28
29    self.slave_dir = self.m.path['start_dir']
30    self.checkout_root = self.slave_dir
31    self.default_env = self.m.context.env
32    self.default_env['CHROME_HEADLESS'] = '1'
33    self.default_env['PATH'] = self.m.path.pathsep.join([
34        self.default_env.get('PATH', '%(PATH)s'),
35        str(self.m.bot_update._module.PACKAGE_REPO_ROOT),
36    ])
37    self.gclient_env = {}
38    self.is_compile_bot = self.builder_name.startswith('Build-')
39
40    self.persistent_checkout = False
41    # Compile bots keep a persistent checkout.
42    if self.is_compile_bot:
43      self.persistent_checkout = True
44    if 'Housekeeper' in self.builder_name:
45      self.persistent_checkout = True
46    if '-CT_' in self.builder_name:
47      self.persistent_checkout = True
48    # We need the source code for the Coverage's Upload step to be in the
49    # same absolute location as when we compiled it so we can map the
50    # coverage data to actual line numbers. We ensure this by making sure
51    # we have a checkout on the Coverage's Upload step and that the Upload
52    # step runs on the same bots that Compile.
53    if 'Coverage' in self.builder_name and 'Upload' in self.builder_name:
54      self.persistent_checkout = True
55
56    if self.persistent_checkout:
57      if 'Win' in self.builder_name:
58        self.checkout_root = self.make_path('C:\\', 'b', 'work')
59        self.gclient_cache = self.make_path('C:\\', 'b', 'cache')
60      else:
61        self.checkout_root = self.make_path('/', 'b', 'work')
62        self.gclient_cache = self.make_path('/', 'b', 'cache')
63
64      # got_revision is filled in after checkout steps.
65      self.got_revision = None
66    else:
67      # If there's no persistent checkout, then we have to asume we got the
68      # correct revision of the files from isolate.
69      self.got_revision = self.m.properties['revision']
70
71    # Some bots also require a checkout of PDFium; in this case we use the
72    # checkout of Skia obtained through DEPS in pdfium/third_party/skia.
73    self.need_pdfium_checkout = 'PDFium' in self.builder_name
74
75    # Some bots also require a checkout of Flutter; in this case we use the
76    # checkout of Skia obtained through DEPS in src/third_party/skia.
77    self.need_flutter_checkout = 'Flutter' in self.builder_name
78
79    self.skia_dir = self.checkout_root.join('skia')
80    if self.need_pdfium_checkout:
81      self.skia_dir = self.checkout_root.join('pdfium', 'third_party', 'skia')
82    elif self.need_flutter_checkout:
83      self.checkout_root = self.checkout_root.join('flutter')
84      self.skia_dir = self.checkout_root.join('src', 'third_party', 'skia')
85
86    if not self.persistent_checkout:
87      self.m.path['checkout'] = self.skia_dir
88
89    self.infrabots_dir = self.skia_dir.join('infra', 'bots')
90    self.resource_dir = self.skia_dir.join('resources')
91    self.images_dir = self.slave_dir.join('skimage')
92    self.skia_out = self.skia_dir.join('out', self.builder_name)
93    self.swarming_out_dir = self.make_path(self.m.properties['swarm_out_dir'])
94    if 'ParentRevision' in self.builder_name:
95      # Tasks that depend on ParentRevision builds usually also depend on a
96      # second build task. Use a different path for build results so that the
97      # binaries end up in different directories in the isolate.
98      self.swarming_out_dir = self.swarming_out_dir.join('ParentRevision')
99    self.local_skp_dir = self.slave_dir.join('skp')
100    self.local_svg_dir = self.slave_dir.join('svg')
101    if not self.is_compile_bot:
102      self.skia_out = self.slave_dir.join('out')
103    self.tmp_dir = self.m.path['start_dir'].join('tmp')
104
105    # Some bots also require a checkout of chromium.
106    self.need_chromium_checkout = False
107    if 'CommandBuffer' in self.builder_name:
108      self.need_chromium_checkout = True
109      self.gclient_env['GYP_CHROMIUM_NO_ACTION'] = '0'
110    if 'RecreateSKPs' in self.builder_name:
111      self.need_chromium_checkout = True
112      self.gclient_env['CPPFLAGS'] = (
113          '-DSK_ALLOW_CROSSPROCESS_PICTUREIMAGEFILTERS=1')
114
115    self.builder_cfg = self.m.builder_name_schema.DictForBuilderName(
116        self.builder_name)
117    self.role = self.builder_cfg['role']
118    if self.role in [self.m.builder_name_schema.BUILDER_ROLE_HOUSEKEEPER,
119                     self.m.builder_name_schema.BUILDER_ROLE_CALMBENCH]:
120      self.configuration = CONFIG_RELEASE
121    else:
122      self.configuration = self.builder_cfg.get('configuration', CONFIG_DEBUG)
123    arch = (self.builder_cfg.get('arch') or self.builder_cfg.get('target_arch'))
124    if ('Win' in self.builder_cfg.get('os', '') and arch == 'x86_64'):
125      self.configuration += '_x64'
126    self.extra_tokens = []
127    if len(self.builder_cfg.get('extra_config', '')) > 0:
128      if self.builder_cfg['extra_config'].startswith('SK'):
129        assert self.builder_cfg['extra_config'].isupper()
130        self.extra_tokens = [self.builder_cfg['extra_config']]
131      else:
132        self.extra_tokens = self.builder_cfg['extra_config'].split('_')
133
134    self.default_env.update({'SKIA_OUT': self.skia_out,
135                             'BUILDTYPE': self.configuration})
136
137    self.patch_storage = self.m.properties.get('patch_storage', 'gerrit')
138    self.issue = None
139    self.patchset = None
140    self.is_trybot = False
141    if (self.m.properties.get('patch_issue', '') and
142        self.m.properties.get('patch_set', '')):
143      self.is_trybot = True
144      self.issue = self.m.properties['patch_issue']
145      self.patchset = self.m.properties['patch_set']
146
147    self.dm_dir = self.m.path.join(
148        self.swarming_out_dir, 'dm')
149    self.perf_data_dir = self.m.path.join(self.swarming_out_dir,
150        'perfdata', self.builder_name, 'data')
151    self._swarming_bot_id = None
152    self._swarming_task_id = None
153
154    # Data should go under in _data_dir, which may be preserved across runs.
155    self.android_data_dir = '/sdcard/revenge_of_the_skiabot/'
156    # Executables go under _bin_dir, which, well, allows executable files.
157    self.android_bin_dir  = '/data/local/tmp/'
158
159    if self.builder_cfg.get('os', '') == 'Chromecast':
160      # On the Chromecast, everything goes in the (~110M) /cache/skia
161      self.android_bin_dir  = '/cache/skia/'
162      self.android_data_dir = '/cache/skia/'
163
164    self.chromeos_homedir = '/home/chronos/user/'
165
166    # Internal bot support.
167    self.internal_hardware_label = (
168        self.m.properties.get('internal_hardware_label'))
169    self.is_internal_bot = self.internal_hardware_label is not None
170
171  @property
172  def is_linux(self):
173    return 'Ubuntu' in self.builder_name or 'Debian' in self.builder_name
174
175  @property
176  def upload_dm_results(self):
177    # TODO(borenet): Move this into the swarm_test recipe.
178    skip_upload_bots = [
179      'ASAN',
180      'Coverage',
181      'MSAN',
182      'TSAN',
183      'UBSAN',
184      'Valgrind',
185    ]
186    upload_dm_results = True
187    for s in skip_upload_bots:
188      if s in self.m.properties['buildername']:
189        upload_dm_results = False
190        break
191    return upload_dm_results
192
193  @property
194  def upload_perf_results(self):
195    # TODO(borenet): Move this into the swarm_perf recipe.
196    if 'Release' not in self.m.properties['buildername']:
197      return False
198    skip_upload_bots = [
199      'ASAN',
200      'Coverage',
201      'MSAN',
202      'TSAN',
203      'UBSAN',
204      'Valgrind',
205    ]
206    upload_perf_results = True
207    for s in skip_upload_bots:
208      if s in self.m.properties['buildername']:
209        upload_perf_results = False
210        break
211    return upload_perf_results
212
213  @property
214  def swarming_bot_id(self):
215    if not self._swarming_bot_id:
216      self._swarming_bot_id = self.m.python.inline(
217          name='get swarming bot id',
218          program='''import os
219print os.environ.get('SWARMING_BOT_ID', '')
220''',
221          stdout=self.m.raw_io.output()).stdout.rstrip()
222    return self._swarming_bot_id
223
224  @property
225  def swarming_task_id(self):
226    if not self._swarming_task_id:
227      self._swarming_task_id = self.m.python.inline(
228          name='get swarming task id',
229          program='''import os
230print os.environ.get('SWARMING_TASK_ID', '')
231''',
232          stdout=self.m.raw_io.output()).stdout.rstrip()
233    return self._swarming_task_id
234