OLD | NEW |
(Empty) | |
| 1 # Copyright 2014 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 """Default flavor utils class, used for desktop builders.""" |
| 7 |
| 8 |
| 9 import json |
| 10 |
| 11 |
| 12 WIN_TOOLCHAIN_DIR = 't' |
| 13 |
| 14 |
| 15 class DeviceDirs(object): |
| 16 def __init__(self, |
| 17 dm_dir, |
| 18 perf_data_dir, |
| 19 resource_dir, |
| 20 images_dir, |
| 21 skp_dir, |
| 22 tmp_dir): |
| 23 self._dm_dir = dm_dir |
| 24 self._perf_data_dir = perf_data_dir |
| 25 self._resource_dir = resource_dir |
| 26 self._images_dir = images_dir |
| 27 self._skp_dir = skp_dir |
| 28 self._tmp_dir = tmp_dir |
| 29 |
| 30 @property |
| 31 def dm_dir(self): |
| 32 """Where DM writes.""" |
| 33 return self._dm_dir |
| 34 |
| 35 @property |
| 36 def perf_data_dir(self): |
| 37 return self._perf_data_dir |
| 38 |
| 39 @property |
| 40 def resource_dir(self): |
| 41 return self._resource_dir |
| 42 |
| 43 @property |
| 44 def images_dir(self): |
| 45 return self._images_dir |
| 46 |
| 47 @property |
| 48 def skp_dir(self): |
| 49 """Holds SKP files that are consumed by RenderSKPs and BenchPictures.""" |
| 50 return self._skp_dir |
| 51 |
| 52 @property |
| 53 def tmp_dir(self): |
| 54 return self._tmp_dir |
| 55 |
| 56 |
| 57 class DefaultFlavorUtils(object): |
| 58 """Utilities to be used by build steps. |
| 59 |
| 60 The methods in this class define how certain high-level functions should |
| 61 work. Each build step flavor should correspond to a subclass of |
| 62 DefaultFlavorUtils which may override any of these functions as appropriate |
| 63 for that flavor. |
| 64 |
| 65 For example, the AndroidFlavorUtils will override the functions for |
| 66 copying files between the host and Android device, as well as the |
| 67 'step' function, so that commands may be run through ADB. |
| 68 """ |
| 69 def __init__(self, skia_api, *args, **kwargs): |
| 70 self._skia_api = skia_api |
| 71 self._chrome_path = None |
| 72 self._win_toolchain_dir = self._skia_api.slave_dir.join(WIN_TOOLCHAIN_DIR) |
| 73 win_toolchain_asset_path = self._skia_api.infrabots_dir.join( |
| 74 'assets', 'win_toolchain', 'VERSION') |
| 75 if not self._skia_api.m.path.exists(win_toolchain_asset_path): |
| 76 self._win_toolchain_dir = self._skia_api.slave_dir |
| 77 |
| 78 |
| 79 def step(self, name, cmd, **kwargs): |
| 80 """Wrapper for the Step API; runs a step as appropriate for this flavor.""" |
| 81 path_to_app = self._skia_api.skia_out.join( |
| 82 self._skia_api.configuration, cmd[0]) |
| 83 if (self._skia_api.m.platform.is_linux and |
| 84 'x86_64' in self._skia_api.builder_name and |
| 85 not 'TSAN' in self._skia_api.builder_name): |
| 86 new_cmd = ['catchsegv', path_to_app] |
| 87 else: |
| 88 new_cmd = [path_to_app] |
| 89 new_cmd.extend(cmd[1:]) |
| 90 return self._skia_api.run(self._skia_api.m.step, |
| 91 name, cmd=new_cmd, **kwargs) |
| 92 |
| 93 @property |
| 94 def chrome_path(self): |
| 95 """Path to a checkout of Chrome on this machine.""" |
| 96 return self._win_toolchain_dir.join('src') |
| 97 |
| 98 def bootstrap_win_toolchain(self): |
| 99 """Run bootstrapping script for the Windows toolchain.""" |
| 100 bootstrap_script = self._skia_api.infrabots_dir.join( |
| 101 'bootstrap_win_toolchain_json.py') |
| 102 win_toolchain_json = self._win_toolchain_dir.join( |
| 103 'src', 'build', 'win_toolchain.json') |
| 104 self._skia_api.m.python( |
| 105 'bootstrap win toolchain', |
| 106 script=bootstrap_script, |
| 107 args=['--win_toolchain_json', win_toolchain_json, |
| 108 '--depot_tools_parent_dir', |
| 109 self._win_toolchain_dir]) |
| 110 |
| 111 def build_command_buffer(self): |
| 112 """Build command_buffer.""" |
| 113 script = self._skia_api.skia_dir.join('tools', 'build_command_buffer.py') |
| 114 self._skia_api.run( |
| 115 self._skia_api.m.python, 'build command_buffer', |
| 116 script=script, |
| 117 args=['--chrome-dir', self._skia_api.checkout_root, |
| 118 '--output-dir', self.out_dir, |
| 119 '--chrome-build-type', self._skia_api.configuration, |
| 120 '--no-sync']) |
| 121 |
| 122 def compile(self, target): |
| 123 """Build the given target.""" |
| 124 # The CHROME_PATH environment variable is needed for builders that use |
| 125 # toolchains downloaded by Chrome. |
| 126 env = {'CHROME_PATH': self.chrome_path} |
| 127 if self._skia_api.m.platform.is_win: |
| 128 make_cmd = ['python', 'make.py'] |
| 129 self._skia_api._run_once(self.bootstrap_win_toolchain) |
| 130 if 'Vulkan' in self._skia_api.builder_name: |
| 131 env['VK_SDK_PATH'] = self._skia_api.slave_dir.join('win_vulkan_sdk') |
| 132 if not self._skia_api.m.path.exists(self._skia_api.infrabots_dir.join( |
| 133 'assets', 'win_vulkan_sdk', 'VERSION')): |
| 134 # TODO(kjlubick): Remove this once enough time has passed. |
| 135 env['VK_SDK_PATH'] = self._skia_api.slave_dir.join('vulkan_1.0.17.0') |
| 136 else: |
| 137 make_cmd = ['make'] |
| 138 cmd = make_cmd + [target] |
| 139 try: |
| 140 self._skia_api.run(self._skia_api.m.step, 'build %s' % target, cmd=cmd, |
| 141 env=env, cwd=self._skia_api.m.path['checkout']) |
| 142 except self._skia_api.m.step.StepFailure: |
| 143 if self._skia_api.m.platform.is_win: |
| 144 # The linker occasionally crashes on Windows. Try again. |
| 145 self._skia_api.run(self._skia_api.m.step, 'build %s' % target, cmd=cmd, |
| 146 env=env, cwd=self._skia_api.m.path['checkout']) |
| 147 if 'CommandBuffer' in self._skia_api.builder_name: |
| 148 self._skia_api._run_once(self.build_command_buffer) |
| 149 |
| 150 def copy_extra_build_products(self, swarming_out_dir): |
| 151 """Copy extra build products to specified directory. |
| 152 |
| 153 Copy flavor-specific build products to swarming_out_dir for use in test and |
| 154 perf steps.""" |
| 155 pass |
| 156 |
| 157 @property |
| 158 def out_dir(self): |
| 159 """Flavor-specific out directory.""" |
| 160 return self._skia_api.skia_out.join(self._skia_api.configuration) |
| 161 |
| 162 def device_path_join(self, *args): |
| 163 """Like os.path.join(), but for paths on a connected device.""" |
| 164 return self._skia_api.m.path.join(*args) |
| 165 |
| 166 def device_path_exists(self, path): # pragma: no cover |
| 167 """Like os.path.exists(), but for paths on a connected device.""" |
| 168 return self._skia_api.m.path.exists(path, infra_step=True) |
| 169 |
| 170 def copy_directory_contents_to_device(self, host_dir, device_dir): |
| 171 """Like shutil.copytree(), but for copying to a connected device.""" |
| 172 # For "normal" builders who don't have an attached device, we expect |
| 173 # host_dir and device_dir to be the same. |
| 174 if str(host_dir) != str(device_dir): |
| 175 raise ValueError('For builders who do not have attached devices, copying ' |
| 176 'from host to device is undefined and only allowed if ' |
| 177 'host_path and device_path are the same (%s vs %s).' % ( |
| 178 str(host_dir), str(device_dir))) # pragma: no cover |
| 179 |
| 180 def copy_directory_contents_to_host(self, device_dir, host_dir): |
| 181 """Like shutil.copytree(), but for copying from a connected device.""" |
| 182 # For "normal" builders who don't have an attached device, we expect |
| 183 # host_dir and device_dir to be the same. |
| 184 if str(host_dir) != str(device_dir): |
| 185 raise ValueError('For builders who do not have attached devices, copying ' |
| 186 'from device to host is undefined and only allowed if ' |
| 187 'host_path and device_path are the same (%s vs %s).' % ( |
| 188 str(host_dir), str(device_dir))) # pragma: no cover |
| 189 |
| 190 def copy_file_to_device(self, host_path, device_path): |
| 191 """Like shutil.copyfile, but for copying to a connected device.""" |
| 192 # For "normal" builders who don't have an attached device, we expect |
| 193 # host_dir and device_dir to be the same. |
| 194 if str(host_path) != str(device_path): # pragma: no cover |
| 195 raise ValueError('For builders who do not have attached devices, copying ' |
| 196 'from host to device is undefined and only allowed if ' |
| 197 'host_path and device_path are the same (%s vs %s).' % ( |
| 198 str(host_path), str(device_path))) |
| 199 |
| 200 def create_clean_device_dir(self, path): |
| 201 """Like shutil.rmtree() + os.makedirs(), but on a connected device.""" |
| 202 self.create_clean_host_dir(path) |
| 203 |
| 204 def create_clean_host_dir(self, path): |
| 205 """Convenience function for creating a clean directory.""" |
| 206 self._skia_api.rmtree(path) |
| 207 self._skia_api.m.file.makedirs( |
| 208 self._skia_api.m.path.basename(path), path, infra_step=True) |
| 209 |
| 210 def install(self): |
| 211 """Run device-specific installation steps.""" |
| 212 pass |
| 213 |
| 214 def cleanup_steps(self): |
| 215 """Run any device-specific cleanup steps.""" |
| 216 pass |
| 217 |
| 218 def get_device_dirs(self): |
| 219 """ Set the directories which will be used by the build steps. |
| 220 |
| 221 These refer to paths on the same device where the test executables will |
| 222 run, for example, for Android bots these are paths on the Android device |
| 223 itself. For desktop bots, these are just local paths. |
| 224 """ |
| 225 return DeviceDirs( |
| 226 dm_dir=self._skia_api.dm_dir, |
| 227 perf_data_dir=self._skia_api.perf_data_dir, |
| 228 resource_dir=self._skia_api.resource_dir, |
| 229 images_dir=self._skia_api.images_dir, |
| 230 skp_dir=self._skia_api.local_skp_dir, |
| 231 tmp_dir=self._skia_api.tmp_dir) |
| 232 |
| 233 def __repr__(self): |
| 234 return '<%s object>' % self.__class__.__name__ # pragma: no cover |
OLD | NEW |