Exemple #1
0
    def classpath(self,
                  targets,
                  classpath_prefix=None,
                  classpath_product=None):
        """Builds a transitive classpath for the given targets.

    Optionally includes a classpath prefix or building from a non-default classpath product.

    :param targets: the targets for which to build the transitive classpath.
    :param classpath_prefix: optional additional entries to prepend to the classpath.
    :param classpath_product: an optional ClasspathProduct from which to build the classpath. if not
    specified, the runtime_classpath will be used.
    :return: a list of classpath strings.
    """
        classpath = list(classpath_prefix) if classpath_prefix else []

        classpath_product = classpath_product or self.context.products.get_data(
            'runtime_classpath')

        closure = BuildGraph.closure(targets, bfs=True)

        classpath_for_targets = ClasspathUtil.classpath(
            closure, classpath_product, self.confs)
        classpath.extend(classpath_for_targets)
        return classpath
Exemple #2
0
  def classpath(self, targets, classpath_prefix=None, classpath_product=None, exclude_scopes=None,
                include_scopes=None):
    """Builds a transitive classpath for the given targets.

    Optionally includes a classpath prefix or building from a non-default classpath product.

    :param targets: the targets for which to build the transitive classpath.
    :param classpath_prefix: optional additional entries to prepend to the classpath.
    :param classpath_product: an optional ClasspathProduct from which to build the classpath. if not
    specified, the runtime_classpath will be used.
    :param :class:`pants.build_graph.target_scopes.Scope` exclude_scopes: Exclude targets which
      have at least one of these scopes on the classpath.
    :param :class:`pants.build_graph.target_scopes.Scope` include_scopes: Only include targets which
      have at least one of these scopes on the classpath. Defaults to Scopes.JVM_RUNTIME_SCOPES.
    :return: a list of classpath strings.
    """
    include_scopes = Scopes.JVM_RUNTIME_SCOPES if include_scopes is None else include_scopes
    classpath_product = classpath_product or self.context.products.get_data('runtime_classpath')
    closure = BuildGraph.closure(targets, bfs=True, include_scopes=include_scopes,
                                 exclude_scopes=exclude_scopes, respect_intransitive=True)

    classpath_for_targets = ClasspathUtil.classpath(closure, classpath_product, self.confs)
    classpath = list(classpath_prefix or ())
    classpath.extend(classpath_for_targets)
    return classpath
Exemple #3
0
    def _compute_classpath(runtime_classpath, targets):
        closure = BuildGraph.closure(
            targets, bfs=True, include_scopes=Scopes.JVM_RUNTIME_SCOPES, respect_intransitive=True
        )
        classpath_for_targets = ClasspathUtil.classpath(closure, runtime_classpath)

        return classpath_for_targets
 def execute(self):
     basedir = os.path.join(self.get_options().pants_distdir,
                            self._output_folder)
     runtime_classpath = self.context.products.get_data('runtime_classpath')
     targets = self.context.targets()
     if self.get_options().manifest_jar_only:
         classpath = ClasspathUtil.classpath(targets, runtime_classpath)
         # Safely create e.g. dist/export-classpath/manifest.jar
         safe_classpath(classpath, basedir, "manifest.jar")
     else:
         ClasspathProducts.create_canonical_classpath(
             runtime_classpath, targets, basedir, save_classpath_file=True)
Exemple #5
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(
        (compile_context.target,),
        self.context.products.get_data('runtime_classpath'),
        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 execute(self):
   basedir = os.path.join(self.get_options().pants_distdir, self._output_folder)
   runtime_classpath = self.context.products.get_data('runtime_classpath')
   targets = self.context.targets()
   if self.get_options().manifest_jar_only:
     classpath = ClasspathUtil.classpath(targets, runtime_classpath)
     # Safely create e.g. dist/export-classpath/manifest.jar
     safe_classpath(classpath, basedir, "manifest.jar")
   else:
     ClasspathProducts.create_canonical_classpath(runtime_classpath,
                                                  targets,
                                                  basedir,
                                                  save_classpath_file=True)
Exemple #7
0
    def execute(self):
        if self.goal not in JvmPrepCommand.goals():
            raise AssertionError(
                'Got goal "{}". Expected goal to be one of {}'.format(
                    self.goal, JvmPrepCommand.goals()))

        targets = self.context.targets(postorder=True,
                                       predicate=self.runnable_prep_cmd)

        compile_classpath = self.context.products.get_data('compile_classpath')
        classpath_products = self.context.products.get_data(
            'runtime_classpath', compile_classpath.copy)

        with self.context.new_workunit(name='jvm_prep_command',
                                       labels=[WorkUnitLabel.PREP
                                               ]) as workunit:
            for target in targets:
                distribution = JvmPlatform.preferred_jvm_distribution(
                    [target.platform])
                executor = SubprocessExecutor(distribution)

                mainclass = target.payload.get_field_value('mainclass')
                args = target.payload.get_field_value('args', [])
                target_jvm_options = target.payload.get_field_value(
                    'jvm_options', [])
                cp = list(
                    ClasspathUtil.classpath(target.closure(),
                                            classpath_products))
                if not cp:
                    raise TaskError(
                        'target {} has no classpath. (Add dependencies= parameter?'
                        .format(target.address.spec))
                self.context.log.info('Running prep command for {}'.format(
                    target.address.spec))
                returncode = distribution.execute_java(
                    executor=executor,
                    classpath=cp,
                    main=mainclass,
                    jvm_options=target_jvm_options,
                    args=args,
                    workunit_factory=self.context.new_workunit,
                    workunit_name='run',
                    workunit_labels=[WorkUnitLabel.PREP],
                )

                workunit.set_outcome(
                    WorkUnit.FAILURE if returncode else WorkUnit.SUCCESS)
                if returncode:
                    raise TaskError(
                        'RunJvmPrepCommand failed to run {}'.format(mainclass))
Exemple #8
0
  def classpath(self, targets, classpath_prefix=None, classpath_product=None):
    """Builds a classpath for the current task and given targets, optionally including a classpath
    prefix or building from a non-default classpath product.

    :param targets: the targets for which to build the classpath.
    :param classpath_prefix: optional additional entries to prepend to the classpath.
    :param classpath_product: an optional ClasspathProduct from which to build the classpath. if not
    specified, the runtime_classpath will be used.
    :return: a list of classpath strings.
    """
    classpath = list(classpath_prefix) if classpath_prefix else []

    classpath_product = classpath_product or self.context.products.get_data('runtime_classpath')

    classpath_for_targets = ClasspathUtil.classpath(targets, classpath_product, self.confs)
    classpath.extend(classpath_for_targets)
    return classpath
    def gen():
      # Compute src -> target.
      if isinstance(target, JvmTarget):
        for src in target.sources_relative_to_buildroot():
          yield os.path.join(self.buildroot, src)
      # TODO(Tejal Desai): pantsbuild/pants/65: Remove java_sources attribute for ScalaLibrary
      if isinstance(target, ScalaLibrary):
        for java_source in target.java_sources:
          for src in java_source.sources_relative_to_buildroot():
            yield os.path.join(self.buildroot, src)

      # Compute classfile -> target and jar -> target.
      files = ClasspathUtil.classpath_contents((target,), self.runtime_classpath)
      # And jars; for binary deps, zinc doesn't emit precise deps (yet).
      cp_entries = ClasspathUtil.classpath((target,), self.runtime_classpath)
      jars = [cpe for cpe in cp_entries if ClasspathUtil.is_jar(cpe)]
      for coll in [files, jars]:
        for f in coll:
          yield f
    def targets_by_file(self):
        """Returns a map from abs path of source, class or jar file to an OrderedSet of targets.

    The value is usually a singleton, because a source or class file belongs to a single target.
    However a single jar may be provided (transitively or intransitively) by multiple JarLibrary
    targets. But if there is a JarLibrary target that depends on a jar directly, then that
    "canonical" target will be the first one in the list of targets.
    """
        targets_by_file = defaultdict(OrderedSet)
        runtime_classpath = self.context.products.get_data('runtime_classpath')

        # Compute src -> target.
        self.context.log.debug('Mapping sources...')
        buildroot = get_buildroot()
        # Look at all targets in-play for this pants run. Does not include synthetic targets,
        for target in self.context.targets():
            if isinstance(target, JvmTarget):
                for src in target.sources_relative_to_buildroot():
                    targets_by_file[os.path.join(buildroot, src)].add(target)
            # TODO(Tejal Desai): pantsbuild/pants/65: Remove java_sources attribute for ScalaLibrary
            if isinstance(target, ScalaLibrary):
                for java_source in target.java_sources:
                    for src in java_source.sources_relative_to_buildroot():
                        targets_by_file[os.path.join(buildroot,
                                                     src)].add(target)

        # Compute classfile -> target and jar -> target.
        self.context.log.debug('Mapping classpath...')
        for target in self.context.targets():
            # Classpath content.
            files = ClasspathUtil.classpath_contents((target, ),
                                                     runtime_classpath,
                                                     transitive=False)
            # And jars; for binary deps, zinc doesn't emit precise deps (yet).
            cp_entries = ClasspathUtil.classpath((target, ),
                                                 runtime_classpath,
                                                 transitive=False)
            jars = [cpe for cpe in cp_entries if ClasspathUtil.is_jar(cpe)]
            for coll in [files, jars]:
                for f in coll:
                    targets_by_file[f].add(target)

        return targets_by_file
Exemple #11
0
        def gen():
            # Compute src -> target.
            if isinstance(target, JvmTarget):
                for src in target.sources_relative_to_buildroot():
                    yield os.path.join(self.buildroot, src)
            # TODO(Tejal Desai): pantsbuild/pants/65: Remove java_sources attribute for ScalaLibrary
            if isinstance(target, ScalaLibrary):
                for java_source in target.java_sources:
                    for src in java_source.sources_relative_to_buildroot():
                        yield os.path.join(self.buildroot, src)

            # Compute classfile -> target and jar -> target.
            files = ClasspathUtil.classpath_contents((target,), self.runtime_classpath)
            # And jars; for binary deps, zinc doesn't emit precise deps (yet).
            cp_entries = ClasspathUtil.classpath((target,), self.runtime_classpath)
            jars = [cpe for cpe in cp_entries if ClasspathUtil.is_jar(cpe)]
            for coll in [files, jars]:
                for f in coll:
                    yield f
Exemple #12
0
  def classpath(self, targets, classpath_prefix=None, classpath_product=None):
    """Builds a transitive classpath for the given targets.

    Optionally includes a classpath prefix or building from a non-default classpath product.

    :param targets: the targets for which to build the transitive classpath.
    :param classpath_prefix: optional additional entries to prepend to the classpath.
    :param classpath_product: an optional ClasspathProduct from which to build the classpath. if not
    specified, the runtime_classpath will be used.
    :return: a list of classpath strings.
    """
    classpath = list(classpath_prefix) if classpath_prefix else []

    classpath_product = classpath_product or self.context.products.get_data('runtime_classpath')

    closure = OrderedSet()
    for target in targets:
      closure.update(target.closure(bfs=True))

    classpath_for_targets = ClasspathUtil.classpath(closure, classpath_product, self.confs)
    classpath.extend(classpath_for_targets)
    return classpath
  def targets_by_file(self):
    """Returns a map from abs path of source, class or jar file to an OrderedSet of targets.

    The value is usually a singleton, because a source or class file belongs to a single target.
    However a single jar may be provided (transitively or intransitively) by multiple JarLibrary
    targets. But if there is a JarLibrary target that depends on a jar directly, then that
    "canonical" target will be the first one in the list of targets.
    """
    targets_by_file = defaultdict(OrderedSet)
    runtime_classpath = self.context.products.get_data('runtime_classpath')

    # Compute src -> target.
    self.context.log.debug('Mapping sources...')
    buildroot = get_buildroot()
    # Look at all targets in-play for this pants run. Does not include synthetic targets,
    for target in self.context.targets():
      if isinstance(target, JvmTarget):
        for src in target.sources_relative_to_buildroot():
          targets_by_file[os.path.join(buildroot, src)].add(target)
      # TODO(Tejal Desai): pantsbuild/pants/65: Remove java_sources attribute for ScalaLibrary
      if isinstance(target, ScalaLibrary):
        for java_source in target.java_sources:
          for src in java_source.sources_relative_to_buildroot():
            targets_by_file[os.path.join(buildroot, src)].add(target)

    # Compute classfile -> target and jar -> target.
    self.context.log.debug('Mapping classpath...')
    for target in self.context.targets():
      # Classpath content.
      files = ClasspathUtil.classpath_contents((target,), runtime_classpath, transitive=False)
      # And jars; for binary deps, zinc doesn't emit precise deps (yet).
      cp_entries = ClasspathUtil.classpath((target,), runtime_classpath, transitive=False)
      jars = [cpe for cpe in cp_entries if ClasspathUtil.is_jar(cpe)]
      for coll in [files, jars]:
        for f in coll:
          targets_by_file[f].add(target)

    return targets_by_file
  def execute(self):
    if self.goal not in JvmPrepCommand.goals():
      raise  AssertionError('Got goal "{}". Expected goal to be one of {}'.format(
          self.goal, JvmPrepCommand.goals()))

    targets = self.context.targets(postorder=True,  predicate=self.runnable_prep_cmd)

    compile_classpath = self.context.products.get_data('compile_classpath')
    classpath_products = self.context.products.get_data('runtime_classpath', compile_classpath.copy)

    with self.context.new_workunit(name='jvm_prep_command', labels=[WorkUnitLabel.PREP]) as workunit:
      for target in targets:
        distribution = JvmPlatform.preferred_jvm_distribution([target.platform])
        executor = SubprocessExecutor(distribution)

        mainclass = target.payload.get_field_value('mainclass')
        args = target.payload.get_field_value('args', [])
        target_jvm_options = target.payload.get_field_value('jvm_options', [])
        cp = list(ClasspathUtil.classpath(target.closure(), classpath_products))
        if not cp:
          raise TaskError('target {} has no classpath. (Add dependencies= parameter?'
                          .format(target.address.spec))
        self.context.log.info('Running prep command for {}'.format(target.address.spec))
        returncode = distribution.execute_java(
          executor=executor,
          classpath=cp,
          main=mainclass,
          jvm_options=target_jvm_options,
          args=args,
          workunit_factory=self.context.new_workunit,
          workunit_name='run',
          workunit_labels=[WorkUnitLabel.PREP],
        )

        workunit.set_outcome(WorkUnit.FAILURE if returncode else WorkUnit.SUCCESS)
        if returncode:
          raise TaskError('RunJvmPrepCommand failed to run {}'.format(mainclass))
Exemple #15
0
  def instrument(self, output_dir):
    for datafile in self._iter_datafiles(output_dir):
      os.unlink(datafile)

    self._canonical_datafile = os.path.join(output_dir, '{}.canonical'.format(self._DATAFILE_NAME))
    # It's conceivable we'll be executing a test that has no source file dependencies; ie: we'll
    # never generate a canonical coverage datafile below. Create an empty one here to allow the
    # test run to proceeed normally.
    touch(self._canonical_datafile)

    # Setup an instrumentation classpath based on the existing runtime classpath.
    runtime_classpath = self._context.products.get_data('runtime_classpath')
    instrumentation_classpath = self._context.products.safe_create_data('instrument_classpath',
                                                                        runtime_classpath.copy)
    self.initialize_instrument_classpath(output_dir,
                                         self._settings,
                                         self._targets,
                                         instrumentation_classpath)

    cobertura_cp = self._settings.tool_classpath('cobertura-instrument')
    files_to_instrument = []
    for target in self._targets:
      if Cobertura.is_coverage_target(target):
        paths = instrumentation_classpath.get_for_target(target)
        for (name, path) in paths:
          files_to_instrument.append(path)

    if len(files_to_instrument) > 0:
      unique_files = list(set(files_to_instrument))
      relativize_paths(unique_files, self._settings.workdir)

      args = [
        '--basedir',
        self._settings.workdir,
        '--datafile',
        self._canonical_datafile,
      ]

      if self._include_user_classpath:
        closure = BuildGraph.closure(self._targets, bfs=True, include_scopes=Scopes.JVM_TEST_SCOPES,
          respect_intransitive=True)

        aux_classpath = safe_classpath(
          ClasspathUtil.classpath(closure, runtime_classpath),
          synthetic_jar_dir=None)
        args.append('--auxClasspath')
        args.extend(aux_classpath)

      # apply class incl/excl filters
      if len(self._include_classes) > 0:
        for pattern in self._include_classes:
          args += ["--includeClasses", pattern]
      else:
        args += ["--includeClasses", '.*']  # default to instrumenting all classes
      for pattern in self._exclude_classes:
        args += ["--excludeClasses", pattern]

      with temporary_file() as tmp_file:
        tmp_file.write("\n".join(unique_files))
        tmp_file.flush()

        args += ["--listOfFilesToInstrument", tmp_file.name]

        main = 'net.sourceforge.cobertura.instrument.InstrumentMain'
        self._settings.log.debug(
          "executing cobertura instrumentation with the following args: {}".format(args))
        result = self._execute_java(classpath=cobertura_cp,
                                    main=main,
                                    jvm_options=self._settings.coverage_jvm_options,
                                    args=args,
                                    workunit_factory=self._context.new_workunit,
                                    workunit_name='cobertura-instrument')
        if result != 0:
          raise TaskError("java {0} ... exited non-zero ({1})"
                          " 'failed to instrument'".format(main, result))
Exemple #16
0
    def instrument(self, output_dir):
        for datafile in self._iter_datafiles(output_dir):
            os.unlink(datafile)

        self._canonical_datafile = os.path.join(
            output_dir, '{}.canonical'.format(self._DATAFILE_NAME))
        # It's conceivable we'll be executing a test that has no source file dependencies; ie: we'll
        # never generate a canonical coverage datafile below. Create an empty one here to allow the
        # test run to proceeed normally.
        touch(self._canonical_datafile)

        # Setup an instrumentation classpath based on the existing runtime classpath.
        runtime_classpath = self._context.products.get_data(
            'runtime_classpath')
        instrumentation_classpath = self._context.products.safe_create_data(
            'instrument_classpath', runtime_classpath.copy)
        self.initialize_instrument_classpath(output_dir, self._settings,
                                             self._targets,
                                             instrumentation_classpath)

        cobertura_cp = self._settings.tool_classpath('cobertura-instrument')
        files_to_instrument = []
        for target in self._targets:
            if Cobertura.is_coverage_target(target):
                paths = instrumentation_classpath.get_for_target(target)
                for (name, path) in paths:
                    files_to_instrument.append(path)

        if len(files_to_instrument) > 0:
            unique_files = list(set(files_to_instrument))
            relativize_paths(unique_files, self._settings.workdir)

            args = [
                '--basedir',
                self._settings.workdir,
                '--datafile',
                self._canonical_datafile,
            ]

            if self._include_user_classpath:
                closure = BuildGraph.closure(
                    self._targets,
                    bfs=True,
                    include_scopes=Scopes.JVM_TEST_SCOPES,
                    respect_intransitive=True)

                aux_classpath = safe_classpath(ClasspathUtil.classpath(
                    closure, runtime_classpath),
                                               synthetic_jar_dir=None)
                args.append('--auxClasspath')
                args.extend(aux_classpath)

            # apply class incl/excl filters
            if len(self._include_classes) > 0:
                for pattern in self._include_classes:
                    args += ["--includeClasses", pattern]
            else:
                args += ["--includeClasses",
                         '.*']  # default to instrumenting all classes
            for pattern in self._exclude_classes:
                args += ["--excludeClasses", pattern]

            with temporary_file(binary_mode=False) as tmp_file:
                tmp_file.write("\n".join(unique_files))
                tmp_file.flush()

                args += ["--listOfFilesToInstrument", tmp_file.name]

                main = 'net.sourceforge.cobertura.instrument.InstrumentMain'
                self._settings.log.debug(
                    "executing cobertura instrumentation with the following args: {}"
                    .format(args))
                result = self._execute_java(
                    classpath=cobertura_cp,
                    main=main,
                    jvm_options=self._settings.coverage_jvm_options,
                    args=args,
                    workunit_factory=self._context.new_workunit,
                    workunit_name='cobertura-instrument')
                if result != 0:
                    raise TaskError("java {0} ... exited non-zero ({1})"
                                    " 'failed to instrument'".format(
                                        main, result))