| 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 targets: list of targets to search for. The target names are unqualified. |
| (...skipping 256 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 267 if _ToLocalPath(toplevel_dir, rel_include_file) in files: | 267 if _ToLocalPath(toplevel_dir, rel_include_file) in files: |
| 268 if debug: | 268 if debug: |
| 269 print 'included gyp file modified, gyp_file=', build_file, \ | 269 print 'included gyp file modified, gyp_file=', build_file, \ |
| 270 'included file=', rel_include_file | 270 'included file=', rel_include_file |
| 271 return True | 271 return True |
| 272 return False | 272 return False |
| 273 | 273 |
| 274 | 274 |
| 275 def _GetOrCreateTargetByName(targets, target_name): | 275 def _GetOrCreateTargetByName(targets, target_name): |
| 276 """Creates or returns the Target at targets[target_name]. If there is no | 276 """Creates or returns the Target at targets[target_name]. If there is no |
| 277 Target for |target_name| one is created.""" | 277 Target for |target_name| one is created. Returns a tuple of whether a new |
| 278 Target was created and the Target.""" |
| 278 if target_name in targets: | 279 if target_name in targets: |
| 279 return targets[target_name] | 280 return False, targets[target_name] |
| 280 target = Target(target_name) | 281 target = Target(target_name) |
| 281 targets[target_name] = target | 282 targets[target_name] = target |
| 282 return target | 283 return True, target |
| 283 | 284 |
| 284 | 285 |
| 285 def _DoesTargetTypeRequireBuild(target_dict): | 286 def _DoesTargetTypeRequireBuild(target_dict): |
| 286 """Returns true if the target type is such that it needs to be built.""" | 287 """Returns true if the target type is such that it needs to be built.""" |
| 287 # If a 'none' target has rules or actions we assume it requires a build. | 288 # If a 'none' target has rules or actions we assume it requires a build. |
| 288 return bool(target_dict['type'] != 'none' or | 289 return bool(target_dict['type'] != 'none' or |
| 289 target_dict.get('actions') or target_dict.get('rules')) | 290 target_dict.get('actions') or target_dict.get('rules')) |
| 290 | 291 |
| 291 | 292 |
| 292 def _GenerateTargets(data, target_list, target_dicts, toplevel_dir, files, | 293 def _GenerateTargets(data, target_list, target_dicts, toplevel_dir, files, |
| 293 build_files): | 294 build_files): |
| 294 """Returns a tuple of the following: | 295 """Returns a tuple of the following: |
| 295 . A dictionary mapping from fully qualified name to Target. | 296 . A dictionary mapping from fully qualified name to Target. |
| 296 . A list of the targets that have a source file in |files|. | 297 . 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 |
| 299 is the set of targets built by the 'all' target. |
| 297 This sets the |match_status| of the targets that contain any of the source | 300 This sets the |match_status| of the targets that contain any of the source |
| 298 files in |files| to MATCH_STATUS_MATCHES. | 301 files in |files| to MATCH_STATUS_MATCHES. |
| 299 |toplevel_dir| is the root of the source tree.""" | 302 |toplevel_dir| is the root of the source tree.""" |
| 300 # Maps from target name to Target. | 303 # Maps from target name to Target. |
| 301 targets = {} | 304 targets = {} |
| 302 | 305 |
| 303 # Targets that matched. | 306 # Targets that matched. |
| 304 matching_targets = [] | 307 matching_targets = [] |
| 305 | 308 |
| 306 # Queue of targets to visit. | 309 # Queue of targets to visit. |
| 307 targets_to_visit = target_list[:] | 310 targets_to_visit = target_list[:] |
| 308 | 311 |
| 309 # Maps from build file to a boolean indicating whether the build file is in | 312 # Maps from build file to a boolean indicating whether the build file is in |
| 310 # |files|. | 313 # |files|. |
| 311 build_file_in_files = {} | 314 build_file_in_files = {} |
| 312 | 315 |
| 316 # Root targets across all files. |
| 317 roots = set() |
| 318 |
| 319 # Set of Targets in |build_files|. |
| 320 build_file_targets = set() |
| 321 |
| 313 while len(targets_to_visit) > 0: | 322 while len(targets_to_visit) > 0: |
| 314 target_name = targets_to_visit.pop() | 323 target_name = targets_to_visit.pop() |
| 315 target = _GetOrCreateTargetByName(targets, target_name) | 324 created_target, target = _GetOrCreateTargetByName(targets, target_name) |
| 316 if target.visited: | 325 if created_target: |
| 326 roots.add(target) |
| 327 elif target.visited: |
| 317 continue | 328 continue |
| 318 | 329 |
| 319 target.visited = True | 330 target.visited = True |
| 320 target.requires_build = _DoesTargetTypeRequireBuild( | 331 target.requires_build = _DoesTargetTypeRequireBuild( |
| 321 target_dicts[target_name]) | 332 target_dicts[target_name]) |
| 322 target_type = target_dicts[target_name]['type'] | 333 target_type = target_dicts[target_name]['type'] |
| 323 target.is_executable = target_type == 'executable' | 334 target.is_executable = target_type == 'executable' |
| 324 target.is_static_library = target_type == 'static_library' | 335 target.is_static_library = target_type == 'static_library' |
| 325 target.is_or_has_linked_ancestor = (target_type == 'executable' or | 336 target.is_or_has_linked_ancestor = (target_type == 'executable' or |
| 326 target_type == 'shared_library') | 337 target_type == 'shared_library') |
| 327 | 338 |
| 328 build_file = gyp.common.ParseQualifiedTarget(target_name)[0] | 339 build_file = gyp.common.ParseQualifiedTarget(target_name)[0] |
| 329 if not build_file in build_file_in_files: | 340 if not build_file in build_file_in_files: |
| 330 build_file_in_files[build_file] = \ | 341 build_file_in_files[build_file] = \ |
| 331 _WasBuildFileModified(build_file, data, files, toplevel_dir) | 342 _WasBuildFileModified(build_file, data, files, toplevel_dir) |
| 332 | 343 |
| 344 if build_file in build_files: |
| 345 build_file_targets.add(target) |
| 346 |
| 333 # If a build file (or any of its included files) is modified we assume all | 347 # If a build file (or any of its included files) is modified we assume all |
| 334 # targets in the file are modified. | 348 # targets in the file are modified. |
| 335 if build_file_in_files[build_file]: | 349 if build_file_in_files[build_file]: |
| 336 print 'matching target from modified build file', target_name | 350 print 'matching target from modified build file', target_name |
| 337 target.match_status = MATCH_STATUS_MATCHES | 351 target.match_status = MATCH_STATUS_MATCHES |
| 338 matching_targets.append(target) | 352 matching_targets.append(target) |
| 339 else: | 353 else: |
| 340 sources = _ExtractSources(target_name, target_dicts[target_name], | 354 sources = _ExtractSources(target_name, target_dicts[target_name], |
| 341 toplevel_dir) | 355 toplevel_dir) |
| 342 for source in sources: | 356 for source in sources: |
| 343 if _ToGypPath(os.path.normpath(source)) in files: | 357 if _ToGypPath(os.path.normpath(source)) in files: |
| 344 print 'target', target_name, 'matches', source | 358 print 'target', target_name, 'matches', source |
| 345 target.match_status = MATCH_STATUS_MATCHES | 359 target.match_status = MATCH_STATUS_MATCHES |
| 346 matching_targets.append(target) | 360 matching_targets.append(target) |
| 347 break | 361 break |
| 348 | 362 |
| 349 # Add dependencies to visit as well as updating back pointers for deps. | 363 # Add dependencies to visit as well as updating back pointers for deps. |
| 350 for dep in target_dicts[target_name].get('dependencies', []): | 364 for dep in target_dicts[target_name].get('dependencies', []): |
| 351 targets_to_visit.append(dep) | 365 targets_to_visit.append(dep) |
| 352 | 366 |
| 353 dep_target = _GetOrCreateTargetByName(targets, dep) | 367 created_dep_target, dep_target = _GetOrCreateTargetByName(targets, dep) |
| 368 if not created_dep_target: |
| 369 roots.discard(dep_target) |
| 354 | 370 |
| 355 target.deps.add(dep_target) | 371 target.deps.add(dep_target) |
| 356 dep_target.back_deps.add(target) | 372 dep_target.back_deps.add(target) |
| 357 | 373 |
| 358 return targets, matching_targets | 374 return targets, matching_targets, roots & build_file_targets |
| 359 | 375 |
| 360 | 376 |
| 361 def _GetUnqualifiedToTargetMapping(all_targets, to_find): | 377 def _GetUnqualifiedToTargetMapping(all_targets, to_find): |
| 362 """Returns a mapping (dictionary) from unqualified name to Target for all the | 378 """Returns a mapping (dictionary) from unqualified name to Target for all the |
| 363 Targets in |to_find|.""" | 379 Targets in |to_find|.""" |
| 364 result = {} | 380 result = {} |
| 365 if not to_find: | 381 if not to_find: |
| 366 return result | 382 return result |
| 367 to_find = set(to_find) | 383 to_find = set(to_find) |
| 368 for target_name in all_targets.keys(): | 384 for target_name in all_targets.keys(): |
| (...skipping 147 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 516 toplevel_dir = _ToGypPath(os.path.abspath(params['options'].toplevel_dir)) | 532 toplevel_dir = _ToGypPath(os.path.abspath(params['options'].toplevel_dir)) |
| 517 if debug: | 533 if debug: |
| 518 print 'toplevel_dir', toplevel_dir | 534 print 'toplevel_dir', toplevel_dir |
| 519 | 535 |
| 520 if _WasGypIncludeFileModified(params, config.files): | 536 if _WasGypIncludeFileModified(params, config.files): |
| 521 result_dict = { 'status': all_changed_string, | 537 result_dict = { 'status': all_changed_string, |
| 522 'targets': list(config.targets) } | 538 'targets': list(config.targets) } |
| 523 _WriteOutput(params, **result_dict) | 539 _WriteOutput(params, **result_dict) |
| 524 return | 540 return |
| 525 | 541 |
| 526 all_targets, matching_targets = _GenerateTargets( | 542 all_targets, matching_targets, _ = _GenerateTargets( |
| 527 data, target_list, target_dicts, toplevel_dir, frozenset(config.files), | 543 data, target_list, target_dicts, toplevel_dir, frozenset(config.files), |
| 528 params['build_files']) | 544 params['build_files']) |
| 529 | 545 |
| 530 unqualified_mapping = _GetUnqualifiedToTargetMapping(all_targets, | 546 unqualified_mapping = _GetUnqualifiedToTargetMapping(all_targets, |
| 531 config.targets) | 547 config.targets) |
| 532 invalid_targets = None | 548 invalid_targets = None |
| 533 if len(unqualified_mapping) != len(config.targets): | 549 if len(unqualified_mapping) != len(config.targets): |
| 534 invalid_targets = _NamesNotIn(config.targets, unqualified_mapping) | 550 invalid_targets = _NamesNotIn(config.targets, unqualified_mapping) |
| 535 | 551 |
| 536 if matching_targets: | 552 if matching_targets: |
| (...skipping 18 matching lines...) Expand all Loading... |
| 555 result_dict = { 'targets': build_targets, | 571 result_dict = { 'targets': build_targets, |
| 556 'status': found_dependency_string if matching_targets else | 572 'status': found_dependency_string if matching_targets else |
| 557 no_dependency_string, | 573 no_dependency_string, |
| 558 'build_targets': build_targets} | 574 'build_targets': build_targets} |
| 559 if invalid_targets: | 575 if invalid_targets: |
| 560 result_dict['invalid_targets'] = invalid_targets | 576 result_dict['invalid_targets'] = invalid_targets |
| 561 _WriteOutput(params, **result_dict) | 577 _WriteOutput(params, **result_dict) |
| 562 | 578 |
| 563 except Exception as e: | 579 except Exception as e: |
| 564 _WriteOutput(params, error=str(e)) | 580 _WriteOutput(params, error=str(e)) |
| OLD | NEW |