public static void updateDependencies(
      CompileContext context,
      List<File> toCompile,
      Map<ModuleBuildTarget, Collection<GroovycOutputParser.OutputItem>> successfullyCompiled,
      OutputConsumer outputConsumer,
      Builder builder)
      throws IOException {
    JavaBuilderUtil.registerFilesToCompile(context, toCompile);
    if (!successfullyCompiled.isEmpty()) {

      final Callbacks.Backend callback = JavaBuilderUtil.getDependenciesRegistrar(context);

      for (Map.Entry<ModuleBuildTarget, Collection<GroovycOutputParser.OutputItem>> entry :
          successfullyCompiled.entrySet()) {
        final ModuleBuildTarget target = entry.getKey();
        final Collection<GroovycOutputParser.OutputItem> compiled = entry.getValue();
        for (GroovycOutputParser.OutputItem item : compiled) {
          final String sourcePath = FileUtil.toSystemIndependentName(item.sourcePath);
          final String outputPath = FileUtil.toSystemIndependentName(item.outputPath);
          final File outputFile = new File(outputPath);
          final File srcFile = new File(sourcePath);
          try {
            final byte[] bytes = FileUtil.loadFileBytes(outputFile);
            if (Utils.IS_TEST_MODE || LOG.isDebugEnabled()) {
              LOG.info("registerCompiledClass " + outputFile + " from " + srcFile);
            }
            outputConsumer.registerCompiledClass(
                target,
                new CompiledClass(
                    outputFile, srcFile, readClassName(bytes), new BinaryContent(bytes)));
            callback.associate(outputPath, sourcePath, new FailSafeClassReader(bytes));
          } catch (Throwable e) {
            // need this to make sure that unexpected errors in, for example, ASM will not ruin the
            // compilation
            final String message =
                "Class dependency information may be incomplete! Error parsing generated class "
                    + item.outputPath;
            LOG.info(message, e);
            context.processMessage(
                new CompilerMessage(
                    builder.getPresentableName(),
                    BuildMessage.Kind.WARNING,
                    message + "\n" + CompilerMessage.getTextFromThrowable(e),
                    sourcePath));
          }
          JavaBuilderUtil.registerSuccessfullyCompiled(context, srcFile);
        }
      }
    }
  }
  @Override
  public final ExitCode build(
      CompileContext context,
      ModuleChunk chunk,
      DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget> dirtyFilesHolder,
      OutputConsumer outputConsumer)
      throws ProjectBuildException, IOException {
    if (outputConsumer.getCompiledClasses().isEmpty() || !isEnabled(context, chunk)) {
      return ExitCode.NOTHING_DONE;
    }

    final String progress = getProgressMessage();
    final boolean shouldShowProgress = !StringUtil.isEmptyOrSpaces(progress);
    if (shouldShowProgress) {
      context.processMessage(new ProgressMessage(progress + " [" + chunk.getName() + "]"));
    }

    ExitCode exitCode = ExitCode.NOTHING_DONE;
    try {
      InstrumentationClassFinder finder = CLASS_FINDER.get(context); // try using shared finder
      if (finder == null) {
        final Collection<File> platformCp =
            ProjectPaths.getPlatformCompilationClasspath(chunk, false);
        final Collection<File> classpath = new ArrayList<File>();
        classpath.addAll(ProjectPaths.getCompilationClasspath(chunk, false));
        classpath.addAll(ProjectPaths.getSourceRootsWithDependents(chunk).keySet());

        finder = createInstrumentationClassFinder(platformCp, classpath, outputConsumer);
        CLASS_FINDER.set(context, finder);
      }

      exitCode = performBuild(context, chunk, finder, outputConsumer);
    } finally {
      if (shouldShowProgress) {
        context.processMessage(new ProgressMessage("")); // cleanup progress
      }
    }
    return exitCode;
  }