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 else: | |
148 raise | |
149 if 'CommandBuffer' in self._skia_api.builder_name: | |
150 self._skia_api._run_once(self.build_command_buffer) | |
151 | |
152 def copy_extra_build_products(self, swarming_out_dir): | |
153 """Copy extra build products to specified directory. | |
154 | |
155 Copy flavor-specific build products to swarming_out_dir for use in test and | |
156 perf steps.""" | |
157 if ("Win" in self._skia_api.builder_name and | |
158 "Vulkan" in self._skia_api.builder_name): | |
159 # This copies vulkan-1.dll that has been bundled into win_vulkan_sdk | |
160 # since version 2 See skia/api BUILD_PRODUCTS_ISOLATE_WHITELIST | |
161 self._skia_api.copy_build_products( | |
162 self._skia_api.m.path['slave_build'].join('win_vulkan_sdk'), | |
163 swarming_out_dir) | |
164 | |
165 @property | |
166 def out_dir(self): | |
167 """Flavor-specific out directory.""" | |
168 return self._skia_api.skia_out.join(self._skia_api.configuration) | |
169 | |
170 def device_path_join(self, *args): | |
171 """Like os.path.join(), but for paths on a connected device.""" | |
172 return self._skia_api.m.path.join(*args) | |
173 | |
174 def device_path_exists(self, path): # pragma: no cover | |
175 """Like os.path.exists(), but for paths on a connected device.""" | |
176 return self._skia_api.m.path.exists(path, infra_step=True) | |
177 | |
178 def copy_directory_contents_to_device(self, host_dir, device_dir): | |
179 """Like shutil.copytree(), but for copying to a connected device.""" | |
180 # For "normal" builders who don't have an attached device, we expect | |
181 # host_dir and device_dir to be the same. | |
182 if str(host_dir) != str(device_dir): | |
183 raise ValueError('For builders who do not have attached devices, copying ' | |
184 'from host to device is undefined and only allowed if ' | |
185 'host_path and device_path are the same (%s vs %s).' % ( | |
186 str(host_dir), str(device_dir))) # pragma: no cover | |
187 | |
188 def copy_directory_contents_to_host(self, device_dir, host_dir): | |
189 """Like shutil.copytree(), but for copying from a connected device.""" | |
190 # For "normal" builders who don't have an attached device, we expect | |
191 # host_dir and device_dir to be the same. | |
192 if str(host_dir) != str(device_dir): | |
193 raise ValueError('For builders who do not have attached devices, copying ' | |
194 'from device to host is undefined and only allowed if ' | |
195 'host_path and device_path are the same (%s vs %s).' % ( | |
196 str(host_dir), str(device_dir))) # pragma: no cover | |
197 | |
198 def copy_file_to_device(self, host_path, device_path): | |
199 """Like shutil.copyfile, but for copying to a connected device.""" | |
200 # For "normal" builders who don't have an attached device, we expect | |
201 # host_dir and device_dir to be the same. | |
202 if str(host_path) != str(device_path): # pragma: no cover | |
203 raise ValueError('For builders who do not have attached devices, copying ' | |
204 'from host to device is undefined and only allowed if ' | |
205 'host_path and device_path are the same (%s vs %s).' % ( | |
206 str(host_path), str(device_path))) | |
207 | |
208 def create_clean_device_dir(self, path): | |
209 """Like shutil.rmtree() + os.makedirs(), but on a connected device.""" | |
210 self.create_clean_host_dir(path) | |
211 | |
212 def create_clean_host_dir(self, path): | |
213 """Convenience function for creating a clean directory.""" | |
214 self._skia_api.rmtree(path) | |
215 self._skia_api.m.file.makedirs( | |
216 self._skia_api.m.path.basename(path), path, infra_step=True) | |
217 | |
218 def install(self): | |
219 """Run device-specific installation steps.""" | |
220 pass | |
221 | |
222 def cleanup_steps(self): | |
223 """Run any device-specific cleanup steps.""" | |
224 pass | |
225 | |
226 def get_device_dirs(self): | |
227 """ Set the directories which will be used by the build steps. | |
228 | |
229 These refer to paths on the same device where the test executables will | |
230 run, for example, for Android bots these are paths on the Android device | |
231 itself. For desktop bots, these are just local paths. | |
232 """ | |
233 return DeviceDirs( | |
234 dm_dir=self._skia_api.dm_dir, | |
235 perf_data_dir=self._skia_api.perf_data_dir, | |
236 resource_dir=self._skia_api.resource_dir, | |
237 images_dir=self._skia_api.images_dir, | |
238 skp_dir=self._skia_api.local_skp_dir, | |
239 tmp_dir=self._skia_api.tmp_dir) | |
240 | |
241 def __repr__(self): | |
242 return '<%s object>' % self.__class__.__name__ # pragma: no cover | |
OLD | NEW |