def plan(self, scheduler, product_type, subject, configuration=None): sources = list( subject.sources.iter_paths(base_path=subject.address.spec_path, ext=self.source_ext)) if not sources: # TODO(John Sirois): Abstract a ~SourcesConsumerPlanner that can grab sources of given types # or else defer to a code generator like we do here. As it stands, the planner must # explicitly allow for code generators and this repeated code / foresight can easily be # missed in new compilers, and other source-using tasks. Once done though, code gen can be # introduced to any nesting depth, ie: code gen '.thrift' files. # This is a dep graph "hole", we depend on the thing but don't know what it is. Either it # could be something that gets transformed in to our compile input source extension (codegen) # or transformed into a `Classpath` product by some other compiler targeting the jvm. sources = scheduler.promise(subject, Sources.of(self.source_ext), configuration=configuration) subject = sources.subject classpath_promises = [] for dep, dep_config in self.iter_configured_dependencies(subject): # This could recurse to us (or be satisfied by IvyResolve, another jvm compiler, etc. # depending on the dep type). classpath = scheduler.promise(dep, Classpath, configuration=dep_config) classpath_promises.append(classpath) return Plan(func_or_task_type=self.compile_task_type, subjects=(subject, ), sources=sources, classpath=classpath_promises)
def plan(self, scheduler, product_type, subject, configuration=None): if isinstance(subject, Jar): # This plan is only used internally, the finalized plan will s/jar/jars/ for a single global # resolve. return Plan(func_or_task_type=IvyResolve, subjects=(subject, ), jar=subject)
def test_codegen_simple(self): build_request = BuildRequest(goals=['compile'], addressable_roots=[self.java.address]) execution_graph = self.scheduler.execution_graph(build_request) plans = list(execution_graph.walk()) self.assertEqual(4, len(plans)) thrift_jars = [ Jar(org='org.apache.thrift', name='libthrift', rev='0.9.2'), Jar(org='commons-lang', name='commons-lang', rev='2.5'), self.graph.resolve(Address.parse('src/thrift:slf4j-api')) ] jars = [self.guava] + thrift_jars # Independent leaves 1st self.assertEqual( {(Sources.of('.java'), Plan(func_or_task_type=gen_apache_thrift, subjects=[self.thrift], strict=True, rev='0.9.2', gen='java', sources=['src/thrift/codegen/simple/simple.thrift'])), (Classpath, Plan(func_or_task_type=IvyResolve, subjects=jars, jars=jars))}, set(self.extract_product_type_and_plan(p) for p in plans[0:2])) # The rest is linked. self.assertEqual( (Classpath, Plan(func_or_task_type=Javac, subjects=[self.thrift], sources=Promise(Sources.of('.java'), self.thrift), classpath=[Promise(Classpath, jar) for jar in thrift_jars])), self.extract_product_type_and_plan(plans[2])) self.assertEqual((Classpath, Plan(func_or_task_type=Javac, subjects=[self.java], sources=['src/java/codegen/simple/Simple.java'], classpath=[ Promise(Classpath, self.guava), Promise(Classpath, self.thrift) ])), self.extract_product_type_and_plan(plans[3]))
def finalize_plans(self, plans): subjects = set() jars = OrderedSet() for plan in plans: subjects.update(plan.subjects) jars.add(plan.jar) global_plan = Plan(func_or_task_type=IvyResolve, subjects=subjects, jars=list(jars)) return [global_plan]
def assert_resolve_only(self, goals, root_specs, jars): build_request = BuildRequest(goals=goals, addressable_roots=[Address.parse(spec) for spec in root_specs]) execution_graph = self.scheduler.execution_graph(build_request) plans = list(execution_graph.walk()) self.assertEqual(1, len(plans)) self.assertEqual((Classpath, Plan(func_or_task_type=IvyResolve, subjects=jars, jars=list(jars))), self.extract_product_type_and_plan(plans[0]))
def plan(self, scheduler, product_type, subject, configuration=None): if not isinstance(subject, Target): return name_config = filter( lambda x: isinstance(x, BuildPropertiesConfiguration), subject.configurations) if not name_config: return assert product_type == Classpath return Plan(func_or_task_type=write_name_file, subjects=(subject, ), name=subject.name)
def test_gen(self): build_request = BuildRequest(goals=['gen'], addressable_roots=[self.thrift.address]) execution_graph = self.scheduler.execution_graph(build_request) plans = list(execution_graph.walk()) self.assertEqual(1, len(plans)) self.assertEqual((Sources.of('.java'), Plan(func_or_task_type=gen_apache_thrift, subjects=[self.thrift], strict=True, rev='0.9.2', gen='java', sources=['src/thrift/codegen/simple/simple.thrift'])), self.extract_product_type_and_plan(plans[0]))
def test_gen_noop(self): # TODO(John Sirois): Ask around - is this OK? # This is different than today. There is a gen'able target reachable from the java target, but # the scheduler 'pull-seeding' has ApacheThriftPlanner stopping short since the subject it's # handed is not thrift. build_request = BuildRequest(goals=['gen'], addressable_roots=[self.java.address]) execution_graph = self.scheduler.execution_graph(build_request) plans = list(execution_graph.walk()) self.assertEqual(1, len(plans)) self.assertEqual((Sources.of('.java'), Plan(func_or_task_type=lift_native_product, subjects=[self.java], subject=self.java, product_type=Sources.of('.java'))), self.extract_product_type_and_plan(plans[0]))
def plan(self, scheduler, product_type, subject, configuration=None): thrift_sources = list( subject.sources.iter_paths(base_path=subject.address.spec_path, ext='.thrift')) if not thrift_sources: raise self.Error('No thrift sources for {!r} from {!r}.'.format( product_type, subject)) config = self._extract_thrift_config(product_type, subject, configuration=configuration) subject = Subject(subject, alternate=Target(dependencies=config.deps)) inputs = self.plan_parameters(scheduler, product_type, subject, config) return Plan(func_or_task_type=self.gen_func, subjects=(subject, ), sources=thrift_sources, **inputs)
def plan(self, scheduler, product_type, subject, configuration=None): if not isinstance(subject, Target): return None thrift_sources = list( subject.sources.iter_paths(base_path=subject.address.spec_path, ext='.thrift')) if not thrift_sources: return None config = self.extract_thrift_config(product_type, subject, configuration=configuration) if config is None: return None subject = Subject(subject, alternate=Target(dependencies=config.deps)) inputs = self.plan_parameters(scheduler, product_type, subject, config) return Plan(func_or_task_type=self.gen_func, subjects=(subject, ), sources=thrift_sources, **inputs)
def plan(self, scheduler, product_type, subject, configuration=None): return Plan(unpickable_result_func, (subject, ))
def plan(self, scheduler, product_type, subject, configuration=None): # Nested functions like this lambda are unpicklable. return Plan(lambda: None, (subject, ))
def plan(self, scheduler, product_type, subject, configuration=None): assert product_type == Classpath return Plan(func_or_task_type=write_name_file, subjects=(subject, ), name=subject.name)