def add_target(self, target, recursive=False): """Adds the classes and resources for a target to an open jar. :param target: The target to add generated classes and resources for. :param bool recursive: `True` to add classes and resources for the target's transitive internal dependency closure. :returns: `True` if the target contributed any files - manifest entries, classfiles or resource files - to this jar. :rtype: bool """ products_added = False classpath_products = self._context.products.get_data('runtime_classpath') # TODO(John Sirois): Manifest handling is broken. We should be tracking state and failing # fast if any duplicate entries are added; ie: if we get a second binary or a second agent. if isinstance(target, JvmBinary): self._add_manifest_entries(target, self._manifest) products_added = True # Ensure that JavaAgent entries are added to the manifest. Either by adding all of the # transitive JavaAgent deps, if recursive, or by adding the root target, if the root target # is itself a JavaAgent. if recursive: agents = [t for t in target.closure() if isinstance(t, JavaAgent)] if len(agents) > 1: raise TaskError('Only 1 agent can be added to a jar, found {} for {}:\n\t{}' .format(len(agents), target.address.reference(), '\n\t'.join(agent.address.reference() for agent in agents))) elif agents: self._add_agent_manifest(agents[0], self._manifest) products_added = True elif isinstance(target, JavaAgent): self._add_agent_manifest(target, self._manifest) products_added = True # In the transitive case we'll gather internal resources naturally as dependencies, but in the # non-transitive case we need to manually add these special (in the context of jarring) # dependencies. targets = target.closure(bfs=True) if recursive else [target] if not recursive and target.has_resources: targets += target.resources # We only gather internal classpath elements per our contract. target_classpath = ClasspathUtil.internal_classpath(targets, classpath_products) for entry in target_classpath: if ClasspathUtil.is_jar(entry): self._jar.writejar(entry) products_added = True elif ClasspathUtil.is_dir(entry): for rel_file in ClasspathUtil.classpath_entries_contents([entry]): self._jar.write(os.path.join(entry, rel_file), rel_file) products_added = True else: # non-jar and non-directory classpath entries should be ignored pass return products_added
def add_target(self, target, recursive=False): """Adds the classes and resources for a target to an open jar. :param target: The target to add generated classes and resources for. :param bool recursive: `True` to add classes and resources for the target's transitive internal dependency closure. :returns: `True` if the target contributed any files - manifest entries, classfiles or resource files - to this jar. :rtype: bool """ products_added = False classpath_products = self._context.products.get_data('runtime_classpath') # TODO(John Sirois): Manifest handling is broken. We should be tracking state and failing # fast if any duplicate entries are added; ie: if we get a second binary or a second agent. if isinstance(target, JvmBinary): self._add_manifest_entries(target, self._manifest) products_added = True # Ensure that JavaAgent entries are added to the manifest. Either by adding all of the # transitive JavaAgent deps, if recursive, or by adding the root target, if the root target # is itself a JavaAgent. if recursive: agents = [t for t in target.closure() if isinstance(t, JavaAgent)] if len(agents) > 1: raise TaskError('Only 1 agent can be added to a jar, found {} for {}:\n\t{}' .format(len(agents), target.address.reference(), '\n\t'.join(agent.address.reference() for agent in agents))) elif agents: self._add_agent_manifest(agents[0], self._manifest) products_added = True elif isinstance(target, JavaAgent): self._add_agent_manifest(target, self._manifest) products_added = True # In the transitive case we'll gather internal resources naturally as dependencies, but in the # non-transitive case we need to manually add these special (in the context of jarring) # dependencies. targets = target.closure(bfs=True) if recursive else [target] if not recursive and target.has_resources: targets += target.resources # We only gather internal classpath elements per our contract. target_classpath = ClasspathUtil.internal_classpath(targets, classpath_products) for entry in target_classpath: if ClasspathUtil.is_jar(entry): self._jar.writejar(entry) products_added = True elif ClasspathUtil.is_dir(entry): for rel_file in ClasspathUtil.classpath_entries_contents([entry]): self._jar.write(os.path.join(entry, rel_file), rel_file) products_added = True else: # non-jar and non-directory classpath entries should be ignored pass return products_added
def _get_external_dependencies(self, binary_target): artifacts_by_file_name = defaultdict(set) for external_dep, coordinate in self.list_external_jar_dependencies(binary_target): self.context.log.debug(' scanning {} from {}'.format(coordinate, external_dep)) for qualified_file_name in ClasspathUtil.classpath_entries_contents([external_dep]): artifacts_by_file_name[qualified_file_name].add(coordinate.artifact_filename) return artifacts_by_file_name
def _get_external_dependencies(self, binary_target): artifacts_by_file_name = defaultdict(set) for external_dep, coordinate in self.list_external_jar_dependencies(binary_target): self.context.log.debug(' scanning {} from {}'.format(coordinate, external_dep)) for qualified_file_name in ClasspathUtil.classpath_entries_contents([external_dep]): artifacts_by_file_name[qualified_file_name].add(coordinate.artifact_filename) return artifacts_by_file_name
def record_file_ownership(target): entries = ClasspathUtil.internal_classpath([target], classpath_products, transitive=False) for f in ClasspathUtil.classpath_entries_contents(entries): if not f.endswith('/'): artifacts_by_file_name[f].add(target.address.reference())
def _write_to_artifact_cache(self, vts, compile_context, get_update_artifact_cache_work): assert len(vts.targets) == 1 assert vts.targets[0] == compile_context.target # Noop if the target is uncacheable. if (compile_context.target.has_label('no_cache')): return vt = vts.versioned_targets[0] # Set up args to relativize analysis in the background. portable_analysis_file = self._portable_analysis_for_target( self._analysis_dir, compile_context.target) relativize_args_tuple = (compile_context.analysis_file, portable_analysis_file) # Collect the artifacts for this target. artifacts = [] # Intransitive classpath entries. target_classpath = ClasspathUtil.classpath_entries( (compile_context.target, ), self.context.products.get_data('runtime_classpath'), ('default', ), transitive=False) for entry in target_classpath: if ClasspathUtil.is_jar(entry): artifacts.append(entry) elif ClasspathUtil.is_dir(entry): for rel_file in ClasspathUtil.classpath_entries_contents( [entry]): artifacts.append(os.path.join(entry, rel_file)) else: # non-jar and non-directory classpath entries should be ignored pass # Log file. log_file = self._capture_log_file(compile_context.target) if log_file and os.path.exists(log_file): artifacts.append(log_file) # Jar. artifacts.append(compile_context.jar_file) # Get the 'work' that will publish these artifacts to the cache. # NB: the portable analysis_file won't exist until we finish. vts_artifactfiles_pair = (vt, artifacts + [portable_analysis_file]) update_artifact_cache_work = get_update_artifact_cache_work( [vts_artifactfiles_pair]) # And execute it. if update_artifact_cache_work: work_chain = [ Work(self._analysis_tools.relativize, [relativize_args_tuple], 'relativize'), update_artifact_cache_work ] self.context.submit_background_work_chain( work_chain, parent_workunit_name='cache')
def add_classpath_entry(entry): if ClasspathUtil.is_jar(entry): self._jar.writejar(entry) elif ClasspathUtil.is_dir(entry): for rel_file in ClasspathUtil.classpath_entries_contents([entry]): self._jar.write(os.path.join(entry, rel_file), rel_file) else: # non-jar and non-directory classpath entries should be ignored pass
def _gather(self, context, target): """Creates a task for the context, and yields the files that would be placed in the dex.""" gathered = [] for entry in self.create_task(context)._gather_dex_entries(target): if ClasspathUtil.is_jar(entry) or ClasspathUtil.is_dir(entry): gathered.extend(ClasspathUtil.classpath_entries_contents([entry])) else: gathered.append(entry) return gathered
def add_classpath_entry(entry): if ClasspathUtil.is_jar(entry): self._jar.writejar(entry) elif ClasspathUtil.is_dir(entry): for rel_file in ClasspathUtil.classpath_entries_contents( [entry]): self._jar.write(os.path.join(entry, rel_file), rel_file) else: # non-jar and non-directory classpath entries should be ignored pass
def _iter_jar_packages(cls, path): paths = set() for pathname in ClasspathUtil.classpath_entries_contents([path]): if cls._potential_package_path(pathname): package = os.path.dirname(pathname) if package: # This check avoids a false positive on things like module-info.class. # We must never add an empty package, as this will cause every single string # literal to be rewritten. paths.add(package) return cls._iter_packages(paths)
def _iter_jar_packages(cls, path): paths = set() for pathname in ClasspathUtil.classpath_entries_contents([path]): if cls._potential_package_path(pathname): package = os.path.dirname(pathname) if package: # This check avoids a false positive on things like module-info.class. # We must never add an empty package, as this will cause every single string # literal to be rewritten. paths.add(package) return cls._iter_packages(paths)
def _write_to_artifact_cache(self, vts, compile_context, get_update_artifact_cache_work): assert len(vts.targets) == 1 assert vts.targets[0] == compile_context.target # Noop if the target is uncacheable. if (compile_context.target.has_label('no_cache')): return vt = vts.versioned_targets[0] # Set up args to relativize analysis in the background. portable_analysis_file = self._portable_analysis_for_target( self._analysis_dir, compile_context.target) relativize_args_tuple = (compile_context.analysis_file, portable_analysis_file) # Collect the artifacts for this target. artifacts = [] # Intransitive classpath entries. target_classpath = ClasspathUtil.classpath_entries( (compile_context.target,), self.context.products.get_data('runtime_classpath'), ('default',), transitive=False) for entry in target_classpath: if ClasspathUtil.is_jar(entry): artifacts.append(entry) elif ClasspathUtil.is_dir(entry): for rel_file in ClasspathUtil.classpath_entries_contents([entry]): artifacts.append(os.path.join(entry, rel_file)) else: # non-jar and non-directory classpath entries should be ignored pass # Log file. log_file = self._capture_log_file(compile_context.target) if log_file and os.path.exists(log_file): artifacts.append(log_file) # Jar. artifacts.append(compile_context.jar_file) # Get the 'work' that will publish these artifacts to the cache. # NB: the portable analysis_file won't exist until we finish. vts_artifactfiles_pair = (vt, artifacts + [portable_analysis_file]) update_artifact_cache_work = get_update_artifact_cache_work([vts_artifactfiles_pair]) # And execute it. if update_artifact_cache_work: work_chain = [ Work(self._analysis_tools.relativize, [relativize_args_tuple], 'relativize'), update_artifact_cache_work ] self.context.submit_background_work_chain(work_chain, parent_workunit_name='cache')
def _jar_classfiles(self, jar_file): """Returns an iterator over the classfiles inside jar_file.""" for cls in ClasspathUtil.classpath_entries_contents([jar_file]): if cls.endswith(b'.class'): yield cls
def record_file_ownership(target): entries = ClasspathUtil.internal_classpath([target], classpath_products) for f in ClasspathUtil.classpath_entries_contents(entries): artifacts_by_file_name[f].add(target.address.reference())
def _jar_classfiles(self, jar_file): """Returns an iterator over the classfiles inside jar_file.""" for cls in ClasspathUtil.classpath_entries_contents([jar_file]): if cls.endswith(b'.class'): yield cls
def _iter_jar_packages(cls, path): paths = set() for pathname in ClasspathUtil.classpath_entries_contents([path]): if cls._potential_package_path(pathname): paths.add(os.path.dirname(pathname)) return cls._iter_packages(paths)
def record_file_ownership(target): entries = ClasspathUtil.internal_classpath([target], classpath_products, transitive=False) for f in ClasspathUtil.classpath_entries_contents(entries): if not f.endswith('/'): artifacts_by_file_name[f].add(target.address.reference())
def record_file_ownership(target): entries = ClasspathUtil.internal_classpath([target], classpath_products) for f in ClasspathUtil.classpath_entries_contents(entries): artifacts_by_file_name[f].add(target.address.reference())
def _iter_jar_packages(cls, path): paths = set() for pathname in ClasspathUtil.classpath_entries_contents([path]): if cls._potential_package_path(pathname): paths.add(os.path.dirname(pathname)) return cls._iter_packages(paths)