def setup_json_scheduler(build_root, native): """Return a build graph and scheduler configured for BLD.json files under the given build root. :rtype :class:`pants.engine.scheduler.LocalScheduler` """ symbol_table = ExampleTable() # Register "literal" subjects required for these tasks. # TODO: Replace with `Subsystems`. address_mapper = AddressMapper(build_patterns=('BLD.json',), parser=JsonParser(symbol_table)) work_dir = os_path_join(build_root, '.pants.d') project_tree = FileSystemProjectTree(build_root) goals = { 'compile': Classpath, # TODO: to allow for running resolve alone, should split out a distinct 'IvyReport' product. 'resolve': Classpath, 'list': BuildFileAddresses, GenGoal.name(): GenGoal, 'ls': Snapshot, 'cat': FilesContent, } tasks = [ # Codegen GenGoal.rule(), gen_apache_java_thrift, gen_apache_python_thrift, gen_scrooge_scala_thrift, gen_scrooge_java_thrift, SingletonRule(Scrooge, Scrooge(Address.parse('src/scala/scrooge'))) ] + [ # scala dependency inference reify_scala_sources, select_package_address, calculate_package_search_path, SingletonRule(SourceRoots, SourceRoots(('src/java','src/scala'))), ] + [ # Remote dependency resolution ivy_resolve, select_rev, ] + [ # Compilers isolate_resources, write_name_file, javac, scalac, ] + ( create_graph_rules(address_mapper, symbol_table) ) + ( create_fs_rules() ) return LocalScheduler(work_dir, goals, tasks, project_tree, native)
def setup_json_scheduler(build_root, native): """Return a build graph and scheduler configured for BLD.json files under the given build root. :rtype :class:`pants.engine.scheduler.SchedulerSession` """ symbol_table = ExampleTable() # Register "literal" subjects required for these rules. address_mapper = AddressMapper(build_patterns=('BLD.json',), parser=JsonParser(symbol_table)) work_dir = os_path_join(build_root, '.pants.d') project_tree = FileSystemProjectTree(build_root) rules = [ # Codegen GenGoal.rule(), gen_apache_java_thrift, gen_apache_python_thrift, gen_scrooge_scala_thrift, gen_scrooge_java_thrift, SingletonRule(Scrooge, Scrooge(Address.parse('src/scala/scrooge'))) ] + [ # scala dependency inference reify_scala_sources, select_package_address, calculate_package_search_path, SingletonRule(SourceRoots, SourceRoots(('src/java','src/scala'))), ] + [ # Remote dependency resolution ivy_resolve, select_rev, ] + [ # Compilers isolate_resources, write_name_file, javac, scalac, ] + ( create_graph_rules(address_mapper, symbol_table) ) + ( create_fs_rules() ) scheduler = Scheduler(native, project_tree, work_dir, rules, DEFAULT_EXECUTION_OPTIONS, None, None) return scheduler.new_session()
def create_graph_rules(address_mapper, symbol_table): """Creates tasks used to parse Structs from BUILD files. :param address_mapper_key: The subject key for an AddressMapper instance. :param symbol_table: A SymbolTable instance to provide symbols for Address lookups. """ symbol_table_constraint = symbol_table.constraint() partial_hydrate_struct = functools.partial(hydrate_struct, symbol_table_constraint) partial_hydrate_struct.__name__ = 'hydrate_struct' return [ # A singleton to provide the AddressMapper. SingletonRule(AddressMapper, address_mapper), # Support for resolving Structs from Addresses. TaskRule( symbol_table_constraint, [Select(AddressMapper), Select(UnhydratedStruct)], partial_hydrate_struct, input_gets=[Get(symbol_table_constraint, Address)], ), resolve_unhydrated_struct, # BUILD file parsing. parse_address_family, # Spec handling: locate directories that contain build files, and request # AddressFamilies for each of them. addresses_from_address_families, # Root rules representing parameters that might be provided via root subjects. RootRule(Address), RootRule(BuildFileAddress), RootRule(BuildFileAddresses), RootRule(Specs), ]
def create_graph_rules(address_mapper, symbol_table_cls): """Creates tasks used to parse Structs from BUILD files. :param address_mapper_key: The subject key for an AddressMapper instance. :param symbol_table_cls: A SymbolTable class to provide symbols for Address lookups. """ symbol_table_constraint = symbol_table_cls.constraint() return [ TaskRule( BuildFilesCollection, [SelectDependencies(BuildFiles, BuildDirs, field_types=(Dir, ))], BuildFilesCollection), # A singleton to provide the AddressMapper. SingletonRule(AddressMapper, address_mapper), # Support for resolving Structs from Addresses. TaskRule(symbol_table_constraint, [ Select(AddressMapper), Select(UnhydratedStruct), SelectDependencies(symbol_table_constraint, UnhydratedStruct, field_types=(Address, )) ], hydrate_struct), resolve_unhydrated_struct, # BUILD file parsing. parse_address_family, build_files, buildfile_path_globs_for_dir, # Spec handling: locate directories that contain build files, and request # AddressFamilies for each of them. addresses_from_address_families, filter_build_dirs, spec_to_globs, ]
def test_noop_removal_in_subgraph(self): @rule(Exactly(A), [Select(C)]) def a_from_c(c): pass @rule(Exactly(A), []) def a(): pass rules = [ a_from_c, a, SingletonRule(B, B()), ] subgraph = self.create_subgraph(A, rules, SubA(), validate=False) self.assert_equal_with_printing( dedent(""" digraph { // root subject types: SubA // root entries "Select(A) for ()" [color=blue] "Select(A) for ()" -> {"(A, [], a) for ()"} // internal entries "(A, [], a) for ()" -> {} }""").strip(), subgraph)
def create(self, build_patterns=None, parser=None): address_mapper = AddressMapper(build_patterns=build_patterns, parser=parser) rules = create_fs_rules() + create_graph_rules(address_mapper) + [SingletonRule(SymbolTable, TestTable())] project_tree = self.mk_fs_tree(os.path.join(os.path.dirname(__file__), 'examples')) scheduler = self.mk_scheduler(rules=rules, project_tree=project_tree) return scheduler
def test_javac_compilation_example_rust_success(self): sources = PathGlobs.create('', include=['scheduler_inputs/src/java/simple/Simple.java']) scheduler = self.mk_scheduler_in_example_fs([ ExecuteProcess.create_in( product_type=ExecuteProcessRequest, input_selectors=(Select(Javac), Select(Snapshot), Select(JavaOutputDir)), input_conversion=process_request_java_args_from_java_sources), SingletonRule(JavaOutputDir, JavaOutputDir('testing')), SingletonRule(Javac, Javac()), ]) req = scheduler.product_request(ExecuteProcessRequest, [sources]) request = scheduler.execution_request([ExecuteProcessResult], req) root_entries = scheduler.execute(request).root_products self.assertEquals(1, len(root_entries)) state = self.assertFirstEntryIsReturn(root_entries, scheduler, request) execution_result = state.value self.assertEqual(0, execution_result.exit_code)
def test_select_dependencies_non_matching_subselector_because_of_singleton(self): rules = [ TaskRule(Exactly(A), [SelectDependencies(B, SubA, field_types=(D,))], noop), SingletonRule(C, C()), ] subgraph = self.create_subgraph(A, rules, SubA()) self.assert_equal_with_printing(dedent(""" digraph { // empty graph }""").strip(), subgraph)
def test_javac_compilation_example(self): sources = PathGlobs.create( '', include=['scheduler_inputs/src/java/simple/Simple.java']) scheduler = self.mk_scheduler_in_example_fs([ SnapshottedProcess.create( ClasspathEntry, Javac, (Select(Snapshot), Select(JavaOutputDir)), java_sources_to_javac_args, process_result_to_classpath_entry), SingletonRule(JavaOutputDir, JavaOutputDir('build')), SingletonRule(Javac, Javac()), ]) request = scheduler.execution_request([ClasspathEntry], [sources]) root_entries = scheduler.execute(request).root_products self.assertEquals(1, len(root_entries)) state = self.assertFirstEntryIsReturn(root_entries, scheduler) classpath_entry = state.value self.assertIsInstance(classpath_entry, ClasspathEntry) self.assertTrue( os.path.exists( os.path.join(classpath_entry.path, 'simple', 'Simple.class')))
def test_javac_version_example(self): sources = PathGlobs.create('', include=['inputs/src/java/simple/Simple.java']) scheduler = self.mk_scheduler_in_example_fs([ ExecuteProcess.create_in(product_type=ExecuteProcessRequest, input_selectors=(Select(Javac),), input_conversion=process_request_from_java_sources), SingletonRule(Javac, Javac()), ]) req = scheduler.product_request(ExecuteProcessRequest, [sources]) request = scheduler.execution_request([ExecuteProcessResult], req) root_entries = scheduler.execute(request).root_products self.assertEquals(1, len(root_entries)) state = self.assertFirstEntryIsReturn(root_entries, scheduler, request) result = state.value self.assertEqual(0, result.exit_code) self.assertIn('javac', result.stderr)
def test_ruleset_with_failure_due_to_incompatible_subject_for_singleton(self): rules = [ RootRule(A), TaskRule(D, [Select(C)], noop), SingletonRule(B, B()), ] with self.assertRaises(ValueError) as cm: create_scheduler(rules) # This error message could note near matches like the singleton. self.assert_equal_with_printing(dedent(""" Rules with errors: 1 (D, (Select(C),), noop): no matches for Select(C) with subject types: A """).strip(), str(cm.exception))
def test_get_with_matching_singleton(self): rules = [ TaskRule(Exactly(A), [Select(SubA)], noop, input_gets=[Get(B, C)]), SingletonRule(B, B()), ] subgraph = self.create_subgraph(A, rules, SubA()) self.assert_equal_with_printing( dedent(""" digraph { // root subject types: SubA // root entries "Select(A) for SubA" [color=blue] "Select(A) for SubA" -> {"(A, [Select(SubA)], [Get(B, C)], noop) for SubA"} // internal entries "(A, [Select(SubA)], [Get(B, C)], noop) for SubA" -> {"Param(SubA)" "Singleton(B(), B)"} }""").strip(), subgraph)
def test_failed_output_conversion_propagates_throw(self): scheduler = self.mk_scheduler_in_example_fs([ # subject to files / product of subject to files for snapshot. SnapshottedProcess.create(product_type=Concatted, binary_type=ShellCatToOutFile, input_selectors=(Select(Snapshot),), input_conversion=file_list_to_args_for_cat_with_snapshot_subjects_and_output_file, output_conversion=fail_process_result), SingletonRule(ShellCatToOutFile, ShellCatToOutFile()), ]) request = scheduler.execution_request([Concatted], [PathGlobs.create('', include=['fs_test/a/b/*'])]) root_entries = scheduler.execute(request).root_products self.assertEquals(1, len(root_entries)) self.assertFirstEntryIsThrow(root_entries, in_msg='Failed in output conversion!')
def test_ruleset_with_failure_due_to_incompatible_subject_for_singleton( self): rules = [ RootRule(A), TaskRule(D, [Select(C)], noop), SingletonRule(B, B()), ] with self.assertRaises(Exception) as cm: create_scheduler(rules) # This error message could note near matches like the singleton. self.assert_equal_with_printing( dedent(""" Rules with errors: 1 (D, [Select(C)], noop): No rule was available to compute C with parameter type A """).strip(), str(cm.exception))
def test_failed_command_propagates_throw(self): scheduler = self.mk_scheduler_in_example_fs([ # subject to files / product of subject to files for snapshot. SnapshottedProcess.create(product_type=Concatted, binary_type=ShellFailCommand, input_selectors=tuple(), input_conversion=empty_process_request, output_conversion=fail_process_result), SingletonRule(ShellFailCommand, ShellFailCommand()), ]) request = scheduler.execution_request([Concatted], [PathGlobs.create('', include=['fs_test/a/b/*'])]) root_entries = scheduler.execute(request).root_products self.assertEquals(1, len(root_entries)) self.assertFirstEntryIsThrow(root_entries, in_msg='Running ShellFailCommand failed with non-zero exit code: 1')
def test_noop_removal_in_subgraph(self): rules = [ TaskRule(Exactly(A), [Select(C)], noop), TaskRule(Exactly(A), [], noop), SingletonRule(B, B()), ] subgraph = self.create_subgraph(A, rules, SubA()) self.assert_equal_with_printing( dedent(""" digraph { // root subject types: SubA // root entries "Select(A) for SubA" [color=blue] "Select(A) for SubA" -> {"(A, (,), noop) of SubA"} // internal entries "(A, (,), noop) of SubA" -> {} }""").strip(), subgraph)
def test_get_with_matching_singleton(self): rules = [ TaskRule(Exactly(A), [Select(SubA)], noop, input_gets=[Get(B, C)]), SingletonRule(B, B()), ] subgraph = self.create_subgraph(A, rules, SubA()) #TODO perhaps singletons should be marked in the dot format somehow self.assert_equal_with_printing(dedent(""" digraph { // root subject types: SubA // root entries "Select(A) for SubA" [color=blue] "Select(A) for SubA" -> {"(A, (Select(SubA),), [Get(B, C)], noop) of SubA"} // internal entries "(A, (Select(SubA),), [Get(B, C)], noop) of SubA" -> {"SubjectIsProduct(SubA)" "Singleton(B(), B)"} }""").strip(), subgraph)
def test_integration_concat_with_snapshot_subjects_test(self): scheduler = self.mk_scheduler_in_example_fs([ # subject to files / product of subject to files for snapshot. SnapshottedProcess.create(product_type=Concatted, binary_type=ShellCatToOutFile, input_selectors=(Select(Snapshot),), input_conversion=file_list_to_args_for_cat_with_snapshot_subjects_and_output_file, output_conversion=process_result_to_concatted_from_outfile), SingletonRule(ShellCatToOutFile, ShellCatToOutFile()), ]) request = scheduler.execution_request([Concatted], [PathGlobs.create('', include=['fs_test/a/b/*'])]) root_entries = scheduler.execute(request).root_products self.assertEquals(1, len(root_entries)) state = self.assertFirstEntryIsReturn(root_entries, scheduler, request) concatted = state.value self.assertEqual(Concatted('one\ntwo\n'), concatted)
def test_get_with_matching_singleton(self): @rule(Exactly(A), [Select(SubA)]) def a_from_suba(suba): _ = yield Get(B, C, C()) # noqa: F841 rules = [ a_from_suba, SingletonRule(B, B()), ] subgraph = self.create_subgraph(A, rules, SubA()) self.assert_equal_with_printing( dedent(""" digraph { // root subject types: SubA // root entries "Select(A) for SubA" [color=blue] "Select(A) for SubA" -> {"(A, [Select(SubA)], [Get(B, C)], a_from_suba) for SubA"} // internal entries "(A, [Select(SubA)], [Get(B, C)], a_from_suba) for SubA" -> {"Param(SubA)" "Singleton(B(), B)"} }""").strip(), subgraph)
def create_graph_rules(address_mapper): """Creates tasks used to parse Structs from BUILD files. :param address_mapper_key: The subject key for an AddressMapper instance. :param symbol_table: A SymbolTable instance to provide symbols for Address lookups. """ return [ # A singleton to provide the AddressMapper. SingletonRule(AddressMapper, address_mapper), # Support for resolving Structs from Addresses. hydrate_struct, resolve_unhydrated_struct, # BUILD file parsing. parse_address_family, # Spec handling: locate directories that contain build files, and request # AddressFamilies for each of them. addresses_from_address_families, # Root rules representing parameters that might be provided via root subjects. RootRule(Address), RootRule(BuildFileAddress), RootRule(BuildFileAddresses), RootRule(Specs), ]
def create_native_environment_rules(): return [ SingletonRule(Platform, Platform.current), ]
def setup_legacy_graph_extended( pants_ignore_patterns, workdir, local_store_dir, build_file_imports_behavior, options_bootstrapper, build_configuration, build_root=None, native=None, glob_match_error_behavior=None, build_ignore_patterns=None, exclude_target_regexps=None, subproject_roots=None, include_trace_on_error=True, execution_options=None, ): """Construct and return the components necessary for LegacyBuildGraph construction. :param list pants_ignore_patterns: A list of path ignore patterns for FileSystemProjectTree, usually taken from the '--pants-ignore' global option. :param str workdir: The pants workdir. :param local_store_dir: The directory to use for storing the engine's LMDB store in. :param build_file_imports_behavior: How to behave if a BUILD file being parsed tries to use import statements. Valid values: "allow", "warn", "error". :type build_file_imports_behavior: string :param str build_root: A path to be used as the build root. If None, then default is used. :param Native native: An instance of the native-engine subsystem. :param options_bootstrapper: A `OptionsBootstrapper` object containing bootstrap options. :type options_bootstrapper: :class:`pants.options.options_bootstrapper.OptionsBootstrapper` :param build_configuration: The `BuildConfiguration` object to get build file aliases from. :type build_configuration: :class:`pants.build_graph.build_configuration.BuildConfiguration` :param glob_match_error_behavior: How to behave if a glob specified for a target's sources or bundles does not expand to anything. :type glob_match_error_behavior: :class:`pants.option.global_options.GlobMatchErrorBehavior` :param list build_ignore_patterns: A list of paths ignore patterns used when searching for BUILD files, usually taken from the '--build-ignore' global option. :param list exclude_target_regexps: A list of regular expressions for excluding targets. :param list subproject_roots: Paths that correspond with embedded build roots under the current build root. :param bool include_trace_on_error: If True, when an error occurs, the error message will include the graph trace. :param execution_options: Option values for (remote) process execution. :type execution_options: :class:`pants.option.global_options.ExecutionOptions` :returns: A LegacyGraphScheduler. """ build_root = build_root or get_buildroot() build_configuration = build_configuration or BuildConfigInitializer.get( options_bootstrapper) build_file_aliases = build_configuration.registered_aliases() rules = build_configuration.rules() console = Console() symbol_table = LegacySymbolTable(build_file_aliases) project_tree = FileSystemProjectTree(build_root, pants_ignore_patterns) execution_options = execution_options or DEFAULT_EXECUTION_OPTIONS # Register "literal" subjects required for these rules. parser = LegacyPythonCallbacksParser(symbol_table, build_file_aliases, build_file_imports_behavior) address_mapper = AddressMapper( parser=parser, build_ignore_patterns=build_ignore_patterns, exclude_target_regexps=exclude_target_regexps, subproject_roots=subproject_roots) # Load the native backend. native = native or Native.create() # Create a Scheduler containing graph and filesystem rules, with no installed goals. The # LegacyBuildGraph will explicitly request the products it needs. rules = ( [ SingletonRule.from_instance(console), SingletonRule.from_instance( GlobMatchErrorBehavior.create(glob_match_error_behavior)), SingletonRule.from_instance(build_configuration), ] + create_legacy_graph_tasks(symbol_table) + create_fs_rules() + create_process_rules() + create_graph_rules(address_mapper, symbol_table) + create_options_parsing_rules() + create_core_rules() + # TODO: This should happen automatically, but most tests (e.g. tests/python/pants_test/auth) fail if it's not here: [run_python_test] + rules) goal_map = EngineInitializer._make_goal_map_from_rules(rules) scheduler = Scheduler( native, project_tree, workdir, local_store_dir, rules, execution_options, include_trace_on_error=include_trace_on_error, ) return LegacyGraphScheduler(scheduler, symbol_table, console, goal_map)
def create_snapshot_rules(): """Intrinsically replaced on the rust side.""" return [ SingletonRule(_Snapshots, _Snapshots('/dev/null')) ]
def setup_legacy_graph_extended( pants_ignore_patterns, workdir, build_file_imports_behavior, build_configuration, build_root=None, native=None, glob_match_error_behavior=None, rules=None, build_ignore_patterns=None, exclude_target_regexps=None, subproject_roots=None, include_trace_on_error=True, remote_store_server=None, remote_execution_server=None ): """Construct and return the components necessary for LegacyBuildGraph construction. :param list pants_ignore_patterns: A list of path ignore patterns for FileSystemProjectTree, usually taken from the '--pants-ignore' global option. :param str workdir: The pants workdir. :param build_file_imports_behavior: How to behave if a BUILD file being parsed tries to use import statements. Valid values: "allow", "warn", "error". :type build_file_imports_behavior: string :param str build_root: A path to be used as the build root. If None, then default is used. :param Native native: An instance of the native-engine subsystem. :param build_configuration: The `BuildConfiguration` object to get build file aliases from. :type build_configuration: :class:`pants.build_graph.build_configuration.BuildConfiguration` :param glob_match_error_behavior: How to behave if a glob specified for a target's sources or bundles does not expand to anything. :type glob_match_error_behavior: :class:`pants.option.global_options.GlobMatchErrorBehavior` :param list build_ignore_patterns: A list of paths ignore patterns used when searching for BUILD files, usually taken from the '--build-ignore' global option. :param list exclude_target_regexps: A list of regular expressions for excluding targets. :param list subproject_roots: Paths that correspond with embedded build roots under the current build root. :param bool include_trace_on_error: If True, when an error occurs, the error message will include the graph trace. :returns: A LegacyGraphScheduler. """ build_root = build_root or get_buildroot() build_configuration = build_configuration or BuildConfigInitializer.get(OptionsBootstrapper()) build_file_aliases = build_configuration.registered_aliases() rules = rules or build_configuration.rules() or [] symbol_table = LegacySymbolTable(build_file_aliases) project_tree = FileSystemProjectTree(build_root, pants_ignore_patterns) # Register "literal" subjects required for these rules. parser = LegacyPythonCallbacksParser( symbol_table, build_file_aliases, build_file_imports_behavior ) address_mapper = AddressMapper(parser=parser, build_ignore_patterns=build_ignore_patterns, exclude_target_regexps=exclude_target_regexps, subproject_roots=subproject_roots) # Load the native backend. native = native or Native.create() # Create a Scheduler containing graph and filesystem rules, with no installed goals. The # LegacyBuildGraph will explicitly request the products it needs. rules = ( [ SingletonRule.from_instance(GlobMatchErrorBehavior.create(glob_match_error_behavior)), SingletonRule.from_instance(build_configuration), ] + create_legacy_graph_tasks(symbol_table) + create_fs_rules() + create_process_rules() + create_graph_rules(address_mapper, symbol_table) + create_options_parsing_rules() + rules ) scheduler = Scheduler( native, project_tree, workdir, rules, remote_store_server, remote_execution_server, include_trace_on_error=include_trace_on_error, ) return LegacyGraphScheduler(scheduler, symbol_table)
def setup_legacy_graph_extended(pants_ignore_patterns, workdir, build_file_imports_behavior, build_file_aliases, build_root=None, native=None, glob_match_error_behavior=None, rules=None, build_ignore_patterns=None, exclude_target_regexps=None, subproject_roots=None, include_trace_on_error=True, remote_store_server=None, remote_execution_server=None): """Construct and return the components necessary for LegacyBuildGraph construction. :param list pants_ignore_patterns: A list of path ignore patterns for FileSystemProjectTree, usually taken from the '--pants-ignore' global option. :param str workdir: The pants workdir. :param build_file_imports_behavior: How to behave if a BUILD file being parsed tries to use import statements. Valid values: "allow", "warn", "error". :type build_file_imports_behavior: string :param str build_root: A path to be used as the build root. If None, then default is used. :param Native native: An instance of the native-engine subsystem. :param build_file_aliases: BuildFileAliases to register. :type build_file_aliases: :class:`pants.build_graph.build_file_aliases.BuildFileAliases` :param glob_match_error_behavior: How to behave if a glob specified for a target's sources or bundles does not expand to anything. :type glob_match_error_behavior: :class:`pants.option.global_options.GlobMatchErrorBehavior` :param list build_ignore_patterns: A list of paths ignore patterns used when searching for BUILD files, usually taken from the '--build-ignore' global option. :param list exclude_target_regexps: A list of regular expressions for excluding targets. :param list subproject_roots: Paths that correspond with embedded build roots under the current build root. :param bool include_trace_on_error: If True, when an error occurs, the error message will include the graph trace. :returns: A LegacyGraphScheduler. """ build_root = build_root or get_buildroot() if not rules: rules = [] symbol_table = LegacySymbolTable(build_file_aliases) project_tree = FileSystemProjectTree(build_root, pants_ignore_patterns) # Register "literal" subjects required for these rules. parser = LegacyPythonCallbacksParser(symbol_table, build_file_aliases, build_file_imports_behavior) address_mapper = AddressMapper( parser=parser, build_ignore_patterns=build_ignore_patterns, exclude_target_regexps=exclude_target_regexps, subproject_roots=subproject_roots) # Load the native backend. native = native or Native.create() # Create a Scheduler containing graph and filesystem rules, with no installed goals. The # LegacyBuildGraph will explicitly request the products it needs. rules = ( create_legacy_graph_tasks(symbol_table) + create_fs_rules() + create_process_rules() + create_graph_rules(address_mapper, symbol_table) + [ SingletonRule( GlobMatchErrorBehavior, GlobMatchErrorBehavior.create(glob_match_error_behavior)) ] + rules) scheduler = Scheduler( native, project_tree, workdir, rules, remote_store_server, remote_execution_server, include_trace_on_error=include_trace_on_error, ) return LegacyGraphScheduler(scheduler, symbol_table)
def rules(): return [ RootRule(NativeToolchain), SingletonRule(Platform, Platform()), ]