Roll src/third_party/WebKit a3b4a2e:7441784 (svn 202551:202552)
[chromium-blink-merge.git] / build / android / pylib / utils / isolator.py
blob20b54072ab9287d462d61289e7d0cf21330e85b4
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.
5 import fnmatch
6 import glob
7 import os
8 import shutil
9 import sys
11 from devil.utils import cmd_helper
12 from pylib import constants
15 _ISOLATE_SCRIPT = os.path.join(
16 constants.DIR_SOURCE_ROOT, 'tools', 'swarming_client', 'isolate.py')
19 def DefaultPathVariables():
20 return {
21 'DEPTH': constants.DIR_SOURCE_ROOT,
22 'PRODUCT_DIR': constants.GetOutDirectory(),
26 def DefaultConfigVariables():
27 # Note: This list must match the --config-vars in build/isolate.gypi
28 return {
29 'CONFIGURATION_NAME': constants.GetBuildType(),
30 'OS': 'android',
31 'asan': '0',
32 'branding': 'Chromium',
33 'chromeos': '0',
34 'component': 'static_library',
35 'enable_pepper_cdms': '0',
36 'enable_plugins': '0',
37 'fastbuild': '0',
38 'icu_use_data_file_flag': '1',
39 'kasko': '0',
40 'lsan': '0',
41 'msan': '0',
42 # TODO(maruel): This may not always be true.
43 'target_arch': 'arm',
44 'tsan': '0',
45 'use_custom_libcxx': '0',
46 'use_instrumented_libraries': '0',
47 'use_prebuilt_instrumented_libraries': '0',
48 'use_openssl': '0',
49 'use_ozone': '0',
50 'use_x11': '0',
51 'v8_use_external_startup_data': '1',
52 'msvs_version': '0',
56 class Isolator(object):
57 """Manages calls to isolate.py for the android test runner scripts."""
59 def __init__(self, isolate_deps_dir):
60 """
61 Args:
62 isolate_deps_dir: The directory in which dependencies specified by
63 isolate are or should be stored.
64 """
65 self._isolate_deps_dir = isolate_deps_dir
67 def Clear(self):
68 """Deletes the isolate dependency directory."""
69 if os.path.exists(self._isolate_deps_dir):
70 shutil.rmtree(self._isolate_deps_dir)
72 def Remap(self, isolate_abs_path, isolated_abs_path,
73 path_variables=None, config_variables=None):
74 """Remaps data dependencies into |self._isolate_deps_dir|.
76 Args:
77 isolate_abs_path: The absolute path to the .isolate file, which specifies
78 data dependencies in the source tree.
79 isolated_abs_path: The absolute path to the .isolated file, which is
80 generated by isolate.py and specifies data dependencies in
81 |self._isolate_deps_dir| and their digests.
82 path_variables: A dict containing everything that should be passed
83 as a |--path-variable| to the isolate script. Defaults to the return
84 value of |DefaultPathVariables()|.
85 config_variables: A dict containing everything that should be passed
86 as a |--config-variable| to the isolate script. Defaults to the return
87 value of |DefaultConfigVariables()|.
88 Raises:
89 Exception if the isolate command fails for some reason.
90 """
91 if not path_variables:
92 path_variables = DefaultPathVariables()
93 if not config_variables:
94 config_variables = DefaultConfigVariables()
96 isolate_cmd = [
97 sys.executable, _ISOLATE_SCRIPT, 'remap',
98 '--isolate', isolate_abs_path,
99 '--isolated', isolated_abs_path,
100 '--outdir', self._isolate_deps_dir,
102 for k, v in path_variables.iteritems():
103 isolate_cmd.extend(['--path-variable', k, v])
104 for k, v in config_variables.iteritems():
105 isolate_cmd.extend(['--config-variable', k, v])
107 if cmd_helper.RunCmd(isolate_cmd):
108 raise Exception('isolate command failed: %s' % ' '.join(isolate_cmd))
110 def VerifyHardlinks(self):
111 """Checks |isolate_deps_dir| for a hardlink.
113 Returns:
114 True if a hardlink is found.
115 False if nothing is found.
116 Raises:
117 Exception if a non-hardlink is found.
119 for root, _, filenames in os.walk(self._isolate_deps_dir):
120 if filenames:
121 linked_file = os.path.join(root, filenames[0])
122 orig_file = os.path.join(
123 self._isolate_deps_dir,
124 os.path.relpath(linked_file, self._isolate_deps_dir))
125 if os.stat(linked_file).st_ino == os.stat(orig_file).st_ino:
126 return True
127 else:
128 raise Exception('isolate remap command did not use hardlinks.')
129 return False
131 def PurgeExcluded(self, deps_exclusion_list):
132 """Deletes anything on |deps_exclusion_list| from |self._isolate_deps_dir|.
134 Args:
135 deps_exclusion_list: A list of globs to exclude from the isolate
136 dependency directory.
138 excluded_paths = (
139 x for y in deps_exclusion_list
140 for x in glob.glob(
141 os.path.abspath(os.path.join(self._isolate_deps_dir, y))))
142 for p in excluded_paths:
143 if os.path.isdir(p):
144 shutil.rmtree(p)
145 else:
146 os.remove(p)
148 def MoveOutputDeps(self):
149 """Moves files from the output directory to the top level of
150 |self._isolate_deps_dir|.
152 Moves pak files from the output directory to to <isolate_deps_dir>/paks
153 Moves files from the product directory to <isolate_deps_dir>
155 # On Android, all pak files need to be in the top-level 'paks' directory.
156 paks_dir = os.path.join(self._isolate_deps_dir, 'paks')
157 os.mkdir(paks_dir)
159 deps_out_dir = os.path.join(
160 self._isolate_deps_dir,
161 os.path.relpath(os.path.join(constants.GetOutDirectory(), os.pardir),
162 constants.DIR_SOURCE_ROOT))
163 for root, _, filenames in os.walk(deps_out_dir):
164 for filename in fnmatch.filter(filenames, '*.pak'):
165 shutil.move(os.path.join(root, filename), paks_dir)
167 # Move everything in PRODUCT_DIR to top level.
168 deps_product_dir = os.path.join(deps_out_dir, constants.GetBuildType())
169 if os.path.isdir(deps_product_dir):
170 for p in os.listdir(deps_product_dir):
171 shutil.move(os.path.join(deps_product_dir, p), self._isolate_deps_dir)
172 os.rmdir(deps_product_dir)
173 os.rmdir(deps_out_dir)