OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # | 2 # |
3 # Copyright (c) 2013 The Chromium Authors. All rights reserved. | 3 # Copyright (c) 2013 The Chromium Authors. All rights reserved. |
4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
6 | 6 |
7 """Runs Android's lint tool.""" | 7 """Runs Android's lint tool.""" |
8 | 8 |
9 | 9 |
10 import argparse | 10 import argparse |
11 import os | 11 import os |
| 12 import re |
12 import sys | 13 import sys |
13 import traceback | 14 import traceback |
14 from xml.dom import minidom | 15 from xml.dom import minidom |
15 | 16 |
16 from util import build_utils | 17 from util import build_utils |
17 | 18 |
18 | 19 |
19 _SRC_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), | 20 _SRC_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), |
20 '..', '..', '..')) | 21 '..', '..', '..')) |
21 | 22 |
22 | 23 |
23 def _OnStaleMd5(changes, lint_path, config_path, processed_config_path, | 24 def _OnStaleMd5(changes, lint_path, config_path, processed_config_path, |
24 manifest_path, result_path, product_dir, sources, jar_path, | 25 manifest_path, result_path, product_dir, sources, jar_path, |
25 cache_dir, resource_dir=None, classpath=None, | 26 cache_dir, android_sdk_version, resource_dir=None, |
26 can_fail_build=False, silent=False): | 27 classpath=None, can_fail_build=False, silent=False): |
27 | |
28 def _RelativizePath(path): | 28 def _RelativizePath(path): |
29 """Returns relative path to top-level src dir. | 29 """Returns relative path to top-level src dir. |
30 | 30 |
31 Args: | 31 Args: |
32 path: A path relative to cwd. | 32 path: A path relative to cwd. |
33 """ | 33 """ |
34 return os.path.relpath(os.path.abspath(path), _SRC_ROOT) | 34 return os.path.relpath(os.path.abspath(path), _SRC_ROOT) |
35 | 35 |
36 def _ProcessConfigFile(): | 36 def _ProcessConfigFile(): |
37 if not config_path or not processed_config_path: | 37 if not config_path or not processed_config_path: |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
122 src_dir = None | 122 src_dir = None |
123 for d in src_dirs: | 123 for d in src_dirs: |
124 if not os.path.exists(PathInDir(d, src)): | 124 if not os.path.exists(PathInDir(d, src)): |
125 src_dir = d | 125 src_dir = d |
126 break | 126 break |
127 if not src_dir: | 127 if not src_dir: |
128 src_dir = NewSourceDir() | 128 src_dir = NewSourceDir() |
129 cmd.extend(['--sources', _RelativizePath(src_dir)]) | 129 cmd.extend(['--sources', _RelativizePath(src_dir)]) |
130 os.symlink(os.path.abspath(src), PathInDir(src_dir, src)) | 130 os.symlink(os.path.abspath(src), PathInDir(src_dir, src)) |
131 | 131 |
| 132 project_dir = NewSourceDir() |
| 133 if android_sdk_version: |
| 134 # Create dummy project.properies file in a temporary "project" directory. |
| 135 # It is the only way to add Android SDK to the Lint's classpath. Proper |
| 136 # classpath is necessary for most source-level checks. |
| 137 with open(os.path.join(project_dir, 'project.properties'), 'w') \ |
| 138 as propfile: |
| 139 print >> propfile, 'target=android-{}'.format(android_sdk_version) |
| 140 |
132 # Put the manifest in a temporary directory in order to avoid lint detecting | 141 # Put the manifest in a temporary directory in order to avoid lint detecting |
133 # sibling res/ and src/ directories (which should be pass explicitly if they | 142 # sibling res/ and src/ directories (which should be pass explicitly if they |
134 # are to be included). | 143 # are to be included). |
135 if manifest_path: | 144 if manifest_path: |
136 src_dir = NewSourceDir() | |
137 os.symlink(os.path.abspath(manifest_path), | 145 os.symlink(os.path.abspath(manifest_path), |
138 PathInDir(src_dir, manifest_path)) | 146 PathInDir(project_dir, manifest_path)) |
139 cmd.append(src_dir) | 147 cmd.append(project_dir) |
140 | 148 |
141 if os.path.exists(result_path): | 149 if os.path.exists(result_path): |
142 os.remove(result_path) | 150 os.remove(result_path) |
143 | 151 |
144 env = {} | 152 env = {} |
145 stderr_filter = None | 153 stderr_filter = None |
146 if cache_dir: | 154 if cache_dir: |
| 155 env['_JAVA_OPTIONS'] = '-Duser.home=%s' % _RelativizePath(cache_dir) |
147 # When _JAVA_OPTIONS is set, java prints to stderr: | 156 # When _JAVA_OPTIONS is set, java prints to stderr: |
148 # Picked up _JAVA_OPTIONS: ... | 157 # Picked up _JAVA_OPTIONS: ... |
149 env['_JAVA_OPTIONS'] = '-Duser.home=%s' % _RelativizePath(cache_dir) | 158 # |
150 stderr_filter = lambda l: '' if '_JAVA_OPTIONS' in l else l | 159 # We drop all lines that contain _JAVA_OPTIONS from the output |
| 160 stderr_filter = lambda l: re.sub(r'.*_JAVA_OPTIONS.*\n?', '', l) |
151 | 161 |
152 try: | 162 try: |
153 build_utils.CheckOutput(cmd, cwd=_SRC_ROOT, env=env or None, | 163 build_utils.CheckOutput(cmd, cwd=_SRC_ROOT, env=env or None, |
154 stderr_filter=stderr_filter) | 164 stderr_filter=stderr_filter) |
155 except build_utils.CalledProcessError: | 165 except build_utils.CalledProcessError: |
156 # There is a problem with lint usage | 166 # There is a problem with lint usage |
157 if not os.path.exists(result_path): | 167 if not os.path.exists(result_path): |
158 raise | 168 raise |
159 | 169 |
160 # Sometimes produces empty (almost) files: | 170 # Sometimes produces empty (almost) files: |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
218 help='Path to lint executable.') | 228 help='Path to lint executable.') |
219 parser.add_argument('--product-dir', required=True, | 229 parser.add_argument('--product-dir', required=True, |
220 help='Path to product dir.') | 230 help='Path to product dir.') |
221 parser.add_argument('--result-path', required=True, | 231 parser.add_argument('--result-path', required=True, |
222 help='Path to XML lint result file.') | 232 help='Path to XML lint result file.') |
223 parser.add_argument('--cache-dir', required=True, | 233 parser.add_argument('--cache-dir', required=True, |
224 help='Path to the directory in which the android cache ' | 234 help='Path to the directory in which the android cache ' |
225 'directory tree should be stored.') | 235 'directory tree should be stored.') |
226 parser.add_argument('--platform-xml-path', required=True, | 236 parser.add_argument('--platform-xml-path', required=True, |
227 help='Path to api-platforms.xml') | 237 help='Path to api-platforms.xml') |
| 238 parser.add_argument('--android-sdk-version', |
| 239 help='Version (API level) of the Android SDK used for ' |
| 240 'building.') |
228 parser.add_argument('--create-cache', action='store_true', | 241 parser.add_argument('--create-cache', action='store_true', |
229 help='Mark the lint cache file as an output rather than ' | 242 help='Mark the lint cache file as an output rather than ' |
230 'an input.') | 243 'an input.') |
231 parser.add_argument('--can-fail-build', action='store_true', | 244 parser.add_argument('--can-fail-build', action='store_true', |
232 help='If set, script will exit with nonzero exit status' | 245 help='If set, script will exit with nonzero exit status' |
233 ' if lint errors are present') | 246 ' if lint errors are present') |
234 parser.add_argument('--config-path', | 247 parser.add_argument('--config-path', |
235 help='Path to lint suppressions file.') | 248 help='Path to lint suppressions file.') |
236 parser.add_argument('--enable', action='store_true', | 249 parser.add_argument('--enable', action='store_true', |
237 help='Run lint instead of just touching stamp.') | 250 help='Run lint instead of just touching stamp.') |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
282 if args.resource_dir: | 295 if args.resource_dir: |
283 input_paths.extend(build_utils.FindInDirectory(args.resource_dir, '*')) | 296 input_paths.extend(build_utils.FindInDirectory(args.resource_dir, '*')) |
284 if sources: | 297 if sources: |
285 input_paths.extend(sources) | 298 input_paths.extend(sources) |
286 classpath = [] | 299 classpath = [] |
287 for gyp_list in args.classpath: | 300 for gyp_list in args.classpath: |
288 classpath.extend(build_utils.ParseGypList(gyp_list)) | 301 classpath.extend(build_utils.ParseGypList(gyp_list)) |
289 input_paths.extend(classpath) | 302 input_paths.extend(classpath) |
290 | 303 |
291 input_strings = [] | 304 input_strings = [] |
| 305 if args.android_sdk_version: |
| 306 input_strings.append(args.android_sdk_version) |
292 if args.processed_config_path: | 307 if args.processed_config_path: |
293 input_strings.append(args.processed_config_path) | 308 input_strings.append(args.processed_config_path) |
294 | 309 |
295 output_paths = [ args.result_path ] | 310 output_paths = [ args.result_path ] |
296 | 311 |
297 build_utils.CallAndWriteDepfileIfStale( | 312 build_utils.CallAndWriteDepfileIfStale( |
298 lambda changes: _OnStaleMd5(changes, args.lint_path, | 313 lambda changes: _OnStaleMd5(changes, args.lint_path, |
299 args.config_path, | 314 args.config_path, |
300 args.processed_config_path, | 315 args.processed_config_path, |
301 args.manifest_path, args.result_path, | 316 args.manifest_path, args.result_path, |
302 args.product_dir, sources, | 317 args.product_dir, sources, |
303 args.jar_path, | 318 args.jar_path, |
304 args.cache_dir, | 319 args.cache_dir, |
| 320 args.android_sdk_version, |
305 resource_dir=args.resource_dir, | 321 resource_dir=args.resource_dir, |
306 classpath=classpath, | 322 classpath=classpath, |
307 can_fail_build=args.can_fail_build, | 323 can_fail_build=args.can_fail_build, |
308 silent=args.silent), | 324 silent=args.silent), |
309 args, | 325 args, |
310 input_paths=input_paths, | 326 input_paths=input_paths, |
311 input_strings=input_strings, | 327 input_strings=input_strings, |
312 output_paths=output_paths, | 328 output_paths=output_paths, |
313 pass_changes=True, | 329 pass_changes=True, |
314 depfile_deps=classpath) | 330 depfile_deps=classpath) |
315 | 331 |
316 | 332 |
317 if __name__ == '__main__': | 333 if __name__ == '__main__': |
318 sys.exit(main()) | 334 sys.exit(main()) |
OLD | NEW |