def _inject_synthetic_target(self, vt, sources):
    """Create, inject, and return a synthetic target for the given target and workdir.

    :param vt: A codegen input VersionedTarget to inject a synthetic target for.
    :param sources: A FilesetWithSpec to inject for the target.
    """
    target = vt.target

    # NB: For stability, the injected target exposes the stable-symlinked `vt.results_dir`,
    # rather than the hash-named `vt.current_results_dir`.
    synthetic_target_dir = self.synthetic_target_dir(target, vt.results_dir)
    synthetic_target_type = self.synthetic_target_type(target)
    synthetic_extra_dependencies = self.synthetic_target_extra_dependencies(target, synthetic_target_dir)

    copied_attributes = {}
    for attribute in self._copy_target_attributes:
      copied_attributes[attribute] = getattr(target, attribute)

    if self._supports_exports(synthetic_target_type):
      extra_exports = self.synthetic_target_extra_exports(target, synthetic_target_dir)

      extra_exports_not_in_extra_dependencies = set(extra_exports).difference(
        set(synthetic_extra_dependencies))
      if len(extra_exports_not_in_extra_dependencies) > 0:
        raise self.MismatchedExtraExports(
          'Extra synthetic exports included targets not in the extra dependencies: {}. Affected target: {}'
            .format(extra_exports_not_in_extra_dependencies, target))

      extra_export_specs = {e.address.spec for e in extra_exports}
      original_export_specs = self._original_export_specs(target)
      union = set(original_export_specs).union(extra_export_specs)

      copied_attributes['exports'] = sorted(union)

    synthetic_target = self.context.add_new_target(
      address=self._get_synthetic_address(target, synthetic_target_dir),
      target_type=synthetic_target_type,
      dependencies=synthetic_extra_dependencies,
      sources=sources,
      derived_from=target,
      **copied_attributes
    )

    build_graph = self.context.build_graph
    # NB(pl): This bypasses the convenience function (Target.inject_dependency) in order
    # to improve performance.  Note that we can walk the transitive dependee subgraph once
    # for transitive invalidation rather than walking a smaller subgraph for every single
    # dependency injected.
    for dependent_address in build_graph.dependents_of(target.address):
      build_graph.inject_dependency(
        dependent=dependent_address,
        dependency=synthetic_target.address,
      )
    # NB(pl): See the above comment.  The same note applies.
    for concrete_dependency_address in build_graph.dependencies_of(target.address):
      build_graph.inject_dependency(
        dependent=synthetic_target.address,
        dependency=concrete_dependency_address,
      )

    if target in self.context.target_roots:
      self.context.target_roots.append(synthetic_target)

    return synthetic_target
Create, inject, and return a synthetic target for the given target and workdir.

    :param vt: A codegen input VersionedTarget to inject a synthetic target for.
    :param sources: A FilesetWithSpec to inject for the target.