Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 # Copyright (c) 2014 Google Inc. All rights reserved. | 1 # Copyright (c) 2014 Google Inc. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 | 4 |
| 5 """ | 5 """ |
| 6 This script is intended for use as a GYP_GENERATOR. It takes as input (by way of | 6 This script is intended for use as a GYP_GENERATOR. It takes as input (by way of |
| 7 the generator flag config_path) the path of a json file that dictates the files | 7 the generator flag config_path) the path of a json file that dictates the files |
| 8 and targets to search for. The following keys are supported: | 8 and targets to search for. The following keys are supported: |
| 9 files: list of paths (relative) of the files to search for. | 9 files: list of paths (relative) of the files to search for. |
| 10 targets: list of targets to search for. The target names are unqualified. | 10 test_targets: unqualified target names to search for. Any target in this list |
| 11 that depends upon a file in |files| is output regardless of the type of target | |
| 12 or chain of dependencies. | |
| 13 compile_targets: Additional unqualified targets to search for. Targets in this | |
|
Dirk Pranke
2015/11/11 03:51:16
"Additional" is perhaps a bit confusing in this co
sky
2015/11/11 18:38:10
I thought we agreed on compile_targets as the name
| |
| 14 list that depend upon a file in |files| are not necessarily output. For | |
| 15 example, if the target is out type none then the target is not output (but one | |
| 16 of the descendants of the target will be). | |
| 11 | 17 |
| 12 The following is output: | 18 The following is output: |
| 13 error: only supplied if there is an error. | 19 error: only supplied if there is an error. |
| 14 build_targets: minimal set of targets that directly depend on the changed | 20 compile_targets: minimal set of targets that directly or indirectly depend on |
| 15 files and need to be built. The expectation is this set of targets is passed | 21 the files in |files| and is one of the supplied targets or a target that one |
| 16 into a build step. The returned values are either values in the supplied | 22 of the supplied targets depends on. |
|
Dirk Pranke
2015/11/11 03:51:16
maybe note that the second clause only applies if
sky
2015/11/11 18:38:10
Done.
| |
| 17 targets, or have a dependency on one of the supplied targets. | 23 The expectation is this set of targets is passed into a build step. |
| 24 test_targets: set of targets from the supplied |test_targets| that either | |
| 25 directly or indictly depend upon a file in |files|. This list if useful | |
|
Dirk Pranke
2015/11/11 03:51:16
typo: s/indictly/indirectly .
sky
2015/11/11 18:38:10
Done.
| |
| 26 if additional processing needs to be done for certain targets after the | |
| 27 build, such as running tests. | |
| 18 status: outputs one of three values: none of the supplied files were found, | 28 status: outputs one of three values: none of the supplied files were found, |
| 19 one of the include files changed so that it should be assumed everything | 29 one of the include files changed so that it should be assumed everything |
| 20 changed (in this case targets and build_targets are not output) or at | 30 changed (in this case test_targets and compile_targets are not output) or at |
| 21 least one file was found. | 31 least one file was found. |
| 22 invalid_targets: list of supplied targets thare were not found. | 32 invalid_targets: list of supplied targets thare were not found. |
|
Dirk Pranke
2015/11/11 03:51:16
typo: s/thare/that/
sky
2015/11/11 18:38:10
Done.
| |
| 23 | 33 |
| 24 Example: | 34 Example: |
| 25 Consider a graph like the following: | 35 Consider a graph like the following: |
| 26 A D | 36 A D |
| 27 / \ | 37 / \ |
| 28 B C | 38 B C |
| 29 A depends upon both B and C, A is of type none and B and C are executables. | 39 A depends upon both B and C, A is of type none and B and C are executables. |
| 30 D is an executable, has no dependencies and nothing depends on it. | 40 D is an executable, has no dependencies and nothing depends on it. |
| 31 If |targets| = ["A"] and files = ["b.cc", "d.cc"] (B depends upon b.cc and D | 41 If |compile_targets| = ["A"], |test_targets| = ["B", "C"] and |
| 32 depends upon d.cc), then the following is output: | 42 files = ["b.cc", "d.cc"] (B depends upon b.cc and D depends upon d.cc), then |
| 33 |build_targets| = ["B"] B must built as it depends upon the changed file b.cc | 43 the following is output: |
| 44 |compile_targets| = ["B"] B must built as it depends upon the changed file b.cc | |
| 34 and the supplied target A depends upon it. A is not output as a build_target | 45 and the supplied target A depends upon it. A is not output as a build_target |
| 35 as it is of type none with no rules and actions. | 46 as it is of type none with no rules and actions. |
| 47 |test_targets| = ["B"] B directly depends upon the change file b.cc. | |
| 36 | 48 |
| 37 Even though the file d.cc, which D depends upon, has changed D is not output | 49 Even though the file d.cc, which D depends upon, has changed D is not output |
| 38 as none of the supplied targets (A) depend upon D. | 50 as it was not supplied by way of |compile_targets| or |test_targets|. |
| 39 | 51 |
| 40 If the generator flag analyzer_output_path is specified, output is written | 52 If the generator flag analyzer_output_path is specified, output is written |
| 41 there. Otherwise output is written to stdout. | 53 there. Otherwise output is written to stdout. |
| 42 """ | 54 """ |
| 43 | 55 |
| 44 import gyp.common | 56 import gyp.common |
| 45 import gyp.ninja_syntax as ninja_syntax | 57 import gyp.ninja_syntax as ninja_syntax |
| 46 import json | 58 import json |
| 47 import os | 59 import os |
| 48 import posixpath | 60 import posixpath |
| (...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 218 self.is_or_has_linked_ancestor = False | 230 self.is_or_has_linked_ancestor = False |
| 219 | 231 |
| 220 | 232 |
| 221 class Config(object): | 233 class Config(object): |
| 222 """Details what we're looking for | 234 """Details what we're looking for |
| 223 files: set of files to search for | 235 files: set of files to search for |
| 224 targets: see file description for details.""" | 236 targets: see file description for details.""" |
| 225 def __init__(self): | 237 def __init__(self): |
| 226 self.files = [] | 238 self.files = [] |
| 227 self.targets = set() | 239 self.targets = set() |
| 240 self.compile_targets = set() | |
| 241 self.test_targets = set() | |
| 242 # Needed until recipes is updated. | |
|
Dirk Pranke
2015/11/11 03:51:16
Nit: "are updated" :).
sky
2015/11/11 18:38:10
Done.
| |
| 243 self.deprecated_mode = False | |
| 228 | 244 |
| 229 def Init(self, params): | 245 def Init(self, params): |
| 230 """Initializes Config. This is a separate method as it raises an exception | 246 """Initializes Config. This is a separate method as it raises an exception |
| 231 if there is a parse error.""" | 247 if there is a parse error.""" |
| 232 generator_flags = params.get('generator_flags', {}) | 248 generator_flags = params.get('generator_flags', {}) |
| 233 config_path = generator_flags.get('config_path', None) | 249 config_path = generator_flags.get('config_path', None) |
| 234 if not config_path: | 250 if not config_path: |
| 235 return | 251 return |
| 236 try: | 252 try: |
| 237 f = open(config_path, 'r') | 253 f = open(config_path, 'r') |
| 238 config = json.load(f) | 254 config = json.load(f) |
| 239 f.close() | 255 f.close() |
| 240 except IOError: | 256 except IOError: |
| 241 raise Exception('Unable to open file ' + config_path) | 257 raise Exception('Unable to open file ' + config_path) |
| 242 except ValueError as e: | 258 except ValueError as e: |
| 243 raise Exception('Unable to parse config file ' + config_path + str(e)) | 259 raise Exception('Unable to parse config file ' + config_path + str(e)) |
| 244 if not isinstance(config, dict): | 260 if not isinstance(config, dict): |
| 245 raise Exception('config_path must be a JSON file containing a dictionary') | 261 raise Exception('config_path must be a JSON file containing a dictionary') |
| 246 self.files = config.get('files', []) | 262 self.files = config.get('files', []) |
| 247 self.targets = set(config.get('targets', [])) | 263 if config.get('targets'): |
| 264 self.targets = set(config.get('targets')) | |
| 265 self.deprecated_mode = True | |
| 266 else: | |
| 267 self.compile_targets = set(config.get('compile_targets', [])) | |
| 268 self.test_targets = set(config.get('test_targets', [])) | |
| 248 | 269 |
| 249 | 270 |
| 250 def _WasBuildFileModified(build_file, data, files, toplevel_dir): | 271 def _WasBuildFileModified(build_file, data, files, toplevel_dir): |
| 251 """Returns true if the build file |build_file| is either in |files| or | 272 """Returns true if the build file |build_file| is either in |files| or |
| 252 one of the files included by |build_file| is in |files|. |toplevel_dir| is | 273 one of the files included by |build_file| is in |files|. |toplevel_dir| is |
| 253 the root of the source tree.""" | 274 the root of the source tree.""" |
| 254 if _ToLocalPath(toplevel_dir, _ToGypPath(build_file)) in files: | 275 if _ToLocalPath(toplevel_dir, _ToGypPath(build_file)) in files: |
| 255 if debug: | 276 if debug: |
| 256 print 'gyp file modified', build_file | 277 print 'gyp file modified', build_file |
| 257 return True | 278 return True |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 289 return bool(target_dict['type'] != 'none' or | 310 return bool(target_dict['type'] != 'none' or |
| 290 target_dict.get('actions') or target_dict.get('rules')) | 311 target_dict.get('actions') or target_dict.get('rules')) |
| 291 | 312 |
| 292 | 313 |
| 293 def _GenerateTargets(data, target_list, target_dicts, toplevel_dir, files, | 314 def _GenerateTargets(data, target_list, target_dicts, toplevel_dir, files, |
| 294 build_files): | 315 build_files): |
| 295 """Returns a tuple of the following: | 316 """Returns a tuple of the following: |
| 296 . A dictionary mapping from fully qualified name to Target. | 317 . A dictionary mapping from fully qualified name to Target. |
| 297 . A list of the targets that have a source file in |files|. | 318 . A list of the targets that have a source file in |files|. |
| 298 . Set of root Targets reachable from the the files |build_files|. This | 319 . Set of root Targets reachable from the the files |build_files|. This |
| 299 is the set of targets built by the 'all' target. | 320 is the set of targets built by the 'all' target. |
|
Dirk Pranke
2015/11/11 03:51:16
As we discussed, in a sense 'root Targets' is misl
sky
2015/11/11 18:38:10
Agreed.
| |
| 300 This sets the |match_status| of the targets that contain any of the source | 321 This sets the |match_status| of the targets that contain any of the source |
| 301 files in |files| to MATCH_STATUS_MATCHES. | 322 files in |files| to MATCH_STATUS_MATCHES. |
| 302 |toplevel_dir| is the root of the source tree.""" | 323 |toplevel_dir| is the root of the source tree.""" |
| 303 # Maps from target name to Target. | 324 # Maps from target name to Target. |
| 304 targets = {} | 325 targets = {} |
| 305 | 326 |
| 306 # Targets that matched. | 327 # Targets that matched. |
| 307 matching_targets = [] | 328 matching_targets = [] |
| 308 | 329 |
| 309 # Queue of targets to visit. | 330 # Queue of targets to visit. |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 368 if not created_dep_target: | 389 if not created_dep_target: |
| 369 roots.discard(dep_target) | 390 roots.discard(dep_target) |
| 370 | 391 |
| 371 target.deps.add(dep_target) | 392 target.deps.add(dep_target) |
| 372 dep_target.back_deps.add(target) | 393 dep_target.back_deps.add(target) |
| 373 | 394 |
| 374 return targets, matching_targets, roots & build_file_targets | 395 return targets, matching_targets, roots & build_file_targets |
| 375 | 396 |
| 376 | 397 |
| 377 def _GetUnqualifiedToTargetMapping(all_targets, to_find): | 398 def _GetUnqualifiedToTargetMapping(all_targets, to_find): |
| 378 """Returns a mapping (dictionary) from unqualified name to Target for all the | 399 """Returns a tuple of the following: |
| 379 Targets in |to_find|.""" | 400 . mapping (dictionary) from unqualified name to Target for all the |
| 401 Targets in |to_find|. | |
| 402 . any target names not found. If this is empty all targets were found.""" | |
| 380 result = {} | 403 result = {} |
| 381 if not to_find: | 404 if not to_find: |
| 382 return result | 405 return {}, [] |
| 383 to_find = set(to_find) | 406 to_find = set(to_find) |
| 384 for target_name in all_targets.keys(): | 407 for target_name in all_targets.keys(): |
| 385 extracted = gyp.common.ParseQualifiedTarget(target_name) | 408 extracted = gyp.common.ParseQualifiedTarget(target_name) |
| 386 if len(extracted) > 1 and extracted[1] in to_find: | 409 if len(extracted) > 1 and extracted[1] in to_find: |
| 387 to_find.remove(extracted[1]) | 410 to_find.remove(extracted[1]) |
| 388 result[extracted[1]] = all_targets[target_name] | 411 result[extracted[1]] = all_targets[target_name] |
| 389 if not to_find: | 412 if not to_find: |
| 390 return result | 413 return result, [] |
| 391 return result | 414 return result, [x for x in to_find] |
| 392 | 415 |
| 393 | 416 |
| 394 def _AddBuildTargets(target, roots, result): | 417 def _AddBuildTargetsDeprecated(target, roots, result): |
| 395 """Recurses through all targets that depend on |target|, adding all targets | 418 """Recurses through all targets that depend on |target|, adding all targets |
| 396 that need to be built (and are in |roots|) to |result|. | 419 that need to be built (and are in |roots|) to |result|. |
| 397 roots: set of root targets. | 420 roots: set of root targets. |
| 398 result: targets that need to be built are added here.""" | 421 result: targets that need to be built are added here.""" |
| 399 if target.visited: | 422 if target.visited: |
| 400 return | 423 return |
| 401 | 424 |
| 402 target.visited = True | 425 target.visited = True |
| 403 target.in_roots = target in roots | 426 target.in_roots = target in roots |
| 404 | 427 |
| 405 for back_dep_target in target.back_deps: | 428 for back_dep_target in target.back_deps: |
| 406 _AddBuildTargets(back_dep_target, roots, result) | 429 _AddBuildTargetsDeprecated(back_dep_target, roots, result) |
| 407 target.added_to_compile_targets |= back_dep_target.added_to_compile_targets | 430 target.added_to_compile_targets |= back_dep_target.added_to_compile_targets |
| 408 target.in_roots |= back_dep_target.in_roots | 431 target.in_roots |= back_dep_target.in_roots |
| 409 target.is_or_has_linked_ancestor |= ( | 432 target.is_or_has_linked_ancestor |= ( |
| 410 back_dep_target.is_or_has_linked_ancestor) | 433 back_dep_target.is_or_has_linked_ancestor) |
| 411 | 434 |
| 412 # Always add 'executable' targets. Even though they may be built by other | 435 # Always add 'executable' targets. Even though they may be built by other |
| 413 # targets that depend upon them it makes detection of what is going to be | 436 # targets that depend upon them it makes detection of what is going to be |
| 414 # built easier. | 437 # built easier. |
| 415 # And always add static_libraries that have no dependencies on them from | 438 # And always add static_libraries that have no dependencies on them from |
| 416 # linkables. This is necessary as the other dependencies on them may be | 439 # linkables. This is necessary as the other dependencies on them may be |
| 417 # static libraries themselves, which are not compile time dependencies. | 440 # static libraries themselves, which are not compile time dependencies. |
| 418 if target.in_roots and \ | 441 if target.in_roots and \ |
| 419 (target.is_executable or | 442 (target.is_executable or |
| 420 (not target.added_to_compile_targets and target.requires_build) or | 443 (not target.added_to_compile_targets and target.requires_build) or |
| 421 (target.is_static_library and not target.is_or_has_linked_ancestor)): | 444 (target.is_static_library and not target.is_or_has_linked_ancestor)): |
| 422 print '\t\tadding to build targets', target.name, 'executable', \ | 445 print '\t\tadding to build targets', target.name, 'executable', \ |
| 423 target.is_executable, 'added_to_compile_targets', \ | 446 target.is_executable, 'added_to_compile_targets', \ |
| 424 target.added_to_compile_targets, 'requires_build', \ | 447 target.added_to_compile_targets, 'requires_build', \ |
| 425 target.requires_build, 'is_static_library', \ | 448 target.requires_build, 'is_static_library', \ |
| 426 target.is_static_library, 'is_or_has_linked_ancestor', \ | 449 target.is_static_library, 'is_or_has_linked_ancestor', \ |
| 427 target.is_or_has_linked_ancestor | 450 target.is_or_has_linked_ancestor |
| 428 result.add(target) | 451 result.add(target) |
| 429 target.added_to_compile_targets = True | 452 target.added_to_compile_targets = True |
| 430 | 453 |
| 431 | 454 |
| 432 def _GetBuildTargets(matching_targets, roots): | 455 def _GetBuildTargetsDeprecated(matching_targets, roots): |
| 433 """Returns the set of Targets that require a build. | 456 """Returns the set of Targets that require a build. |
| 434 matching_targets: targets that changed and need to be built. | 457 matching_targets: targets that changed and need to be built. |
| 435 roots: set of root targets in the build files to search from.""" | 458 roots: set of root targets in the build files to search from.""" |
| 436 result = set() | 459 result = set() |
| 437 for target in matching_targets: | 460 for target in matching_targets: |
| 438 print '\tfinding build targets for match', target.name | 461 print '\tfinding build targets for match', target.name |
| 439 _AddBuildTargets(target, roots, result) | 462 _AddBuildTargetsDeprecated(target, roots, result) |
| 440 return result | 463 return result |
| 441 | 464 |
| 442 | 465 |
| 466 def _DoesTargetDependOn(target): | |
|
sky
2015/11/10 18:41:31
This function and the next are exactly the same as
| |
| 467 """Returns true if |target| or any of its dependencies matches the supplied | |
| 468 set of paths. This updates |matches| of the Targets as it recurses. | |
|
Dirk Pranke
2015/11/11 03:51:16
"the supplied set of paths" is unclear (to me) her
sky
2015/11/11 18:38:10
I updated the docs and changed names.
As to the d
| |
| 469 target: the Target to look for.""" | |
| 470 if target.match_status == MATCH_STATUS_DOESNT_MATCH: | |
| 471 return False | |
| 472 if target.match_status == MATCH_STATUS_MATCHES or \ | |
| 473 target.match_status == MATCH_STATUS_MATCHES_BY_DEPENDENCY: | |
| 474 return True | |
| 475 for dep in target.deps: | |
| 476 if _DoesTargetDependOn(dep): | |
| 477 target.match_status = MATCH_STATUS_MATCHES_BY_DEPENDENCY | |
| 478 print '\t', target.name, 'matches by dep', dep.name | |
| 479 return True | |
| 480 target.match_status = MATCH_STATUS_DOESNT_MATCH | |
| 481 return False | |
| 482 | |
| 483 | |
| 484 def _GetTargetsDependingOn(possible_targets): | |
|
Dirk Pranke
2015/11/11 03:51:16
See comments above for _DoesTargetDependOn() (as r
| |
| 485 """Returns the list of Targets in |possible_targets| that depend (either | |
| 486 directly on indirectly) on the matched targets. | |
| 487 possible_targets: targets to search from.""" | |
| 488 found = [] | |
| 489 print 'Targets that matched by dependency:' | |
| 490 for target in possible_targets: | |
| 491 if _DoesTargetDependOn(target): | |
| 492 found.append(target) | |
| 493 return found | |
| 494 | |
| 495 | |
| 496 def _AddCompileTargets(target, roots, add_if_no_ancestor, result): | |
|
sky
2015/11/10 18:41:31
And this is _AddBuildTargets from before https://c
| |
| 497 """Recurses through all targets that depend on |target|, adding all targets | |
| 498 that need to be built (and are in |roots|) to |result|. | |
| 499 roots: set of root targets. | |
| 500 add_if_no_ancestor: If true and there are no ancestors of |target| then add | |
| 501 |target| to |result|. |target| must still be in |roots|. | |
| 502 result: targets that need to be built are added here.""" | |
| 503 if target.visited: | |
| 504 return | |
| 505 | |
| 506 target.visited = True | |
| 507 target.in_roots = target in roots | |
| 508 | |
| 509 for back_dep_target in target.back_deps: | |
| 510 _AddCompileTargets(back_dep_target, roots, False, result) | |
| 511 target.added_to_compile_targets |= back_dep_target.added_to_compile_targets | |
| 512 target.in_roots |= back_dep_target.in_roots | |
| 513 target.is_or_has_linked_ancestor |= ( | |
| 514 back_dep_target.is_or_has_linked_ancestor) | |
| 515 | |
| 516 # Always add 'executable' targets. Even though they may be built by other | |
| 517 # targets that depend upon them it makes detection of what is going to be | |
| 518 # built easier. | |
| 519 # And always add static_libraries that have no dependencies on them from | |
| 520 # linkables. This is necessary as the other dependencies on them may be | |
| 521 # static libraries themselves, which are not compile time dependencies. | |
| 522 if target.in_roots and \ | |
| 523 (target.is_executable or | |
| 524 (not target.added_to_compile_targets and | |
| 525 (add_if_no_ancestor or target.requires_build)) or | |
| 526 (target.is_static_library and add_if_no_ancestor and | |
| 527 not target.is_or_has_linked_ancestor)): | |
| 528 print '\t\tadding to compile targets', target.name, 'executable', \ | |
| 529 target.is_executable, 'added_to_compile_targets', \ | |
| 530 target.added_to_compile_targets, 'add_if_no_ancestor', \ | |
| 531 add_if_no_ancestor, 'requires_build', target.requires_build, \ | |
| 532 'is_static_library', target.is_static_library, \ | |
| 533 'is_or_has_linked_ancestor', target.is_or_has_linked_ancestor | |
| 534 result.add(target) | |
| 535 target.added_to_compile_targets = True | |
| 536 | |
| 537 | |
| 538 def _GetCompileTargets(matching_targets, roots): | |
| 539 """Returns the set of Targets that require a build. | |
| 540 matching_targets: targets that changed and need to be built. | |
| 541 roots: set of root targets in the build files to search from.""" | |
|
Dirk Pranke
2015/11/11 03:51:16
calling this 'roots' is also a bit confusing, beca
sky
2015/11/11 18:38:10
Done.
| |
| 542 result = set() | |
| 543 for target in matching_targets: | |
| 544 print 'finding compile targets for match', target.name | |
| 545 _AddCompileTargets(target, roots, True, result) | |
| 546 return result | |
| 547 | |
| 548 | |
| 443 def _WriteOutput(params, **values): | 549 def _WriteOutput(params, **values): |
|
Dirk Pranke
2015/11/11 03:51:16
Nit: it looks like you only ever call this like _W
sky
2015/11/11 18:38:10
There is one place that doesn't. See the last line
| |
| 444 """Writes the output, either to stdout or a file is specified.""" | 550 """Writes the output, either to stdout or a file is specified.""" |
| 445 if 'error' in values: | 551 if 'error' in values: |
| 446 print 'Error:', values['error'] | 552 print 'Error:', values['error'] |
| 447 if 'status' in values: | 553 if 'status' in values: |
| 448 print values['status'] | 554 print values['status'] |
| 449 if 'targets' in values: | 555 if 'targets' in values: |
| 450 values['targets'].sort() | 556 values['targets'].sort() |
| 451 print 'Supplied targets that depend on changed files:' | 557 print 'Supplied targets that depend on changed files:' |
| 452 for target in values['targets']: | 558 for target in values['targets']: |
| 453 print '\t', target | 559 print '\t', target |
| 454 if 'invalid_targets' in values: | 560 if 'invalid_targets' in values: |
| 455 values['invalid_targets'].sort() | 561 values['invalid_targets'].sort() |
| 456 print 'The following targets were not found:' | 562 print 'The following targets were not found:' |
| 457 for target in values['invalid_targets']: | 563 for target in values['invalid_targets']: |
| 458 print '\t', target | 564 print '\t', target |
| 459 if 'build_targets' in values: | 565 if 'build_targets' in values: |
| 460 values['build_targets'].sort() | 566 values['build_targets'].sort() |
| 461 print 'Targets that require a build:' | 567 print 'Targets that require a build:' |
| 462 for target in values['build_targets']: | 568 for target in values['build_targets']: |
| 463 print '\t', target | 569 print '\t', target |
| 570 if 'compile_targets' in values: | |
| 571 values['compile_targets'].sort() | |
| 572 print 'Targets that need to be built:' | |
| 573 for target in values['compile_targets']: | |
| 574 print '\t', target | |
| 575 if 'test_targets' in values: | |
| 576 values['test_targets'].sort() | |
| 577 print 'Test targets:' | |
| 578 for target in values['test_targets']: | |
| 579 print '\t', target | |
| 464 | 580 |
| 465 output_path = params.get('generator_flags', {}).get( | 581 output_path = params.get('generator_flags', {}).get( |
| 466 'analyzer_output_path', None) | 582 'analyzer_output_path', None) |
| 467 if not output_path: | 583 if not output_path: |
| 468 print json.dumps(values) | 584 print json.dumps(values) |
| 469 return | 585 return |
| 470 try: | 586 try: |
| 471 f = open(output_path, 'w') | 587 f = open(output_path, 'w') |
| 472 f.write(json.dumps(values) + '\n') | 588 f.write(json.dumps(values) + '\n') |
| 473 f.close() | 589 f.close() |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 513 'generator_additional_path_sections', []) | 629 'generator_additional_path_sections', []) |
| 514 | 630 |
| 515 gyp.msvs_emulation.CalculateCommonVariables(default_variables, params) | 631 gyp.msvs_emulation.CalculateCommonVariables(default_variables, params) |
| 516 else: | 632 else: |
| 517 operating_system = flavor | 633 operating_system = flavor |
| 518 if flavor == 'android': | 634 if flavor == 'android': |
| 519 operating_system = 'linux' # Keep this legacy behavior for now. | 635 operating_system = 'linux' # Keep this legacy behavior for now. |
| 520 default_variables.setdefault('OS', operating_system) | 636 default_variables.setdefault('OS', operating_system) |
| 521 | 637 |
| 522 | 638 |
| 639 def _GenerateOutputDeprecated(target_list, target_dicts, data, params, config): | |
| 640 """Old deprecated behavior, will be nuked shortly.""" | |
| 641 toplevel_dir = _ToGypPath(os.path.abspath(params['options'].toplevel_dir)) | |
| 642 | |
| 643 if _WasGypIncludeFileModified(params, config.files): | |
| 644 result_dict = { 'status': all_changed_string, | |
| 645 'targets': list(config.targets) } | |
|
Dirk Pranke
2015/11/11 03:51:16
this is probably a nit, since this is the way the
sky
2015/11/11 18:38:10
I believe the recipe code ignores the targets if a
| |
| 646 _WriteOutput(params, **result_dict) | |
| 647 return | |
| 648 | |
| 649 all_targets, matching_targets, root_targets = _GenerateTargets( | |
| 650 data, target_list, target_dicts, toplevel_dir, frozenset(config.files), | |
| 651 params['build_files']) | |
| 652 | |
| 653 unqualified_mapping, invalid_targets = _GetUnqualifiedToTargetMapping( | |
| 654 all_targets, config.targets) | |
| 655 | |
| 656 if matching_targets: | |
| 657 search_targets = _LookupTargets(config.targets, unqualified_mapping) | |
| 658 print 'supplied targets' | |
| 659 for target in config.targets: | |
| 660 print '\t', target | |
| 661 print 'expanded supplied targets' | |
| 662 for target in search_targets: | |
| 663 print '\t', target.name | |
| 664 # Reset the visited status for _GetBuildTargets. | |
| 665 for target in all_targets.itervalues(): | |
| 666 target.visited = False | |
| 667 build_targets = _GetBuildTargetsDeprecated(matching_targets, search_targets) | |
| 668 build_targets = [gyp.common.ParseQualifiedTarget(target.name)[1] | |
| 669 for target in build_targets] | |
| 670 else: | |
| 671 build_targets = [] | |
| 672 | |
| 673 result_dict = { 'targets': build_targets, | |
| 674 'status': found_dependency_string if matching_targets else | |
| 675 no_dependency_string, | |
| 676 'build_targets': build_targets} | |
| 677 if invalid_targets: | |
| 678 result_dict['invalid_targets'] = invalid_targets | |
| 679 _WriteOutput(params, **result_dict) | |
| 680 | |
| 681 | |
| 523 def GenerateOutput(target_list, target_dicts, data, params): | 682 def GenerateOutput(target_list, target_dicts, data, params): |
| 524 """Called by gyp as the final stage. Outputs results.""" | 683 """Called by gyp as the final stage. Outputs results.""" |
| 525 config = Config() | 684 config = Config() |
| 526 try: | 685 try: |
| 527 config.Init(params) | 686 config.Init(params) |
| 687 | |
| 528 if not config.files: | 688 if not config.files: |
| 529 raise Exception('Must specify files to analyze via config_path generator ' | 689 raise Exception('Must specify files to analyze via config_path generator ' |
| 530 'flag') | 690 'flag') |
| 531 | 691 |
| 692 if config.deprecated_mode: | |
| 693 _GenerateOutputDeprecated(target_list, target_dicts, data, params, | |
| 694 config) | |
| 695 return | |
| 696 | |
| 532 toplevel_dir = _ToGypPath(os.path.abspath(params['options'].toplevel_dir)) | 697 toplevel_dir = _ToGypPath(os.path.abspath(params['options'].toplevel_dir)) |
| 533 if debug: | 698 if debug: |
| 534 print 'toplevel_dir', toplevel_dir | 699 print 'toplevel_dir', toplevel_dir |
| 535 | 700 |
| 536 if _WasGypIncludeFileModified(params, config.files): | 701 if _WasGypIncludeFileModified(params, config.files): |
| 537 result_dict = { 'status': all_changed_string, | 702 result_dict = { 'status': all_changed_string, |
| 538 'targets': list(config.targets) } | 703 'test_targets': list(config.test_targets), |
| 704 'compile_targets': list(config.compile_targets) } | |
| 539 _WriteOutput(params, **result_dict) | 705 _WriteOutput(params, **result_dict) |
| 540 return | 706 return |
| 541 | 707 |
|
Dirk Pranke
2015/11/11 03:51:16
General comments on the rest of this function:
It
sky
2015/11/11 18:38:10
I moved all of this off into a class. Hopefully it
| |
| 542 all_targets, matching_targets, _ = _GenerateTargets( | 708 all_targets, changed_targets, root_targets = _GenerateTargets( |
|
Dirk Pranke
2015/11/11 03:51:16
'changed_targets' is the list of targets *directly
| |
| 543 data, target_list, target_dicts, toplevel_dir, frozenset(config.files), | 709 data, target_list, target_dicts, toplevel_dir, frozenset(config.files), |
| 544 params['build_files']) | 710 params['build_files']) |
| 545 | 711 |
| 546 unqualified_mapping = _GetUnqualifiedToTargetMapping(all_targets, | 712 supplied_target_names = config.compile_targets | config.test_targets |
|
Dirk Pranke
2015/11/11 03:51:16
We discussed this earlier (as to how this was safe
| |
| 547 config.targets) | 713 # 'all' is added back below. |
| 548 invalid_targets = None | 714 supplied_targets_contains_all = 'all' in supplied_target_names |
| 549 if len(unqualified_mapping) != len(config.targets): | 715 supplied_target_names.discard('all') |
| 550 invalid_targets = _NamesNotIn(config.targets, unqualified_mapping) | 716 unqualified_mapping, invalid_targets = _GetUnqualifiedToTargetMapping( |
| 717 all_targets, supplied_target_names) | |
| 551 | 718 |
| 552 if matching_targets: | 719 if changed_targets: |
| 553 search_targets = _LookupTargets(config.targets, unqualified_mapping) | 720 # Find the test targets first. 'all' is special cased to mean all the |
| 554 print 'supplied targets' | 721 # root targets. To deal with all the supplied |test_targets| are expanded |
| 555 for target in config.targets: | 722 # to include the root targets during lookup. If any of the root targets |
| 556 print '\t', target | 723 # match, we remove it and replace it with 'all'. |
|
Dirk Pranke
2015/11/11 03:51:16
Same concerns about 'all' and 'root targets' here
| |
| 557 print 'expanded supplied targets' | 724 test_target_names = set(config.test_targets) |
| 558 for target in search_targets: | 725 test_target_names_contains_all = 'all' in test_target_names |
| 726 test_target_names.discard('all') | |
| 727 test_targets = _LookupTargets(test_target_names, unqualified_mapping) | |
| 728 original_test_targets = set(test_targets) | |
| 729 if test_target_names_contains_all: | |
| 730 test_targets = [x for x in (set(test_targets) | set(root_targets))] | |
|
Dirk Pranke
2015/11/11 03:51:16
Rewrite as
test_targets = list(set(test_targets)
| |
| 731 print 'supplied test_targets' | |
| 732 for target_name in config.test_targets: | |
| 733 print '\t', target_name | |
| 734 print 'found test_targets' | |
| 735 for target in test_targets: | |
| 559 print '\t', target.name | 736 print '\t', target.name |
| 737 print 'searching for matching test targets' | |
| 738 test_targets = _GetTargetsDependingOn(test_targets) | |
|
Dirk Pranke
2015/11/11 03:51:16
maybe instead something like:
affected_test_targe
| |
| 739 test_targets_contains_all = (test_target_names_contains_all and | |
| 740 set(test_targets) & set(root_targets)) | |
|
Dirk Pranke
2015/11/11 03:51:16
and then rewriting this as something like:
affe
| |
| 741 if test_targets_contains_all: | |
| 742 # Remove any of the targets for all that were not explicitly supplied, | |
| 743 # 'all' is subsequentely added to the matching names below. | |
| 744 test_targets = [x for x in (set(test_targets) & | |
| 745 set(original_test_targets))] | |
|
Dirk Pranke
2015/11/11 03:51:16
affected_test_targets = list(set(affected_test_tar
| |
| 746 | |
| 747 print 'matched test_targets' | |
| 748 for target in test_targets: | |
| 749 print '\t', target.name | |
| 750 test_target_names = [gyp.common.ParseQualifiedTarget(target.name)[1] | |
| 751 for target in test_targets] | |
| 752 if test_targets_contains_all: | |
| 753 test_target_names.append('all') | |
| 754 print '\tall' | |
| 755 | |
| 756 # Compile targets are found by searching up from changed targets. | |
| 560 # Reset the visited status for _GetBuildTargets. | 757 # Reset the visited status for _GetBuildTargets. |
| 561 for target in all_targets.itervalues(): | 758 for target in all_targets.itervalues(): |
| 562 target.visited = False | 759 target.visited = False |
| 563 print 'Finding build targets' | 760 |
| 564 build_targets = _GetBuildTargets(matching_targets, search_targets) | 761 supplied_targets = _LookupTargets(supplied_target_names, |
|
Dirk Pranke
2015/11/11 03:51:16
see comments above re: supplied_target_names being
| |
| 565 build_targets = [gyp.common.ParseQualifiedTarget(target.name)[1] | 762 unqualified_mapping) |
| 566 for target in build_targets] | 763 if supplied_targets_contains_all: |
| 764 supplied_targets = [x for x in (set(supplied_targets) | | |
| 765 set(root_targets))] | |
| 766 print 'Supplied test_targets & compile_targets' | |
| 767 for target in supplied_targets: | |
| 768 print '\t', target.name | |
| 769 print 'Finding compile targets' | |
| 770 compile_targets = _GetCompileTargets(changed_targets, supplied_targets) | |
| 771 compile_target_names = [gyp.common.ParseQualifiedTarget(target.name)[1] | |
| 772 for target in compile_targets] | |
| 567 else: | 773 else: |
| 568 build_targets = [] | 774 compile_target_names = [] |
| 775 test_target_names = [] | |
| 569 | 776 |
| 570 # TODO(sky): nuke 'targets'. | 777 found_at_least_one_target = compile_target_names or test_target_names |
| 571 result_dict = { 'targets': build_targets, | 778 result_dict = { 'test_targets': test_target_names, |
| 572 'status': found_dependency_string if matching_targets else | 779 'status': found_dependency_string if |
| 573 no_dependency_string, | 780 found_at_least_one_target else no_dependency_string, |
| 574 'build_targets': build_targets} | 781 'compile_targets': compile_target_names} |
| 575 if invalid_targets: | 782 if invalid_targets: |
| 576 result_dict['invalid_targets'] = invalid_targets | 783 result_dict['invalid_targets'] = invalid_targets |
|
Dirk Pranke
2015/11/11 03:51:16
Looks like you *don't* return an error if there ar
| |
| 577 _WriteOutput(params, **result_dict) | 784 _WriteOutput(params, **result_dict) |
| 578 | 785 |
| 579 except Exception as e: | 786 except Exception as e: |
| 580 _WriteOutput(params, error=str(e)) | 787 _WriteOutput(params, error=str(e)) |
| OLD | NEW |