Esempio n. 1
0
    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
Esempio n. 2
0
    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
Esempio n. 3
0
 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
Esempio n. 4
0
 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
Esempio n. 5
0
 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())
Esempio n. 6
0
    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')
Esempio n. 7
0
 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
Esempio n. 8
0
 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
Esempio n. 9
0
 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
Esempio n. 10
0
 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)
Esempio n. 11
0
 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)
Esempio n. 12
0
  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')
Esempio n. 13
0
 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
Esempio n. 14
0
 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())
Esempio n. 15
0
 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
Esempio n. 16
0
 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)
Esempio n. 17
0
 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())
Esempio n. 18
0
 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())
Esempio n. 19
0
 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)