@Override
 public ResolvedTargets<Void> getExplicitTarget(String targetName)
     throws TargetParsingException, InterruptedException {
   Label label = TargetPatternResolverUtil.label(targetName);
   try {
     Target target = packageProvider.getTarget(env.getListener(), label);
     SkyKey key = TransitiveTraversalValue.key(target.getLabel());
     SkyValue token =
         env.getValueOrThrow(key, NoSuchPackageException.class, NoSuchTargetException.class);
     if (token == null) {
       throw new MissingDepException();
     }
     return ResolvedTargets.empty();
   } catch (NoSuchThingException e) {
     throw new TargetParsingException(e.getMessage(), e);
   }
 }
  @Override
  @Nullable
  public BuildConfiguration createConfigurations(
      ConfigurationFactory configurationFactory,
      Cache<String, BuildConfiguration> cache,
      PackageProviderForConfigurations packageProvider,
      BuildOptions buildOptions,
      EventHandler eventHandler,
      boolean performSanityCheck)
      throws InvalidConfigurationException {
    // Target configuration
    BuildConfiguration targetConfiguration =
        configurationFactory.getConfiguration(packageProvider, buildOptions, false, cache);
    if (targetConfiguration == null) {
      return null;
    }

    BuildConfiguration dataConfiguration = targetConfiguration;

    // Host configuration
    // Note that this passes in the dataConfiguration, not the target
    // configuration. This is intentional.
    BuildConfiguration hostConfiguration =
        getHostConfigurationFromRequest(
            configurationFactory, packageProvider, dataConfiguration, buildOptions, cache);
    if (hostConfiguration == null) {
      return null;
    }

    ListMultimap<SplitTransition<?>, BuildConfiguration> splitTransitionsTable =
        ArrayListMultimap.create();
    for (SplitTransition<BuildOptions> transition : buildOptions.getPotentialSplitTransitions()) {
      List<BuildOptions> splitOptionsList = transition.split(buildOptions);

      // While it'd be clearer to condition the below on "if (!splitOptionsList.empty())",
      // IosExtension.ExtensionSplitArchTransition defaults to a single-value split. If we failed
      // that case then no builds would work, whether or not they're iOS builds (since iOS
      // configurations are unconditionally loaded). Once we have dynamic configuraiton support
      // for split transitions, this will all go away.
      if (splitOptionsList.size() > 1 && targetConfiguration.useDynamicConfigurations()) {
        throw new InvalidConfigurationException(
            "dynamic configurations don't yet support split transitions");
      }

      for (BuildOptions splitOptions : splitOptionsList) {
        BuildConfiguration splitConfig =
            configurationFactory.getConfiguration(packageProvider, splitOptions, false, cache);
        splitTransitionsTable.put(transition, splitConfig);
      }
    }
    if (packageProvider.valuesMissing()) {
      return null;
    }

    // Sanity check that the implicit labels are all in the transitive closure of explicit ones.
    // This also registers all targets in the cache entry and validates them on subsequent requests.
    Set<Label> reachableLabels = new HashSet<>();
    if (performSanityCheck) {
      // We allow the package provider to be null for testing.
      for (Map.Entry<String, Label> entry : buildOptions.getAllLabels().entries()) {
        Label label = entry.getValue();
        try {
          collectTransitiveClosure(packageProvider, reachableLabels, label);
        } catch (NoSuchThingException e) {
          eventHandler.handle(Event.error(e.getMessage()));
          throw new InvalidConfigurationException(
              String.format("Failed to load required %s target: '%s'", entry.getKey(), label));
        }
      }
      if (packageProvider.valuesMissing()) {
        return null;
      }
      sanityCheckImplicitLabels(reachableLabels, targetConfiguration);
      sanityCheckImplicitLabels(reachableLabels, hostConfiguration);
    }

    BuildConfiguration result =
        setupTransitions(
            targetConfiguration, dataConfiguration, hostConfiguration, splitTransitionsTable);
    result.reportInvalidOptions(eventHandler);
    return result;
  }