def __init__(self, root_dir, parser, argv): Command.__init__(self, root_dir, parser, argv) if not self.args: self.error("A spec argument is required") try: specs_end = self.args.index('--') if len(self.args) > specs_end: self.build_args = self.args.__getslice__( specs_end + 1, len(self.args) + 1) else: self.build_args = [] except ValueError: specs_end = 1 self.build_args = self.args[1:] if len(self.args) > 1 else [] self.targets = OrderedSet() for spec in self.args.__getslice__(0, specs_end): try: address = Address.parse(root_dir, spec) except: self.error("Problem parsing spec %s: %s" % (spec, traceback.format_exc())) try: target = Target.get(address) except: self.error("Problem parsing BUILD target %s: %s" % (address, traceback.format_exc())) try: InternalTarget.check_cycles(target) except CycleException as e: self.error("Target contains an internal dependency cycle: %s" % e) if not target: self.error("Target %s does not exist" % address) if not target.address.is_meta: target.address.is_meta = self.options.is_meta or address.is_meta self.targets.add(target) self.is_ide = self.options.is_ide self.ide_transitivity = self.options.ide_transitivity
def __init__(self, root_dir, parser, argv): Command.__init__(self, root_dir, parser, argv) if not self.args: self.error("A spec argument is required") try: specs_end = self.args.index('--') if len(self.args) > specs_end: self.build_args = self.args.__getslice__(specs_end + 1, len(self.args) + 1) else: self.build_args = [] except ValueError: specs_end = 1 self.build_args = self.args[1:] if len(self.args) > 1 else [] self.targets = OrderedSet() for spec in self.args.__getslice__(0, specs_end): try: address = Address.parse(root_dir, spec) except: self.error("Problem parsing spec %s: %s" % (spec, traceback.format_exc())) try: target = Target.get(address) except: self.error("Problem parsing BUILD target %s: %s" % (address, traceback.format_exc())) try: InternalTarget.check_cycles(target) except CycleException as e: self.error("Target contains an internal dependency cycle: %s" % e) if not target: self.error("Target %s does not exist" % address) if not target.address.is_meta: target.address.is_meta = self.options.is_meta or address.is_meta self.targets.add(target) self.is_ide = self.options.is_ide self.ide_transitivity = self.options.ide_transitivity
def extract_target(java_targets, name = None): """Extracts a minimal set of linked targets from the given target's internal transitive dependency set. The root target in the extracted target set is returned. The algorithm does a topological sort of the internal targets and then tries to coalesce targets of a given type. Any target with a custom ant build xml will be excluded from the coalescing.""" # TODO(John Sirois): this is broken - representative_target is not necessarily representative representative_target = list(java_targets)[0] meta_target_base_name = "fast-%s" % (name if name else representative_target.name) provides = None deployjar = hasattr(representative_target, 'deployjar') and representative_target.deployjar buildflags = representative_target.buildflags def create_target(target_type, target_name, target_index, targets): def name(name): return "%s-%s-%d" % (target_name, name, target_index) if target_type == JavaProtobufLibrary: return JavaProtobufLibrary._aggregate(name('protobuf'), provides, buildflags, targets) elif target_type == JavaThriftLibrary: return JavaThriftLibrary._aggregate(name('thrift'), provides, buildflags, targets) elif target_type == JavaLibrary: return JavaLibrary._aggregate(name('java'), provides, deployjar, buildflags, targets) elif target_type == ScalaLibrary: return ScalaLibrary._aggregate(name('scala'), provides, deployjar, buildflags, targets) elif target_type == JavaTests: return JavaTests._aggregate(name('java-tests'), buildflags, targets) elif target_type == ScalaTests: return ScalaTests._aggregate(name('scala-tests'), buildflags, targets) else: raise Exception("Cannot aggregate targets of type: %s" % target_type) # chunk up our targets by type & custom build xml coalesced = InternalTarget.coalesce_targets(java_targets) coalesced = list(reversed(coalesced)) start_type = type(coalesced[0]) start = 0 descriptors = [] for current in range(0, len(coalesced)): current_target = coalesced[current] current_type = type(current_target) if current_target.custom_antxml_path: if start < current: # if we have a type chunk to our left, record it descriptors.append((start_type, coalesced[start:current])) # record a chunk containing just the target that has the custom build xml to be conservative descriptors.append((current_type, [current_target])) start = current + 1 if current < (len(coalesced) - 1): start_type = type(coalesced[start]) elif start_type != current_type: # record the type chunk we just left descriptors.append((start_type, coalesced[start:current])) start = current start_type = current_type if start < len(coalesced): # record the tail chunk descriptors.append((start_type, coalesced[start:])) # build meta targets aggregated from the chunks and keep track of which targets end up in which # meta targets meta_targets_by_target_id = dict() targets_by_meta_target = [] for (target_type, targets), index in zip(descriptors, reversed(range(0, len(descriptors)))): meta_target = create_target(target_type, meta_target_base_name, index, targets) targets_by_meta_target.append((meta_target, targets)) for target in targets: meta_targets_by_target_id[target._id] = meta_target # calculate the other meta-targets (if any) each meta-target depends on extra_targets_by_meta_target = [] for meta_target, targets in targets_by_meta_target: meta_deps = set() custom_antxml_path = None for target in targets: if target.custom_antxml_path: custom_antxml_path = target.custom_antxml_path for dep in target.resolved_dependencies: if is_jvm(dep): meta = meta_targets_by_target_id[dep._id] if meta != meta_target: meta_deps.add(meta) extra_targets_by_meta_target.append((meta_target, meta_deps, custom_antxml_path)) def lift_excludes(meta_target): excludes = set() def lift(target): if target.excludes: excludes.update(target.excludes) for jar_dep in target.jar_dependencies: excludes.update(jar_dep.excludes) for internal_dep in target.internal_dependencies: lift(internal_dep) lift(meta_target) return excludes # link in the extra inter-meta deps meta_targets = [] for meta_target, extra_deps, custom_antxml_path in extra_targets_by_meta_target: meta_targets.append(meta_target) meta_target.update_dependencies(extra_deps) meta_target.excludes = lift_excludes(meta_target) meta_target.custom_antxml_path = custom_antxml_path sorted_meta_targets = InternalTarget.sort_targets(meta_targets) def prune_metas(target): if sorted_meta_targets: try: sorted_meta_targets.remove(target) except ValueError: # we've already removed target in the current walk pass # link any disconnected meta_target graphs so we can return 1 root target root = None while sorted_meta_targets: new_root = sorted_meta_targets[0] new_root.walk(prune_metas, is_jvm) if root: new_root.update_dependencies([root]) root = new_root return root
def extract_target(java_targets, name=None): """Extracts a minimal set of linked targets from the given target's internal transitive dependency set. The root target in the extracted target set is returned. The algorithm does a topological sort of the internal targets and then tries to coalesce targets of a given type. Any target with a custom ant build xml will be excluded from the coalescing.""" # TODO(John Sirois): this is broken - representative_target is not necessarily representative representative_target = list(java_targets)[0] meta_target_base_name = "fast-%s" % (name if name else representative_target.name) provides = None deployjar = hasattr(representative_target, 'deployjar') and representative_target.deployjar buildflags = representative_target.buildflags def create_target(target_type, target_name, target_index, targets): def name(name): return "%s-%s-%d" % (target_name, name, target_index) if target_type == JavaProtobufLibrary: return JavaProtobufLibrary._aggregate(name('protobuf'), provides, buildflags, targets) elif target_type == JavaThriftLibrary: return JavaThriftLibrary._aggregate(name('thrift'), provides, buildflags, targets) elif target_type == JavaLibrary: return JavaLibrary._aggregate(name('java'), provides, deployjar, buildflags, targets) elif target_type == ScalaLibrary: return ScalaLibrary._aggregate(name('scala'), provides, deployjar, buildflags, targets) elif target_type == JavaTests: return JavaTests._aggregate(name('java-tests'), buildflags, targets) elif target_type == ScalaTests: return ScalaTests._aggregate(name('scala-tests'), buildflags, targets) else: raise Exception("Cannot aggregate targets of type: %s" % target_type) # chunk up our targets by type & custom build xml coalesced = InternalTarget.coalesce_targets(java_targets) coalesced = list(reversed(coalesced)) start_type = type(coalesced[0]) start = 0 descriptors = [] for current in range(0, len(coalesced)): current_target = coalesced[current] current_type = type(current_target) if current_target.custom_antxml_path: if start < current: # if we have a type chunk to our left, record it descriptors.append((start_type, coalesced[start:current])) # record a chunk containing just the target that has the custom build xml to be conservative descriptors.append((current_type, [current_target])) start = current + 1 if current < (len(coalesced) - 1): start_type = type(coalesced[start]) elif start_type != current_type: # record the type chunk we just left descriptors.append((start_type, coalesced[start:current])) start = current start_type = current_type if start < len(coalesced): # record the tail chunk descriptors.append((start_type, coalesced[start:])) # build meta targets aggregated from the chunks and keep track of which targets end up in which # meta targets meta_targets_by_target_id = dict() targets_by_meta_target = [] for (target_type, targets), index in zip(descriptors, reversed(range(0, len(descriptors)))): meta_target = create_target(target_type, meta_target_base_name, index, targets) targets_by_meta_target.append((meta_target, targets)) for target in targets: meta_targets_by_target_id[target._id] = meta_target # calculate the other meta-targets (if any) each meta-target depends on extra_targets_by_meta_target = [] for meta_target, targets in targets_by_meta_target: meta_deps = set() custom_antxml_path = None for target in targets: if target.custom_antxml_path: custom_antxml_path = target.custom_antxml_path for dep in target.resolved_dependencies: if is_jvm(dep): meta = meta_targets_by_target_id[dep._id] if meta != meta_target: meta_deps.add(meta) extra_targets_by_meta_target.append( (meta_target, meta_deps, custom_antxml_path)) def lift_excludes(meta_target): excludes = set() def lift(target): if target.excludes: excludes.update(target.excludes) for jar_dep in target.jar_dependencies: excludes.update(jar_dep.excludes) for internal_dep in target.internal_dependencies: lift(internal_dep) lift(meta_target) return excludes # link in the extra inter-meta deps meta_targets = [] for meta_target, extra_deps, custom_antxml_path in extra_targets_by_meta_target: meta_targets.append(meta_target) meta_target.update_dependencies(extra_deps) meta_target.excludes = lift_excludes(meta_target) meta_target.custom_antxml_path = custom_antxml_path sorted_meta_targets = InternalTarget.sort_targets(meta_targets) def prune_metas(target): if sorted_meta_targets: try: sorted_meta_targets.remove(target) except ValueError: # we've already removed target in the current walk pass # link any disconnected meta_target graphs so we can return 1 root target root = None while sorted_meta_targets: new_root = sorted_meta_targets[0] new_root.walk(prune_metas, is_jvm) if root: new_root.update_dependencies([root]) root = new_root return root