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 12BUILD_PRODUCTS_ISOLATE_WHITELIST = [ 13 'dm', 14 'dm.exe', 15 'dm.app', 16 'nanobench.app', 17 'get_images_from_skps', 18 'get_images_from_skps.exe', 19 'nanobench', 20 'nanobench.exe', 21 'skpbench', 22 '*.so', 23 '*.dll', 24 '*.dylib', 25 'skia_launcher', 26 'lib/*.so', 27 'iOSShell.app', 28 'iOSShell.ipa', 29 'visualbench', 30 'visualbench.exe', 31 'vulkan-1.dll', 32] 33 34 35class SkiaStepApi(recipe_api.RecipeApi): 36 37 def __init__(self, *args, **kwargs): 38 """Initialize the recipe module.""" 39 super(SkiaStepApi, self).__init__(*args, **kwargs) 40 41 self._already_ran = {} 42 self._ccache = None 43 self._checked_for_ccache = False 44 self._failed = [] 45 46 def check_failure(self): 47 """Raise an exception if any step failed.""" 48 if self._failed: 49 raise self.m.step.StepFailure('Failed build steps: %s' % 50 ', '.join([f.name for f in self._failed])) 51 52 @property 53 def failed_steps(self): 54 return self._failed[:] 55 56 def run_once(self, fn, *args, **kwargs): 57 if not fn.__name__ in self._already_ran: 58 self._already_ran[fn.__name__] = fn(*args, **kwargs) 59 return self._already_ran[fn.__name__] 60 61 def readfile(self, filename, *args, **kwargs): 62 """Convenience function for reading files.""" 63 name = kwargs.pop('name', 'read %s' % self.m.path.basename(filename)) 64 return self.m.file.read_text(name, filename, *args, **kwargs) 65 66 def writefile(self, filename, contents): 67 """Convenience function for writing files.""" 68 return self.m.file.write_text('write %s' % self.m.path.basename(filename), 69 filename, contents) 70 71 def rmtree(self, path): 72 """Wrapper around api.file.rmtree.""" 73 self.m.file.rmtree('rmtree %s' % self.m.path.basename(path), path) 74 75 def __call__(self, steptype, name, abort_on_failure=True, 76 fail_build_on_failure=True, **kwargs): 77 """Run a step. If it fails, keep going but mark the build status failed.""" 78 try: 79 with self.m.env(self.m.vars.default_env): 80 return steptype(name=name, **kwargs) 81 except self.m.step.StepFailure as e: 82 if abort_on_failure or fail_build_on_failure: 83 self._failed.append(e) 84 if abort_on_failure: 85 raise 86 87 def copy_build_products(self, src, dst): 88 """Copy whitelisted build products from src to dst.""" 89 self.m.python.inline( 90 name='copy build products', 91 program='''import errno 92import glob 93import os 94import shutil 95import sys 96 97src = sys.argv[1] 98dst = sys.argv[2] 99build_products_whitelist = %s 100 101try: 102 os.makedirs(dst) 103except OSError as e: 104 if e.errno != errno.EEXIST: 105 raise 106 107for pattern in build_products_whitelist: 108 path = os.path.join(src, pattern) 109 for f in glob.glob(path): 110 dst_path = os.path.join(dst, os.path.relpath(f, src)) 111 if not os.path.isdir(os.path.dirname(dst_path)): 112 os.makedirs(os.path.dirname(dst_path)) 113 print 'Copying build product %%s to %%s' %% (f, dst_path) 114 shutil.move(f, dst_path) 115''' % str(BUILD_PRODUCTS_ISOLATE_WHITELIST), 116 args=[src, dst], 117 infra_step=True) 118 119 def with_retry(self, steptype, name, attempts, **kwargs): 120 for attempt in xrange(attempts): 121 step_name = name 122 if attempt > 0: 123 step_name += ' (attempt %d)' % (attempt + 1) 124 try: 125 res = self(steptype, name=step_name, **kwargs) 126 return res 127 except self.m.step.StepFailure: 128 if attempt == attempts - 1: 129 raise 130