OLD | NEW |
| (Empty) |
1 #!/usr/bin/env python | |
2 # | |
3 # Copyright 2016 Google Inc. | |
4 # | |
5 # Use of this source code is governed by a BSD-style license that can be | |
6 # found in the LICENSE file. | |
7 | |
8 | |
9 """Default flavor utils class, used for desktop bots.""" | |
10 | |
11 | |
12 import os | |
13 import shutil | |
14 import sys | |
15 | |
16 | |
17 class DeviceDirs(object): | |
18 def __init__(self, | |
19 dm_dir, | |
20 perf_data_dir, | |
21 resource_dir, | |
22 images_dir, | |
23 skp_dir, | |
24 tmp_dir): | |
25 self._dm_dir = dm_dir | |
26 self._perf_data_dir = perf_data_dir | |
27 self._resource_dir = resource_dir | |
28 self._images_dir = images_dir | |
29 self._skp_dir = skp_dir | |
30 self._tmp_dir = tmp_dir | |
31 | |
32 @property | |
33 def dm_dir(self): | |
34 """Where DM writes.""" | |
35 return self._dm_dir | |
36 | |
37 @property | |
38 def perf_data_dir(self): | |
39 return self._perf_data_dir | |
40 | |
41 @property | |
42 def resource_dir(self): | |
43 return self._resource_dir | |
44 | |
45 @property | |
46 def images_dir(self): | |
47 return self._images_dir | |
48 | |
49 @property | |
50 def skp_dir(self): | |
51 return self._skp_dir | |
52 | |
53 @property | |
54 def tmp_dir(self): | |
55 return self._tmp_dir | |
56 | |
57 | |
58 class DefaultFlavorUtils(object): | |
59 """Utilities to be used by build steps. | |
60 | |
61 The methods in this class define how certain high-level functions should | |
62 work. Each build step flavor should correspond to a subclass of | |
63 DefaultFlavorUtils which may override any of these functions as appropriate | |
64 for that flavor. | |
65 | |
66 For example, the AndroidFlavorUtils will override the functions for | |
67 copying files between the host and Android device, as well as the | |
68 'step' function, so that commands may be run through ADB. | |
69 """ | |
70 def __init__(self, bot_info, *args, **kwargs): | |
71 self._bot_info = bot_info | |
72 self.chrome_path = os.path.join(self._bot_info.build_dir, 'src') | |
73 | |
74 def run(self, cmd, **kwargs): | |
75 """Runs a step as appropriate for this flavor.""" | |
76 path_to_app = os.path.join(self._bot_info.out_dir, | |
77 self._bot_info.configuration, cmd[0]) | |
78 if ('linux' in sys.platform and | |
79 'x86_64' in self._bot_info.name and | |
80 not 'TSAN' in self._bot_info.name): | |
81 new_cmd = ['catchsegv', path_to_app] | |
82 else: | |
83 if sys.platform == 'win32': | |
84 path_to_app += '.exe' | |
85 new_cmd = [path_to_app] | |
86 new_cmd.extend(cmd[1:]) | |
87 return self._bot_info.run(new_cmd, **kwargs) | |
88 | |
89 def bootstrap_win_toolchain(self): | |
90 """Run bootstrapping script for the Windows toolchain.""" | |
91 bootstrap_script = os.path.join(self._bot_info.infrabots_dir, | |
92 'bootstrap_win_toolchain_json.py') | |
93 win_toolchain_json = os.path.join( | |
94 self._bot_info.build_dir, 'src', 'build', 'win_toolchain.json') | |
95 self._bot_info.run([ | |
96 'python', bootstrap_script, | |
97 '--win_toolchain_json', win_toolchain_json, | |
98 '--depot_tools_parent_dir', self._bot_info.build_dir]) | |
99 | |
100 def compile(self, target): | |
101 """Build the given target.""" | |
102 # The CHROME_PATH environment variable is needed for bots that use | |
103 # toolchains downloaded by Chrome. | |
104 env = {} | |
105 if sys.platform == 'win32': | |
106 make_cmd = ['python', 'make.py'] | |
107 env['CHROME_PATH'] = self.chrome_path | |
108 self._bot_info._run_once(self.bootstrap_win_toolchain) | |
109 else: | |
110 # Ensure depot_tools is in PATH. | |
111 depot_tools = os.path.join('/b', 'depot_tools') | |
112 env['PATH'] = os.pathsep.join([depot_tools, os.environ['PATH']]) | |
113 make_cmd = ['make'] | |
114 cmd = make_cmd + [target] | |
115 self._bot_info.run(cmd, env=env) | |
116 | |
117 def device_path_join(self, *args): | |
118 """Like os.path.join(), but for paths on a connected device.""" | |
119 return os.path.join(*args) | |
120 | |
121 def device_path_exists(self, path): | |
122 """Like os.path.exists(), but for paths on a connected device.""" | |
123 return os.path.exists(path, infra_step=True) # pragma: no cover | |
124 | |
125 def copy_directory_contents_to_device(self, host_dir, device_dir): | |
126 """Like shutil.copytree(), but for copying to a connected device.""" | |
127 # For "normal" bots who don't have an attached device, we expect | |
128 # host_dir and device_dir to be the same. | |
129 if str(host_dir) != str(device_dir): | |
130 raise ValueError('For bots who do not have attached devices, copying ' | |
131 'from host to device is undefined and only allowed if ' | |
132 'host_path and device_path are the same (%s vs %s).' % ( | |
133 str(host_dir), str(device_dir))) # pragma: no cover | |
134 | |
135 def copy_directory_contents_to_host(self, device_dir, host_dir): | |
136 """Like shutil.copytree(), but for copying from a connected device.""" | |
137 # For "normal" bots who don't have an attached device, we expect | |
138 # host_dir and device_dir to be the same. | |
139 if str(host_dir) != str(device_dir): | |
140 raise ValueError('For bots who do not have attached devices, copying ' | |
141 'from device to host is undefined and only allowed if ' | |
142 'host_path and device_path are the same (%s vs %s).' % ( | |
143 str(host_dir), str(device_dir))) # pragma: no cover | |
144 | |
145 def copy_file_to_device(self, host_path, device_path): | |
146 """Like shutil.copyfile, but for copying to a connected device.""" | |
147 # For "normal" bots who don't have an attached device, we expect | |
148 # host_dir and device_dir to be the same. | |
149 if str(host_path) != str(device_path): # pragma: no cover | |
150 raise ValueError('For bots who do not have attached devices, copying ' | |
151 'from host to device is undefined and only allowed if ' | |
152 'host_path and device_path are the same (%s vs %s).' % ( | |
153 str(host_path), str(device_path))) | |
154 | |
155 def create_clean_device_dir(self, path): | |
156 """Like shutil.rmtree() + os.makedirs(), but on a connected device.""" | |
157 self.create_clean_host_dir(path) | |
158 | |
159 def create_clean_host_dir(self, path): | |
160 """Convenience function for creating a clean directory.""" | |
161 if os.path.exists(path): | |
162 shutil.rmtree(path) | |
163 os.makedirs(path) | |
164 | |
165 def install(self): | |
166 """Run device-specific installation steps.""" | |
167 pass | |
168 | |
169 def cleanup_steps(self): | |
170 """Run any device-specific cleanup steps.""" | |
171 pass | |
172 | |
173 def get_device_dirs(self): | |
174 """ Set the directories which will be used by the build steps. | |
175 | |
176 These refer to paths on the same device where the test executables will | |
177 run, for example, for Android bots these are paths on the Android device | |
178 itself. For desktop bots, these are just local paths. | |
179 """ | |
180 join = lambda p: os.path.join(self._bot_info.build_dir, p) | |
181 return DeviceDirs( | |
182 dm_dir=os.path.join(self._bot_info.swarm_out_dir, 'dm'), | |
183 perf_data_dir=self._bot_info.perf_data_dir, | |
184 resource_dir=self._bot_info.resource_dir, | |
185 images_dir=join('images'), | |
186 skp_dir=self._bot_info.local_skp_dir, | |
187 tmp_dir=join('tmp')) | |
188 | |
189 def __repr__(self): | |
190 return '<%s object>' % self.__class__.__name__ # pragma: no cover | |
OLD | NEW |