/**
     * @return Pair of dep-file rule key and the members of possibleDepFileSourcePaths that actually
     *     appeared in the dep file
     * @throws IOException
     */
    public Optional<Pair<RuleKey, ImmutableSet<SourcePath>>> build(
        Optional<ImmutableSet<SourcePath>> possibleDepFileSourcePaths) throws IOException {
      ImmutableSet<SourcePath> inputs = builder.getInputsSoFar();

      ImmutableSet<SourcePath> depFileInputs = inputs;

      if (possibleDepFileSourcePaths.isPresent()) {
        // possibleDepFileSourcePaths is an ImmutableSortedSet which implements contains() via
        // binary search rather than via hashing. Thus taking the intersection/difference
        // is O(n*log(n)). Here, we make a hash-based copy of the set, so that intersection
        // will be reduced to O(N).
        ImmutableSet<SourcePath> possibleDepFileSourcePathsUnsorted =
            ImmutableSet.copyOf(possibleDepFileSourcePaths.get());
        Sets.SetView<SourcePath> nonDepFileInputs =
            Sets.difference(inputs, possibleDepFileSourcePathsUnsorted);

        builder.addToRuleKey(nonDepFileInputs);

        depFileInputs =
            ImmutableSet.copyOf(Sets.intersection(inputs, possibleDepFileSourcePathsUnsorted));
      }

      Optional<RuleKey> ruleKey = builder.build();
      if (ruleKey.isPresent()) {
        return Optional.of(new Pair<>(ruleKey.get(), depFileInputs));
      } else {
        return Optional.empty();
      }
    }
    public Optional<Pair<RuleKey, ImmutableSet<SourcePath>>> build(
        Optional<ImmutableSet<SourcePath>> possibleDepFileSourcePaths,
        ImmutableList<DependencyFileEntry> depFileEntries)
        throws IOException {
      // TODO(jkeljo): Make this use possibleDepFileSourcePaths all the time
      Iterable<SourcePath> inputsSoFar = builder.getIterableInputsSoFar();
      // Dep file paths come as a sorted set, which does binary search instead of hashing for
      // lookups, so we re-create it as a hashset.
      ImmutableSet<SourcePath> fastPossibleSourcePaths =
          possibleDepFileSourcePaths.isPresent()
              ? ImmutableSet.copyOf(possibleDepFileSourcePaths.get())
              : ImmutableSet.copyOf(inputsSoFar);

      ImmutableSet<DependencyFileEntry> depFileEntriesSet = ImmutableSet.copyOf(depFileEntries);

      final ImmutableSet.Builder<SourcePath> depFileSourcePathsBuilder = ImmutableSet.builder();
      final ImmutableSet.Builder<DependencyFileEntry> filesAccountedFor = ImmutableSet.builder();

      // Each input path falls into one of three categories:
      // 1) It's not covered by dep files, so we need to consider it part of the rule key
      // 2) It's covered by dep files and present in the dep file, so we consider it
      //    part of the rule key
      // 3) It's covered by dep files but not present in the dep file, so we don't include it in
      //    the rule key (the benefit of dep file support is that lots of things fall in this
      //    category, so we can avoid rebuilds that would have happened with input-based rule keys)
      for (SourcePath input : inputsSoFar) {
        if (!fastPossibleSourcePaths.contains(input)) {
          // If this path is not a dep file path, then add it to the builder directly
          builder.addToRuleKey(input);
        } else {
          // If this input path is covered by the dep paths, check to see if it was declared
          // as a real dependency by the dep file entries
          DependencyFileEntry entry = DependencyFileEntry.fromSourcePath(input, pathResolver);
          if (depFileEntriesSet.contains(entry)) {
            builder.addToRuleKey(input);
            depFileSourcePathsBuilder.add(input);
            filesAccountedFor.add(entry);
          }
        }
      }

      Sets.SetView<DependencyFileEntry> filesUnaccountedFor =
          Sets.difference(depFileEntriesSet, filesAccountedFor.build());
      // If we don't find actual inputs in one of the rules that corresponded to the input, this
      // likely means that the rule changed to no longer use the input. In this case we need to
      // throw a `NoSuchFileException` so that the build engine handles this as a signal that the
      // dep file rule key cannot be used.
      if (!filesUnaccountedFor.isEmpty()) {
        throw new NoSuchFileException(
            String.format(
                "%s: could not find any inputs matching the relative paths [%s]",
                rule.getBuildTarget(), Joiner.on(',').join(filesUnaccountedFor)));
      }

      Optional<RuleKey> ruleKey = builder.build();
      if (ruleKey.isPresent()) {
        return Optional.of(new Pair<>(ruleKey.get(), depFileSourcePathsBuilder.build()));
      } else {
        return Optional.empty();
      }
    }