11cb0ef41Sopenharmony_ci# Copyright (c) 2014 Google Inc. All rights reserved. 21cb0ef41Sopenharmony_ci# Use of this source code is governed by a BSD-style license that can be 31cb0ef41Sopenharmony_ci# found in the LICENSE file. 41cb0ef41Sopenharmony_ci 51cb0ef41Sopenharmony_ci""" 61cb0ef41Sopenharmony_ciThis script is intended for use as a GYP_GENERATOR. It takes as input (by way of 71cb0ef41Sopenharmony_cithe generator flag config_path) the path of a json file that dictates the files 81cb0ef41Sopenharmony_ciand targets to search for. The following keys are supported: 91cb0ef41Sopenharmony_cifiles: list of paths (relative) of the files to search for. 101cb0ef41Sopenharmony_citest_targets: unqualified target names to search for. Any target in this list 111cb0ef41Sopenharmony_cithat depends upon a file in |files| is output regardless of the type of target 121cb0ef41Sopenharmony_cior chain of dependencies. 131cb0ef41Sopenharmony_ciadditional_compile_targets: Unqualified targets to search for in addition to 141cb0ef41Sopenharmony_citest_targets. Targets in the combined list that depend upon a file in |files| 151cb0ef41Sopenharmony_ciare not necessarily output. For example, if the target is of type none then the 161cb0ef41Sopenharmony_citarget is not output (but one of the descendants of the target will be). 171cb0ef41Sopenharmony_ci 181cb0ef41Sopenharmony_ciThe following is output: 191cb0ef41Sopenharmony_cierror: only supplied if there is an error. 201cb0ef41Sopenharmony_cicompile_targets: minimal set of targets that directly or indirectly (for 211cb0ef41Sopenharmony_ci targets of type none) depend on the files in |files| and is one of the 221cb0ef41Sopenharmony_ci supplied targets or a target that one of the supplied targets depends on. 231cb0ef41Sopenharmony_ci The expectation is this set of targets is passed into a build step. This list 241cb0ef41Sopenharmony_ci always contains the output of test_targets as well. 251cb0ef41Sopenharmony_citest_targets: set of targets from the supplied |test_targets| that either 261cb0ef41Sopenharmony_ci directly or indirectly depend upon a file in |files|. This list if useful 271cb0ef41Sopenharmony_ci if additional processing needs to be done for certain targets after the 281cb0ef41Sopenharmony_ci build, such as running tests. 291cb0ef41Sopenharmony_cistatus: outputs one of three values: none of the supplied files were found, 301cb0ef41Sopenharmony_ci one of the include files changed so that it should be assumed everything 311cb0ef41Sopenharmony_ci changed (in this case test_targets and compile_targets are not output) or at 321cb0ef41Sopenharmony_ci least one file was found. 331cb0ef41Sopenharmony_ciinvalid_targets: list of supplied targets that were not found. 341cb0ef41Sopenharmony_ci 351cb0ef41Sopenharmony_ciExample: 361cb0ef41Sopenharmony_ciConsider a graph like the following: 371cb0ef41Sopenharmony_ci A D 381cb0ef41Sopenharmony_ci / \ 391cb0ef41Sopenharmony_ciB C 401cb0ef41Sopenharmony_ciA depends upon both B and C, A is of type none and B and C are executables. 411cb0ef41Sopenharmony_ciD is an executable, has no dependencies and nothing depends on it. 421cb0ef41Sopenharmony_ciIf |additional_compile_targets| = ["A"], |test_targets| = ["B", "C"] and 431cb0ef41Sopenharmony_cifiles = ["b.cc", "d.cc"] (B depends upon b.cc and D depends upon d.cc), then 441cb0ef41Sopenharmony_cithe following is output: 451cb0ef41Sopenharmony_ci|compile_targets| = ["B"] B must built as it depends upon the changed file b.cc 461cb0ef41Sopenharmony_ciand the supplied target A depends upon it. A is not output as a build_target 471cb0ef41Sopenharmony_cias it is of type none with no rules and actions. 481cb0ef41Sopenharmony_ci|test_targets| = ["B"] B directly depends upon the change file b.cc. 491cb0ef41Sopenharmony_ci 501cb0ef41Sopenharmony_ciEven though the file d.cc, which D depends upon, has changed D is not output 511cb0ef41Sopenharmony_cias it was not supplied by way of |additional_compile_targets| or |test_targets|. 521cb0ef41Sopenharmony_ci 531cb0ef41Sopenharmony_ciIf the generator flag analyzer_output_path is specified, output is written 541cb0ef41Sopenharmony_cithere. Otherwise output is written to stdout. 551cb0ef41Sopenharmony_ci 561cb0ef41Sopenharmony_ciIn Gyp the "all" target is shorthand for the root targets in the files passed 571cb0ef41Sopenharmony_cito gyp. For example, if file "a.gyp" contains targets "a1" and 581cb0ef41Sopenharmony_ci"a2", and file "b.gyp" contains targets "b1" and "b2" and "a2" has a dependency 591cb0ef41Sopenharmony_cion "b2" and gyp is supplied "a.gyp" then "all" consists of "a1" and "a2". 601cb0ef41Sopenharmony_ciNotice that "b1" and "b2" are not in the "all" target as "b.gyp" was not 611cb0ef41Sopenharmony_cidirectly supplied to gyp. OTOH if both "a.gyp" and "b.gyp" are supplied to gyp 621cb0ef41Sopenharmony_cithen the "all" target includes "b1" and "b2". 631cb0ef41Sopenharmony_ci""" 641cb0ef41Sopenharmony_ci 651cb0ef41Sopenharmony_ci 661cb0ef41Sopenharmony_ciimport gyp.common 671cb0ef41Sopenharmony_ciimport json 681cb0ef41Sopenharmony_ciimport os 691cb0ef41Sopenharmony_ciimport posixpath 701cb0ef41Sopenharmony_ci 711cb0ef41Sopenharmony_cidebug = False 721cb0ef41Sopenharmony_ci 731cb0ef41Sopenharmony_cifound_dependency_string = "Found dependency" 741cb0ef41Sopenharmony_cino_dependency_string = "No dependencies" 751cb0ef41Sopenharmony_ci# Status when it should be assumed that everything has changed. 761cb0ef41Sopenharmony_ciall_changed_string = "Found dependency (all)" 771cb0ef41Sopenharmony_ci 781cb0ef41Sopenharmony_ci# MatchStatus is used indicate if and how a target depends upon the supplied 791cb0ef41Sopenharmony_ci# sources. 801cb0ef41Sopenharmony_ci# The target's sources contain one of the supplied paths. 811cb0ef41Sopenharmony_ciMATCH_STATUS_MATCHES = 1 821cb0ef41Sopenharmony_ci# The target has a dependency on another target that contains one of the 831cb0ef41Sopenharmony_ci# supplied paths. 841cb0ef41Sopenharmony_ciMATCH_STATUS_MATCHES_BY_DEPENDENCY = 2 851cb0ef41Sopenharmony_ci# The target's sources weren't in the supplied paths and none of the target's 861cb0ef41Sopenharmony_ci# dependencies depend upon a target that matched. 871cb0ef41Sopenharmony_ciMATCH_STATUS_DOESNT_MATCH = 3 881cb0ef41Sopenharmony_ci# The target doesn't contain the source, but the dependent targets have not yet 891cb0ef41Sopenharmony_ci# been visited to determine a more specific status yet. 901cb0ef41Sopenharmony_ciMATCH_STATUS_TBD = 4 911cb0ef41Sopenharmony_ci 921cb0ef41Sopenharmony_cigenerator_supports_multiple_toolsets = gyp.common.CrossCompileRequested() 931cb0ef41Sopenharmony_ci 941cb0ef41Sopenharmony_cigenerator_wants_static_library_dependencies_adjusted = False 951cb0ef41Sopenharmony_ci 961cb0ef41Sopenharmony_cigenerator_default_variables = {} 971cb0ef41Sopenharmony_cifor dirname in [ 981cb0ef41Sopenharmony_ci "INTERMEDIATE_DIR", 991cb0ef41Sopenharmony_ci "SHARED_INTERMEDIATE_DIR", 1001cb0ef41Sopenharmony_ci "PRODUCT_DIR", 1011cb0ef41Sopenharmony_ci "LIB_DIR", 1021cb0ef41Sopenharmony_ci "SHARED_LIB_DIR", 1031cb0ef41Sopenharmony_ci]: 1041cb0ef41Sopenharmony_ci generator_default_variables[dirname] = "!!!" 1051cb0ef41Sopenharmony_ci 1061cb0ef41Sopenharmony_cifor unused in [ 1071cb0ef41Sopenharmony_ci "RULE_INPUT_PATH", 1081cb0ef41Sopenharmony_ci "RULE_INPUT_ROOT", 1091cb0ef41Sopenharmony_ci "RULE_INPUT_NAME", 1101cb0ef41Sopenharmony_ci "RULE_INPUT_DIRNAME", 1111cb0ef41Sopenharmony_ci "RULE_INPUT_EXT", 1121cb0ef41Sopenharmony_ci "EXECUTABLE_PREFIX", 1131cb0ef41Sopenharmony_ci "EXECUTABLE_SUFFIX", 1141cb0ef41Sopenharmony_ci "STATIC_LIB_PREFIX", 1151cb0ef41Sopenharmony_ci "STATIC_LIB_SUFFIX", 1161cb0ef41Sopenharmony_ci "SHARED_LIB_PREFIX", 1171cb0ef41Sopenharmony_ci "SHARED_LIB_SUFFIX", 1181cb0ef41Sopenharmony_ci "CONFIGURATION_NAME", 1191cb0ef41Sopenharmony_ci]: 1201cb0ef41Sopenharmony_ci generator_default_variables[unused] = "" 1211cb0ef41Sopenharmony_ci 1221cb0ef41Sopenharmony_ci 1231cb0ef41Sopenharmony_cidef _ToGypPath(path): 1241cb0ef41Sopenharmony_ci """Converts a path to the format used by gyp.""" 1251cb0ef41Sopenharmony_ci if os.sep == "\\" and os.altsep == "/": 1261cb0ef41Sopenharmony_ci return path.replace("\\", "/") 1271cb0ef41Sopenharmony_ci return path 1281cb0ef41Sopenharmony_ci 1291cb0ef41Sopenharmony_ci 1301cb0ef41Sopenharmony_cidef _ResolveParent(path, base_path_components): 1311cb0ef41Sopenharmony_ci """Resolves |path|, which starts with at least one '../'. Returns an empty 1321cb0ef41Sopenharmony_ci string if the path shouldn't be considered. See _AddSources() for a 1331cb0ef41Sopenharmony_ci description of |base_path_components|.""" 1341cb0ef41Sopenharmony_ci depth = 0 1351cb0ef41Sopenharmony_ci while path.startswith("../"): 1361cb0ef41Sopenharmony_ci depth += 1 1371cb0ef41Sopenharmony_ci path = path[3:] 1381cb0ef41Sopenharmony_ci # Relative includes may go outside the source tree. For example, an action may 1391cb0ef41Sopenharmony_ci # have inputs in /usr/include, which are not in the source tree. 1401cb0ef41Sopenharmony_ci if depth > len(base_path_components): 1411cb0ef41Sopenharmony_ci return "" 1421cb0ef41Sopenharmony_ci if depth == len(base_path_components): 1431cb0ef41Sopenharmony_ci return path 1441cb0ef41Sopenharmony_ci return ( 1451cb0ef41Sopenharmony_ci "/".join(base_path_components[0 : len(base_path_components) - depth]) 1461cb0ef41Sopenharmony_ci + "/" 1471cb0ef41Sopenharmony_ci + path 1481cb0ef41Sopenharmony_ci ) 1491cb0ef41Sopenharmony_ci 1501cb0ef41Sopenharmony_ci 1511cb0ef41Sopenharmony_cidef _AddSources(sources, base_path, base_path_components, result): 1521cb0ef41Sopenharmony_ci """Extracts valid sources from |sources| and adds them to |result|. Each 1531cb0ef41Sopenharmony_ci source file is relative to |base_path|, but may contain '..'. To make 1541cb0ef41Sopenharmony_ci resolving '..' easier |base_path_components| contains each of the 1551cb0ef41Sopenharmony_ci directories in |base_path|. Additionally each source may contain variables. 1561cb0ef41Sopenharmony_ci Such sources are ignored as it is assumed dependencies on them are expressed 1571cb0ef41Sopenharmony_ci and tracked in some other means.""" 1581cb0ef41Sopenharmony_ci # NOTE: gyp paths are always posix style. 1591cb0ef41Sopenharmony_ci for source in sources: 1601cb0ef41Sopenharmony_ci if not len(source) or source.startswith("!!!") or source.startswith("$"): 1611cb0ef41Sopenharmony_ci continue 1621cb0ef41Sopenharmony_ci # variable expansion may lead to //. 1631cb0ef41Sopenharmony_ci org_source = source 1641cb0ef41Sopenharmony_ci source = source[0] + source[1:].replace("//", "/") 1651cb0ef41Sopenharmony_ci if source.startswith("../"): 1661cb0ef41Sopenharmony_ci source = _ResolveParent(source, base_path_components) 1671cb0ef41Sopenharmony_ci if len(source): 1681cb0ef41Sopenharmony_ci result.append(source) 1691cb0ef41Sopenharmony_ci continue 1701cb0ef41Sopenharmony_ci result.append(base_path + source) 1711cb0ef41Sopenharmony_ci if debug: 1721cb0ef41Sopenharmony_ci print("AddSource", org_source, result[len(result) - 1]) 1731cb0ef41Sopenharmony_ci 1741cb0ef41Sopenharmony_ci 1751cb0ef41Sopenharmony_cidef _ExtractSourcesFromAction(action, base_path, base_path_components, results): 1761cb0ef41Sopenharmony_ci if "inputs" in action: 1771cb0ef41Sopenharmony_ci _AddSources(action["inputs"], base_path, base_path_components, results) 1781cb0ef41Sopenharmony_ci 1791cb0ef41Sopenharmony_ci 1801cb0ef41Sopenharmony_cidef _ToLocalPath(toplevel_dir, path): 1811cb0ef41Sopenharmony_ci """Converts |path| to a path relative to |toplevel_dir|.""" 1821cb0ef41Sopenharmony_ci if path == toplevel_dir: 1831cb0ef41Sopenharmony_ci return "" 1841cb0ef41Sopenharmony_ci if path.startswith(toplevel_dir + "/"): 1851cb0ef41Sopenharmony_ci return path[len(toplevel_dir) + len("/") :] 1861cb0ef41Sopenharmony_ci return path 1871cb0ef41Sopenharmony_ci 1881cb0ef41Sopenharmony_ci 1891cb0ef41Sopenharmony_cidef _ExtractSources(target, target_dict, toplevel_dir): 1901cb0ef41Sopenharmony_ci # |target| is either absolute or relative and in the format of the OS. Gyp 1911cb0ef41Sopenharmony_ci # source paths are always posix. Convert |target| to a posix path relative to 1921cb0ef41Sopenharmony_ci # |toplevel_dir_|. This is done to make it easy to build source paths. 1931cb0ef41Sopenharmony_ci base_path = posixpath.dirname(_ToLocalPath(toplevel_dir, _ToGypPath(target))) 1941cb0ef41Sopenharmony_ci base_path_components = base_path.split("/") 1951cb0ef41Sopenharmony_ci 1961cb0ef41Sopenharmony_ci # Add a trailing '/' so that _AddSources() can easily build paths. 1971cb0ef41Sopenharmony_ci if len(base_path): 1981cb0ef41Sopenharmony_ci base_path += "/" 1991cb0ef41Sopenharmony_ci 2001cb0ef41Sopenharmony_ci if debug: 2011cb0ef41Sopenharmony_ci print("ExtractSources", target, base_path) 2021cb0ef41Sopenharmony_ci 2031cb0ef41Sopenharmony_ci results = [] 2041cb0ef41Sopenharmony_ci if "sources" in target_dict: 2051cb0ef41Sopenharmony_ci _AddSources(target_dict["sources"], base_path, base_path_components, results) 2061cb0ef41Sopenharmony_ci # Include the inputs from any actions. Any changes to these affect the 2071cb0ef41Sopenharmony_ci # resulting output. 2081cb0ef41Sopenharmony_ci if "actions" in target_dict: 2091cb0ef41Sopenharmony_ci for action in target_dict["actions"]: 2101cb0ef41Sopenharmony_ci _ExtractSourcesFromAction(action, base_path, base_path_components, results) 2111cb0ef41Sopenharmony_ci if "rules" in target_dict: 2121cb0ef41Sopenharmony_ci for rule in target_dict["rules"]: 2131cb0ef41Sopenharmony_ci _ExtractSourcesFromAction(rule, base_path, base_path_components, results) 2141cb0ef41Sopenharmony_ci 2151cb0ef41Sopenharmony_ci return results 2161cb0ef41Sopenharmony_ci 2171cb0ef41Sopenharmony_ci 2181cb0ef41Sopenharmony_ciclass Target: 2191cb0ef41Sopenharmony_ci """Holds information about a particular target: 2201cb0ef41Sopenharmony_ci deps: set of Targets this Target depends upon. This is not recursive, only the 2211cb0ef41Sopenharmony_ci direct dependent Targets. 2221cb0ef41Sopenharmony_ci match_status: one of the MatchStatus values. 2231cb0ef41Sopenharmony_ci back_deps: set of Targets that have a dependency on this Target. 2241cb0ef41Sopenharmony_ci visited: used during iteration to indicate whether we've visited this target. 2251cb0ef41Sopenharmony_ci This is used for two iterations, once in building the set of Targets and 2261cb0ef41Sopenharmony_ci again in _GetBuildTargets(). 2271cb0ef41Sopenharmony_ci name: fully qualified name of the target. 2281cb0ef41Sopenharmony_ci requires_build: True if the target type is such that it needs to be built. 2291cb0ef41Sopenharmony_ci See _DoesTargetTypeRequireBuild for details. 2301cb0ef41Sopenharmony_ci added_to_compile_targets: used when determining if the target was added to the 2311cb0ef41Sopenharmony_ci set of targets that needs to be built. 2321cb0ef41Sopenharmony_ci in_roots: true if this target is a descendant of one of the root nodes. 2331cb0ef41Sopenharmony_ci is_executable: true if the type of target is executable. 2341cb0ef41Sopenharmony_ci is_static_library: true if the type of target is static_library. 2351cb0ef41Sopenharmony_ci is_or_has_linked_ancestor: true if the target does a link (eg executable), or 2361cb0ef41Sopenharmony_ci if there is a target in back_deps that does a link.""" 2371cb0ef41Sopenharmony_ci 2381cb0ef41Sopenharmony_ci def __init__(self, name): 2391cb0ef41Sopenharmony_ci self.deps = set() 2401cb0ef41Sopenharmony_ci self.match_status = MATCH_STATUS_TBD 2411cb0ef41Sopenharmony_ci self.back_deps = set() 2421cb0ef41Sopenharmony_ci self.name = name 2431cb0ef41Sopenharmony_ci # TODO(sky): I don't like hanging this off Target. This state is specific 2441cb0ef41Sopenharmony_ci # to certain functions and should be isolated there. 2451cb0ef41Sopenharmony_ci self.visited = False 2461cb0ef41Sopenharmony_ci self.requires_build = False 2471cb0ef41Sopenharmony_ci self.added_to_compile_targets = False 2481cb0ef41Sopenharmony_ci self.in_roots = False 2491cb0ef41Sopenharmony_ci self.is_executable = False 2501cb0ef41Sopenharmony_ci self.is_static_library = False 2511cb0ef41Sopenharmony_ci self.is_or_has_linked_ancestor = False 2521cb0ef41Sopenharmony_ci 2531cb0ef41Sopenharmony_ci 2541cb0ef41Sopenharmony_ciclass Config: 2551cb0ef41Sopenharmony_ci """Details what we're looking for 2561cb0ef41Sopenharmony_ci files: set of files to search for 2571cb0ef41Sopenharmony_ci targets: see file description for details.""" 2581cb0ef41Sopenharmony_ci 2591cb0ef41Sopenharmony_ci def __init__(self): 2601cb0ef41Sopenharmony_ci self.files = [] 2611cb0ef41Sopenharmony_ci self.targets = set() 2621cb0ef41Sopenharmony_ci self.additional_compile_target_names = set() 2631cb0ef41Sopenharmony_ci self.test_target_names = set() 2641cb0ef41Sopenharmony_ci 2651cb0ef41Sopenharmony_ci def Init(self, params): 2661cb0ef41Sopenharmony_ci """Initializes Config. This is a separate method as it raises an exception 2671cb0ef41Sopenharmony_ci if there is a parse error.""" 2681cb0ef41Sopenharmony_ci generator_flags = params.get("generator_flags", {}) 2691cb0ef41Sopenharmony_ci config_path = generator_flags.get("config_path", None) 2701cb0ef41Sopenharmony_ci if not config_path: 2711cb0ef41Sopenharmony_ci return 2721cb0ef41Sopenharmony_ci try: 2731cb0ef41Sopenharmony_ci f = open(config_path) 2741cb0ef41Sopenharmony_ci config = json.load(f) 2751cb0ef41Sopenharmony_ci f.close() 2761cb0ef41Sopenharmony_ci except OSError: 2771cb0ef41Sopenharmony_ci raise Exception("Unable to open file " + config_path) 2781cb0ef41Sopenharmony_ci except ValueError as e: 2791cb0ef41Sopenharmony_ci raise Exception("Unable to parse config file " + config_path + str(e)) 2801cb0ef41Sopenharmony_ci if not isinstance(config, dict): 2811cb0ef41Sopenharmony_ci raise Exception("config_path must be a JSON file containing a dictionary") 2821cb0ef41Sopenharmony_ci self.files = config.get("files", []) 2831cb0ef41Sopenharmony_ci self.additional_compile_target_names = set( 2841cb0ef41Sopenharmony_ci config.get("additional_compile_targets", []) 2851cb0ef41Sopenharmony_ci ) 2861cb0ef41Sopenharmony_ci self.test_target_names = set(config.get("test_targets", [])) 2871cb0ef41Sopenharmony_ci 2881cb0ef41Sopenharmony_ci 2891cb0ef41Sopenharmony_cidef _WasBuildFileModified(build_file, data, files, toplevel_dir): 2901cb0ef41Sopenharmony_ci """Returns true if the build file |build_file| is either in |files| or 2911cb0ef41Sopenharmony_ci one of the files included by |build_file| is in |files|. |toplevel_dir| is 2921cb0ef41Sopenharmony_ci the root of the source tree.""" 2931cb0ef41Sopenharmony_ci if _ToLocalPath(toplevel_dir, _ToGypPath(build_file)) in files: 2941cb0ef41Sopenharmony_ci if debug: 2951cb0ef41Sopenharmony_ci print("gyp file modified", build_file) 2961cb0ef41Sopenharmony_ci return True 2971cb0ef41Sopenharmony_ci 2981cb0ef41Sopenharmony_ci # First element of included_files is the file itself. 2991cb0ef41Sopenharmony_ci if len(data[build_file]["included_files"]) <= 1: 3001cb0ef41Sopenharmony_ci return False 3011cb0ef41Sopenharmony_ci 3021cb0ef41Sopenharmony_ci for include_file in data[build_file]["included_files"][1:]: 3031cb0ef41Sopenharmony_ci # |included_files| are relative to the directory of the |build_file|. 3041cb0ef41Sopenharmony_ci rel_include_file = _ToGypPath( 3051cb0ef41Sopenharmony_ci gyp.common.UnrelativePath(include_file, build_file) 3061cb0ef41Sopenharmony_ci ) 3071cb0ef41Sopenharmony_ci if _ToLocalPath(toplevel_dir, rel_include_file) in files: 3081cb0ef41Sopenharmony_ci if debug: 3091cb0ef41Sopenharmony_ci print( 3101cb0ef41Sopenharmony_ci "included gyp file modified, gyp_file=", 3111cb0ef41Sopenharmony_ci build_file, 3121cb0ef41Sopenharmony_ci "included file=", 3131cb0ef41Sopenharmony_ci rel_include_file, 3141cb0ef41Sopenharmony_ci ) 3151cb0ef41Sopenharmony_ci return True 3161cb0ef41Sopenharmony_ci return False 3171cb0ef41Sopenharmony_ci 3181cb0ef41Sopenharmony_ci 3191cb0ef41Sopenharmony_cidef _GetOrCreateTargetByName(targets, target_name): 3201cb0ef41Sopenharmony_ci """Creates or returns the Target at targets[target_name]. If there is no 3211cb0ef41Sopenharmony_ci Target for |target_name| one is created. Returns a tuple of whether a new 3221cb0ef41Sopenharmony_ci Target was created and the Target.""" 3231cb0ef41Sopenharmony_ci if target_name in targets: 3241cb0ef41Sopenharmony_ci return False, targets[target_name] 3251cb0ef41Sopenharmony_ci target = Target(target_name) 3261cb0ef41Sopenharmony_ci targets[target_name] = target 3271cb0ef41Sopenharmony_ci return True, target 3281cb0ef41Sopenharmony_ci 3291cb0ef41Sopenharmony_ci 3301cb0ef41Sopenharmony_cidef _DoesTargetTypeRequireBuild(target_dict): 3311cb0ef41Sopenharmony_ci """Returns true if the target type is such that it needs to be built.""" 3321cb0ef41Sopenharmony_ci # If a 'none' target has rules or actions we assume it requires a build. 3331cb0ef41Sopenharmony_ci return bool( 3341cb0ef41Sopenharmony_ci target_dict["type"] != "none" 3351cb0ef41Sopenharmony_ci or target_dict.get("actions") 3361cb0ef41Sopenharmony_ci or target_dict.get("rules") 3371cb0ef41Sopenharmony_ci ) 3381cb0ef41Sopenharmony_ci 3391cb0ef41Sopenharmony_ci 3401cb0ef41Sopenharmony_cidef _GenerateTargets(data, target_list, target_dicts, toplevel_dir, files, build_files): 3411cb0ef41Sopenharmony_ci """Returns a tuple of the following: 3421cb0ef41Sopenharmony_ci . A dictionary mapping from fully qualified name to Target. 3431cb0ef41Sopenharmony_ci . A list of the targets that have a source file in |files|. 3441cb0ef41Sopenharmony_ci . Targets that constitute the 'all' target. See description at top of file 3451cb0ef41Sopenharmony_ci for details on the 'all' target. 3461cb0ef41Sopenharmony_ci This sets the |match_status| of the targets that contain any of the source 3471cb0ef41Sopenharmony_ci files in |files| to MATCH_STATUS_MATCHES. 3481cb0ef41Sopenharmony_ci |toplevel_dir| is the root of the source tree.""" 3491cb0ef41Sopenharmony_ci # Maps from target name to Target. 3501cb0ef41Sopenharmony_ci name_to_target = {} 3511cb0ef41Sopenharmony_ci 3521cb0ef41Sopenharmony_ci # Targets that matched. 3531cb0ef41Sopenharmony_ci matching_targets = [] 3541cb0ef41Sopenharmony_ci 3551cb0ef41Sopenharmony_ci # Queue of targets to visit. 3561cb0ef41Sopenharmony_ci targets_to_visit = target_list[:] 3571cb0ef41Sopenharmony_ci 3581cb0ef41Sopenharmony_ci # Maps from build file to a boolean indicating whether the build file is in 3591cb0ef41Sopenharmony_ci # |files|. 3601cb0ef41Sopenharmony_ci build_file_in_files = {} 3611cb0ef41Sopenharmony_ci 3621cb0ef41Sopenharmony_ci # Root targets across all files. 3631cb0ef41Sopenharmony_ci roots = set() 3641cb0ef41Sopenharmony_ci 3651cb0ef41Sopenharmony_ci # Set of Targets in |build_files|. 3661cb0ef41Sopenharmony_ci build_file_targets = set() 3671cb0ef41Sopenharmony_ci 3681cb0ef41Sopenharmony_ci while len(targets_to_visit) > 0: 3691cb0ef41Sopenharmony_ci target_name = targets_to_visit.pop() 3701cb0ef41Sopenharmony_ci created_target, target = _GetOrCreateTargetByName(name_to_target, target_name) 3711cb0ef41Sopenharmony_ci if created_target: 3721cb0ef41Sopenharmony_ci roots.add(target) 3731cb0ef41Sopenharmony_ci elif target.visited: 3741cb0ef41Sopenharmony_ci continue 3751cb0ef41Sopenharmony_ci 3761cb0ef41Sopenharmony_ci target.visited = True 3771cb0ef41Sopenharmony_ci target.requires_build = _DoesTargetTypeRequireBuild(target_dicts[target_name]) 3781cb0ef41Sopenharmony_ci target_type = target_dicts[target_name]["type"] 3791cb0ef41Sopenharmony_ci target.is_executable = target_type == "executable" 3801cb0ef41Sopenharmony_ci target.is_static_library = target_type == "static_library" 3811cb0ef41Sopenharmony_ci target.is_or_has_linked_ancestor = ( 3821cb0ef41Sopenharmony_ci target_type == "executable" or target_type == "shared_library" 3831cb0ef41Sopenharmony_ci ) 3841cb0ef41Sopenharmony_ci 3851cb0ef41Sopenharmony_ci build_file = gyp.common.ParseQualifiedTarget(target_name)[0] 3861cb0ef41Sopenharmony_ci if build_file not in build_file_in_files: 3871cb0ef41Sopenharmony_ci build_file_in_files[build_file] = _WasBuildFileModified( 3881cb0ef41Sopenharmony_ci build_file, data, files, toplevel_dir 3891cb0ef41Sopenharmony_ci ) 3901cb0ef41Sopenharmony_ci 3911cb0ef41Sopenharmony_ci if build_file in build_files: 3921cb0ef41Sopenharmony_ci build_file_targets.add(target) 3931cb0ef41Sopenharmony_ci 3941cb0ef41Sopenharmony_ci # If a build file (or any of its included files) is modified we assume all 3951cb0ef41Sopenharmony_ci # targets in the file are modified. 3961cb0ef41Sopenharmony_ci if build_file_in_files[build_file]: 3971cb0ef41Sopenharmony_ci print("matching target from modified build file", target_name) 3981cb0ef41Sopenharmony_ci target.match_status = MATCH_STATUS_MATCHES 3991cb0ef41Sopenharmony_ci matching_targets.append(target) 4001cb0ef41Sopenharmony_ci else: 4011cb0ef41Sopenharmony_ci sources = _ExtractSources( 4021cb0ef41Sopenharmony_ci target_name, target_dicts[target_name], toplevel_dir 4031cb0ef41Sopenharmony_ci ) 4041cb0ef41Sopenharmony_ci for source in sources: 4051cb0ef41Sopenharmony_ci if _ToGypPath(os.path.normpath(source)) in files: 4061cb0ef41Sopenharmony_ci print("target", target_name, "matches", source) 4071cb0ef41Sopenharmony_ci target.match_status = MATCH_STATUS_MATCHES 4081cb0ef41Sopenharmony_ci matching_targets.append(target) 4091cb0ef41Sopenharmony_ci break 4101cb0ef41Sopenharmony_ci 4111cb0ef41Sopenharmony_ci # Add dependencies to visit as well as updating back pointers for deps. 4121cb0ef41Sopenharmony_ci for dep in target_dicts[target_name].get("dependencies", []): 4131cb0ef41Sopenharmony_ci targets_to_visit.append(dep) 4141cb0ef41Sopenharmony_ci 4151cb0ef41Sopenharmony_ci created_dep_target, dep_target = _GetOrCreateTargetByName( 4161cb0ef41Sopenharmony_ci name_to_target, dep 4171cb0ef41Sopenharmony_ci ) 4181cb0ef41Sopenharmony_ci if not created_dep_target: 4191cb0ef41Sopenharmony_ci roots.discard(dep_target) 4201cb0ef41Sopenharmony_ci 4211cb0ef41Sopenharmony_ci target.deps.add(dep_target) 4221cb0ef41Sopenharmony_ci dep_target.back_deps.add(target) 4231cb0ef41Sopenharmony_ci 4241cb0ef41Sopenharmony_ci return name_to_target, matching_targets, roots & build_file_targets 4251cb0ef41Sopenharmony_ci 4261cb0ef41Sopenharmony_ci 4271cb0ef41Sopenharmony_cidef _GetUnqualifiedToTargetMapping(all_targets, to_find): 4281cb0ef41Sopenharmony_ci """Returns a tuple of the following: 4291cb0ef41Sopenharmony_ci . mapping (dictionary) from unqualified name to Target for all the 4301cb0ef41Sopenharmony_ci Targets in |to_find|. 4311cb0ef41Sopenharmony_ci . any target names not found. If this is empty all targets were found.""" 4321cb0ef41Sopenharmony_ci result = {} 4331cb0ef41Sopenharmony_ci if not to_find: 4341cb0ef41Sopenharmony_ci return {}, [] 4351cb0ef41Sopenharmony_ci to_find = set(to_find) 4361cb0ef41Sopenharmony_ci for target_name in all_targets.keys(): 4371cb0ef41Sopenharmony_ci extracted = gyp.common.ParseQualifiedTarget(target_name) 4381cb0ef41Sopenharmony_ci if len(extracted) > 1 and extracted[1] in to_find: 4391cb0ef41Sopenharmony_ci to_find.remove(extracted[1]) 4401cb0ef41Sopenharmony_ci result[extracted[1]] = all_targets[target_name] 4411cb0ef41Sopenharmony_ci if not to_find: 4421cb0ef41Sopenharmony_ci return result, [] 4431cb0ef41Sopenharmony_ci return result, [x for x in to_find] 4441cb0ef41Sopenharmony_ci 4451cb0ef41Sopenharmony_ci 4461cb0ef41Sopenharmony_cidef _DoesTargetDependOnMatchingTargets(target): 4471cb0ef41Sopenharmony_ci """Returns true if |target| or any of its dependencies is one of the 4481cb0ef41Sopenharmony_ci targets containing the files supplied as input to analyzer. This updates 4491cb0ef41Sopenharmony_ci |matches| of the Targets as it recurses. 4501cb0ef41Sopenharmony_ci target: the Target to look for.""" 4511cb0ef41Sopenharmony_ci if target.match_status == MATCH_STATUS_DOESNT_MATCH: 4521cb0ef41Sopenharmony_ci return False 4531cb0ef41Sopenharmony_ci if ( 4541cb0ef41Sopenharmony_ci target.match_status == MATCH_STATUS_MATCHES 4551cb0ef41Sopenharmony_ci or target.match_status == MATCH_STATUS_MATCHES_BY_DEPENDENCY 4561cb0ef41Sopenharmony_ci ): 4571cb0ef41Sopenharmony_ci return True 4581cb0ef41Sopenharmony_ci for dep in target.deps: 4591cb0ef41Sopenharmony_ci if _DoesTargetDependOnMatchingTargets(dep): 4601cb0ef41Sopenharmony_ci target.match_status = MATCH_STATUS_MATCHES_BY_DEPENDENCY 4611cb0ef41Sopenharmony_ci print("\t", target.name, "matches by dep", dep.name) 4621cb0ef41Sopenharmony_ci return True 4631cb0ef41Sopenharmony_ci target.match_status = MATCH_STATUS_DOESNT_MATCH 4641cb0ef41Sopenharmony_ci return False 4651cb0ef41Sopenharmony_ci 4661cb0ef41Sopenharmony_ci 4671cb0ef41Sopenharmony_cidef _GetTargetsDependingOnMatchingTargets(possible_targets): 4681cb0ef41Sopenharmony_ci """Returns the list of Targets in |possible_targets| that depend (either 4691cb0ef41Sopenharmony_ci directly on indirectly) on at least one of the targets containing the files 4701cb0ef41Sopenharmony_ci supplied as input to analyzer. 4711cb0ef41Sopenharmony_ci possible_targets: targets to search from.""" 4721cb0ef41Sopenharmony_ci found = [] 4731cb0ef41Sopenharmony_ci print("Targets that matched by dependency:") 4741cb0ef41Sopenharmony_ci for target in possible_targets: 4751cb0ef41Sopenharmony_ci if _DoesTargetDependOnMatchingTargets(target): 4761cb0ef41Sopenharmony_ci found.append(target) 4771cb0ef41Sopenharmony_ci return found 4781cb0ef41Sopenharmony_ci 4791cb0ef41Sopenharmony_ci 4801cb0ef41Sopenharmony_cidef _AddCompileTargets(target, roots, add_if_no_ancestor, result): 4811cb0ef41Sopenharmony_ci """Recurses through all targets that depend on |target|, adding all targets 4821cb0ef41Sopenharmony_ci that need to be built (and are in |roots|) to |result|. 4831cb0ef41Sopenharmony_ci roots: set of root targets. 4841cb0ef41Sopenharmony_ci add_if_no_ancestor: If true and there are no ancestors of |target| then add 4851cb0ef41Sopenharmony_ci |target| to |result|. |target| must still be in |roots|. 4861cb0ef41Sopenharmony_ci result: targets that need to be built are added here.""" 4871cb0ef41Sopenharmony_ci if target.visited: 4881cb0ef41Sopenharmony_ci return 4891cb0ef41Sopenharmony_ci 4901cb0ef41Sopenharmony_ci target.visited = True 4911cb0ef41Sopenharmony_ci target.in_roots = target in roots 4921cb0ef41Sopenharmony_ci 4931cb0ef41Sopenharmony_ci for back_dep_target in target.back_deps: 4941cb0ef41Sopenharmony_ci _AddCompileTargets(back_dep_target, roots, False, result) 4951cb0ef41Sopenharmony_ci target.added_to_compile_targets |= back_dep_target.added_to_compile_targets 4961cb0ef41Sopenharmony_ci target.in_roots |= back_dep_target.in_roots 4971cb0ef41Sopenharmony_ci target.is_or_has_linked_ancestor |= back_dep_target.is_or_has_linked_ancestor 4981cb0ef41Sopenharmony_ci 4991cb0ef41Sopenharmony_ci # Always add 'executable' targets. Even though they may be built by other 5001cb0ef41Sopenharmony_ci # targets that depend upon them it makes detection of what is going to be 5011cb0ef41Sopenharmony_ci # built easier. 5021cb0ef41Sopenharmony_ci # And always add static_libraries that have no dependencies on them from 5031cb0ef41Sopenharmony_ci # linkables. This is necessary as the other dependencies on them may be 5041cb0ef41Sopenharmony_ci # static libraries themselves, which are not compile time dependencies. 5051cb0ef41Sopenharmony_ci if target.in_roots and ( 5061cb0ef41Sopenharmony_ci target.is_executable 5071cb0ef41Sopenharmony_ci or ( 5081cb0ef41Sopenharmony_ci not target.added_to_compile_targets 5091cb0ef41Sopenharmony_ci and (add_if_no_ancestor or target.requires_build) 5101cb0ef41Sopenharmony_ci ) 5111cb0ef41Sopenharmony_ci or ( 5121cb0ef41Sopenharmony_ci target.is_static_library 5131cb0ef41Sopenharmony_ci and add_if_no_ancestor 5141cb0ef41Sopenharmony_ci and not target.is_or_has_linked_ancestor 5151cb0ef41Sopenharmony_ci ) 5161cb0ef41Sopenharmony_ci ): 5171cb0ef41Sopenharmony_ci print( 5181cb0ef41Sopenharmony_ci "\t\tadding to compile targets", 5191cb0ef41Sopenharmony_ci target.name, 5201cb0ef41Sopenharmony_ci "executable", 5211cb0ef41Sopenharmony_ci target.is_executable, 5221cb0ef41Sopenharmony_ci "added_to_compile_targets", 5231cb0ef41Sopenharmony_ci target.added_to_compile_targets, 5241cb0ef41Sopenharmony_ci "add_if_no_ancestor", 5251cb0ef41Sopenharmony_ci add_if_no_ancestor, 5261cb0ef41Sopenharmony_ci "requires_build", 5271cb0ef41Sopenharmony_ci target.requires_build, 5281cb0ef41Sopenharmony_ci "is_static_library", 5291cb0ef41Sopenharmony_ci target.is_static_library, 5301cb0ef41Sopenharmony_ci "is_or_has_linked_ancestor", 5311cb0ef41Sopenharmony_ci target.is_or_has_linked_ancestor, 5321cb0ef41Sopenharmony_ci ) 5331cb0ef41Sopenharmony_ci result.add(target) 5341cb0ef41Sopenharmony_ci target.added_to_compile_targets = True 5351cb0ef41Sopenharmony_ci 5361cb0ef41Sopenharmony_ci 5371cb0ef41Sopenharmony_cidef _GetCompileTargets(matching_targets, supplied_targets): 5381cb0ef41Sopenharmony_ci """Returns the set of Targets that require a build. 5391cb0ef41Sopenharmony_ci matching_targets: targets that changed and need to be built. 5401cb0ef41Sopenharmony_ci supplied_targets: set of targets supplied to analyzer to search from.""" 5411cb0ef41Sopenharmony_ci result = set() 5421cb0ef41Sopenharmony_ci for target in matching_targets: 5431cb0ef41Sopenharmony_ci print("finding compile targets for match", target.name) 5441cb0ef41Sopenharmony_ci _AddCompileTargets(target, supplied_targets, True, result) 5451cb0ef41Sopenharmony_ci return result 5461cb0ef41Sopenharmony_ci 5471cb0ef41Sopenharmony_ci 5481cb0ef41Sopenharmony_cidef _WriteOutput(params, **values): 5491cb0ef41Sopenharmony_ci """Writes the output, either to stdout or a file is specified.""" 5501cb0ef41Sopenharmony_ci if "error" in values: 5511cb0ef41Sopenharmony_ci print("Error:", values["error"]) 5521cb0ef41Sopenharmony_ci if "status" in values: 5531cb0ef41Sopenharmony_ci print(values["status"]) 5541cb0ef41Sopenharmony_ci if "targets" in values: 5551cb0ef41Sopenharmony_ci values["targets"].sort() 5561cb0ef41Sopenharmony_ci print("Supplied targets that depend on changed files:") 5571cb0ef41Sopenharmony_ci for target in values["targets"]: 5581cb0ef41Sopenharmony_ci print("\t", target) 5591cb0ef41Sopenharmony_ci if "invalid_targets" in values: 5601cb0ef41Sopenharmony_ci values["invalid_targets"].sort() 5611cb0ef41Sopenharmony_ci print("The following targets were not found:") 5621cb0ef41Sopenharmony_ci for target in values["invalid_targets"]: 5631cb0ef41Sopenharmony_ci print("\t", target) 5641cb0ef41Sopenharmony_ci if "build_targets" in values: 5651cb0ef41Sopenharmony_ci values["build_targets"].sort() 5661cb0ef41Sopenharmony_ci print("Targets that require a build:") 5671cb0ef41Sopenharmony_ci for target in values["build_targets"]: 5681cb0ef41Sopenharmony_ci print("\t", target) 5691cb0ef41Sopenharmony_ci if "compile_targets" in values: 5701cb0ef41Sopenharmony_ci values["compile_targets"].sort() 5711cb0ef41Sopenharmony_ci print("Targets that need to be built:") 5721cb0ef41Sopenharmony_ci for target in values["compile_targets"]: 5731cb0ef41Sopenharmony_ci print("\t", target) 5741cb0ef41Sopenharmony_ci if "test_targets" in values: 5751cb0ef41Sopenharmony_ci values["test_targets"].sort() 5761cb0ef41Sopenharmony_ci print("Test targets:") 5771cb0ef41Sopenharmony_ci for target in values["test_targets"]: 5781cb0ef41Sopenharmony_ci print("\t", target) 5791cb0ef41Sopenharmony_ci 5801cb0ef41Sopenharmony_ci output_path = params.get("generator_flags", {}).get("analyzer_output_path", None) 5811cb0ef41Sopenharmony_ci if not output_path: 5821cb0ef41Sopenharmony_ci print(json.dumps(values)) 5831cb0ef41Sopenharmony_ci return 5841cb0ef41Sopenharmony_ci try: 5851cb0ef41Sopenharmony_ci f = open(output_path, "w") 5861cb0ef41Sopenharmony_ci f.write(json.dumps(values) + "\n") 5871cb0ef41Sopenharmony_ci f.close() 5881cb0ef41Sopenharmony_ci except OSError as e: 5891cb0ef41Sopenharmony_ci print("Error writing to output file", output_path, str(e)) 5901cb0ef41Sopenharmony_ci 5911cb0ef41Sopenharmony_ci 5921cb0ef41Sopenharmony_cidef _WasGypIncludeFileModified(params, files): 5931cb0ef41Sopenharmony_ci """Returns true if one of the files in |files| is in the set of included 5941cb0ef41Sopenharmony_ci files.""" 5951cb0ef41Sopenharmony_ci if params["options"].includes: 5961cb0ef41Sopenharmony_ci for include in params["options"].includes: 5971cb0ef41Sopenharmony_ci if _ToGypPath(os.path.normpath(include)) in files: 5981cb0ef41Sopenharmony_ci print("Include file modified, assuming all changed", include) 5991cb0ef41Sopenharmony_ci return True 6001cb0ef41Sopenharmony_ci return False 6011cb0ef41Sopenharmony_ci 6021cb0ef41Sopenharmony_ci 6031cb0ef41Sopenharmony_cidef _NamesNotIn(names, mapping): 6041cb0ef41Sopenharmony_ci """Returns a list of the values in |names| that are not in |mapping|.""" 6051cb0ef41Sopenharmony_ci return [name for name in names if name not in mapping] 6061cb0ef41Sopenharmony_ci 6071cb0ef41Sopenharmony_ci 6081cb0ef41Sopenharmony_cidef _LookupTargets(names, mapping): 6091cb0ef41Sopenharmony_ci """Returns a list of the mapping[name] for each value in |names| that is in 6101cb0ef41Sopenharmony_ci |mapping|.""" 6111cb0ef41Sopenharmony_ci return [mapping[name] for name in names if name in mapping] 6121cb0ef41Sopenharmony_ci 6131cb0ef41Sopenharmony_ci 6141cb0ef41Sopenharmony_cidef CalculateVariables(default_variables, params): 6151cb0ef41Sopenharmony_ci """Calculate additional variables for use in the build (called by gyp).""" 6161cb0ef41Sopenharmony_ci flavor = gyp.common.GetFlavor(params) 6171cb0ef41Sopenharmony_ci if flavor == "mac": 6181cb0ef41Sopenharmony_ci default_variables.setdefault("OS", "mac") 6191cb0ef41Sopenharmony_ci elif flavor == "win": 6201cb0ef41Sopenharmony_ci default_variables.setdefault("OS", "win") 6211cb0ef41Sopenharmony_ci gyp.msvs_emulation.CalculateCommonVariables(default_variables, params) 6221cb0ef41Sopenharmony_ci else: 6231cb0ef41Sopenharmony_ci operating_system = flavor 6241cb0ef41Sopenharmony_ci if flavor == "android": 6251cb0ef41Sopenharmony_ci operating_system = "linux" # Keep this legacy behavior for now. 6261cb0ef41Sopenharmony_ci default_variables.setdefault("OS", operating_system) 6271cb0ef41Sopenharmony_ci 6281cb0ef41Sopenharmony_ci 6291cb0ef41Sopenharmony_ciclass TargetCalculator: 6301cb0ef41Sopenharmony_ci """Calculates the matching test_targets and matching compile_targets.""" 6311cb0ef41Sopenharmony_ci 6321cb0ef41Sopenharmony_ci def __init__( 6331cb0ef41Sopenharmony_ci self, 6341cb0ef41Sopenharmony_ci files, 6351cb0ef41Sopenharmony_ci additional_compile_target_names, 6361cb0ef41Sopenharmony_ci test_target_names, 6371cb0ef41Sopenharmony_ci data, 6381cb0ef41Sopenharmony_ci target_list, 6391cb0ef41Sopenharmony_ci target_dicts, 6401cb0ef41Sopenharmony_ci toplevel_dir, 6411cb0ef41Sopenharmony_ci build_files, 6421cb0ef41Sopenharmony_ci ): 6431cb0ef41Sopenharmony_ci self._additional_compile_target_names = set(additional_compile_target_names) 6441cb0ef41Sopenharmony_ci self._test_target_names = set(test_target_names) 6451cb0ef41Sopenharmony_ci ( 6461cb0ef41Sopenharmony_ci self._name_to_target, 6471cb0ef41Sopenharmony_ci self._changed_targets, 6481cb0ef41Sopenharmony_ci self._root_targets, 6491cb0ef41Sopenharmony_ci ) = _GenerateTargets( 6501cb0ef41Sopenharmony_ci data, target_list, target_dicts, toplevel_dir, frozenset(files), build_files 6511cb0ef41Sopenharmony_ci ) 6521cb0ef41Sopenharmony_ci ( 6531cb0ef41Sopenharmony_ci self._unqualified_mapping, 6541cb0ef41Sopenharmony_ci self.invalid_targets, 6551cb0ef41Sopenharmony_ci ) = _GetUnqualifiedToTargetMapping( 6561cb0ef41Sopenharmony_ci self._name_to_target, self._supplied_target_names_no_all() 6571cb0ef41Sopenharmony_ci ) 6581cb0ef41Sopenharmony_ci 6591cb0ef41Sopenharmony_ci def _supplied_target_names(self): 6601cb0ef41Sopenharmony_ci return self._additional_compile_target_names | self._test_target_names 6611cb0ef41Sopenharmony_ci 6621cb0ef41Sopenharmony_ci def _supplied_target_names_no_all(self): 6631cb0ef41Sopenharmony_ci """Returns the supplied test targets without 'all'.""" 6641cb0ef41Sopenharmony_ci result = self._supplied_target_names() 6651cb0ef41Sopenharmony_ci result.discard("all") 6661cb0ef41Sopenharmony_ci return result 6671cb0ef41Sopenharmony_ci 6681cb0ef41Sopenharmony_ci def is_build_impacted(self): 6691cb0ef41Sopenharmony_ci """Returns true if the supplied files impact the build at all.""" 6701cb0ef41Sopenharmony_ci return self._changed_targets 6711cb0ef41Sopenharmony_ci 6721cb0ef41Sopenharmony_ci def find_matching_test_target_names(self): 6731cb0ef41Sopenharmony_ci """Returns the set of output test targets.""" 6741cb0ef41Sopenharmony_ci assert self.is_build_impacted() 6751cb0ef41Sopenharmony_ci # Find the test targets first. 'all' is special cased to mean all the 6761cb0ef41Sopenharmony_ci # root targets. To deal with all the supplied |test_targets| are expanded 6771cb0ef41Sopenharmony_ci # to include the root targets during lookup. If any of the root targets 6781cb0ef41Sopenharmony_ci # match, we remove it and replace it with 'all'. 6791cb0ef41Sopenharmony_ci test_target_names_no_all = set(self._test_target_names) 6801cb0ef41Sopenharmony_ci test_target_names_no_all.discard("all") 6811cb0ef41Sopenharmony_ci test_targets_no_all = _LookupTargets( 6821cb0ef41Sopenharmony_ci test_target_names_no_all, self._unqualified_mapping 6831cb0ef41Sopenharmony_ci ) 6841cb0ef41Sopenharmony_ci test_target_names_contains_all = "all" in self._test_target_names 6851cb0ef41Sopenharmony_ci if test_target_names_contains_all: 6861cb0ef41Sopenharmony_ci test_targets = [ 6871cb0ef41Sopenharmony_ci x for x in (set(test_targets_no_all) | set(self._root_targets)) 6881cb0ef41Sopenharmony_ci ] 6891cb0ef41Sopenharmony_ci else: 6901cb0ef41Sopenharmony_ci test_targets = [x for x in test_targets_no_all] 6911cb0ef41Sopenharmony_ci print("supplied test_targets") 6921cb0ef41Sopenharmony_ci for target_name in self._test_target_names: 6931cb0ef41Sopenharmony_ci print("\t", target_name) 6941cb0ef41Sopenharmony_ci print("found test_targets") 6951cb0ef41Sopenharmony_ci for target in test_targets: 6961cb0ef41Sopenharmony_ci print("\t", target.name) 6971cb0ef41Sopenharmony_ci print("searching for matching test targets") 6981cb0ef41Sopenharmony_ci matching_test_targets = _GetTargetsDependingOnMatchingTargets(test_targets) 6991cb0ef41Sopenharmony_ci matching_test_targets_contains_all = test_target_names_contains_all and set( 7001cb0ef41Sopenharmony_ci matching_test_targets 7011cb0ef41Sopenharmony_ci ) & set(self._root_targets) 7021cb0ef41Sopenharmony_ci if matching_test_targets_contains_all: 7031cb0ef41Sopenharmony_ci # Remove any of the targets for all that were not explicitly supplied, 7041cb0ef41Sopenharmony_ci # 'all' is subsequentely added to the matching names below. 7051cb0ef41Sopenharmony_ci matching_test_targets = [ 7061cb0ef41Sopenharmony_ci x for x in (set(matching_test_targets) & set(test_targets_no_all)) 7071cb0ef41Sopenharmony_ci ] 7081cb0ef41Sopenharmony_ci print("matched test_targets") 7091cb0ef41Sopenharmony_ci for target in matching_test_targets: 7101cb0ef41Sopenharmony_ci print("\t", target.name) 7111cb0ef41Sopenharmony_ci matching_target_names = [ 7121cb0ef41Sopenharmony_ci gyp.common.ParseQualifiedTarget(target.name)[1] 7131cb0ef41Sopenharmony_ci for target in matching_test_targets 7141cb0ef41Sopenharmony_ci ] 7151cb0ef41Sopenharmony_ci if matching_test_targets_contains_all: 7161cb0ef41Sopenharmony_ci matching_target_names.append("all") 7171cb0ef41Sopenharmony_ci print("\tall") 7181cb0ef41Sopenharmony_ci return matching_target_names 7191cb0ef41Sopenharmony_ci 7201cb0ef41Sopenharmony_ci def find_matching_compile_target_names(self): 7211cb0ef41Sopenharmony_ci """Returns the set of output compile targets.""" 7221cb0ef41Sopenharmony_ci assert self.is_build_impacted() 7231cb0ef41Sopenharmony_ci # Compile targets are found by searching up from changed targets. 7241cb0ef41Sopenharmony_ci # Reset the visited status for _GetBuildTargets. 7251cb0ef41Sopenharmony_ci for target in self._name_to_target.values(): 7261cb0ef41Sopenharmony_ci target.visited = False 7271cb0ef41Sopenharmony_ci 7281cb0ef41Sopenharmony_ci supplied_targets = _LookupTargets( 7291cb0ef41Sopenharmony_ci self._supplied_target_names_no_all(), self._unqualified_mapping 7301cb0ef41Sopenharmony_ci ) 7311cb0ef41Sopenharmony_ci if "all" in self._supplied_target_names(): 7321cb0ef41Sopenharmony_ci supplied_targets = [ 7331cb0ef41Sopenharmony_ci x for x in (set(supplied_targets) | set(self._root_targets)) 7341cb0ef41Sopenharmony_ci ] 7351cb0ef41Sopenharmony_ci print("Supplied test_targets & compile_targets") 7361cb0ef41Sopenharmony_ci for target in supplied_targets: 7371cb0ef41Sopenharmony_ci print("\t", target.name) 7381cb0ef41Sopenharmony_ci print("Finding compile targets") 7391cb0ef41Sopenharmony_ci compile_targets = _GetCompileTargets(self._changed_targets, supplied_targets) 7401cb0ef41Sopenharmony_ci return [ 7411cb0ef41Sopenharmony_ci gyp.common.ParseQualifiedTarget(target.name)[1] 7421cb0ef41Sopenharmony_ci for target in compile_targets 7431cb0ef41Sopenharmony_ci ] 7441cb0ef41Sopenharmony_ci 7451cb0ef41Sopenharmony_ci 7461cb0ef41Sopenharmony_cidef GenerateOutput(target_list, target_dicts, data, params): 7471cb0ef41Sopenharmony_ci """Called by gyp as the final stage. Outputs results.""" 7481cb0ef41Sopenharmony_ci config = Config() 7491cb0ef41Sopenharmony_ci try: 7501cb0ef41Sopenharmony_ci config.Init(params) 7511cb0ef41Sopenharmony_ci 7521cb0ef41Sopenharmony_ci if not config.files: 7531cb0ef41Sopenharmony_ci raise Exception( 7541cb0ef41Sopenharmony_ci "Must specify files to analyze via config_path generator " "flag" 7551cb0ef41Sopenharmony_ci ) 7561cb0ef41Sopenharmony_ci 7571cb0ef41Sopenharmony_ci toplevel_dir = _ToGypPath(os.path.abspath(params["options"].toplevel_dir)) 7581cb0ef41Sopenharmony_ci if debug: 7591cb0ef41Sopenharmony_ci print("toplevel_dir", toplevel_dir) 7601cb0ef41Sopenharmony_ci 7611cb0ef41Sopenharmony_ci if _WasGypIncludeFileModified(params, config.files): 7621cb0ef41Sopenharmony_ci result_dict = { 7631cb0ef41Sopenharmony_ci "status": all_changed_string, 7641cb0ef41Sopenharmony_ci "test_targets": list(config.test_target_names), 7651cb0ef41Sopenharmony_ci "compile_targets": list( 7661cb0ef41Sopenharmony_ci config.additional_compile_target_names | config.test_target_names 7671cb0ef41Sopenharmony_ci ), 7681cb0ef41Sopenharmony_ci } 7691cb0ef41Sopenharmony_ci _WriteOutput(params, **result_dict) 7701cb0ef41Sopenharmony_ci return 7711cb0ef41Sopenharmony_ci 7721cb0ef41Sopenharmony_ci calculator = TargetCalculator( 7731cb0ef41Sopenharmony_ci config.files, 7741cb0ef41Sopenharmony_ci config.additional_compile_target_names, 7751cb0ef41Sopenharmony_ci config.test_target_names, 7761cb0ef41Sopenharmony_ci data, 7771cb0ef41Sopenharmony_ci target_list, 7781cb0ef41Sopenharmony_ci target_dicts, 7791cb0ef41Sopenharmony_ci toplevel_dir, 7801cb0ef41Sopenharmony_ci params["build_files"], 7811cb0ef41Sopenharmony_ci ) 7821cb0ef41Sopenharmony_ci if not calculator.is_build_impacted(): 7831cb0ef41Sopenharmony_ci result_dict = { 7841cb0ef41Sopenharmony_ci "status": no_dependency_string, 7851cb0ef41Sopenharmony_ci "test_targets": [], 7861cb0ef41Sopenharmony_ci "compile_targets": [], 7871cb0ef41Sopenharmony_ci } 7881cb0ef41Sopenharmony_ci if calculator.invalid_targets: 7891cb0ef41Sopenharmony_ci result_dict["invalid_targets"] = calculator.invalid_targets 7901cb0ef41Sopenharmony_ci _WriteOutput(params, **result_dict) 7911cb0ef41Sopenharmony_ci return 7921cb0ef41Sopenharmony_ci 7931cb0ef41Sopenharmony_ci test_target_names = calculator.find_matching_test_target_names() 7941cb0ef41Sopenharmony_ci compile_target_names = calculator.find_matching_compile_target_names() 7951cb0ef41Sopenharmony_ci found_at_least_one_target = compile_target_names or test_target_names 7961cb0ef41Sopenharmony_ci result_dict = { 7971cb0ef41Sopenharmony_ci "test_targets": test_target_names, 7981cb0ef41Sopenharmony_ci "status": found_dependency_string 7991cb0ef41Sopenharmony_ci if found_at_least_one_target 8001cb0ef41Sopenharmony_ci else no_dependency_string, 8011cb0ef41Sopenharmony_ci "compile_targets": list(set(compile_target_names) | set(test_target_names)), 8021cb0ef41Sopenharmony_ci } 8031cb0ef41Sopenharmony_ci if calculator.invalid_targets: 8041cb0ef41Sopenharmony_ci result_dict["invalid_targets"] = calculator.invalid_targets 8051cb0ef41Sopenharmony_ci _WriteOutput(params, **result_dict) 8061cb0ef41Sopenharmony_ci 8071cb0ef41Sopenharmony_ci except Exception as e: 8081cb0ef41Sopenharmony_ci _WriteOutput(params, error=str(e)) 809