@Override
  public void build(@NotNull ResourcesTarget target,
                    @NotNull DirtyFilesHolder<ResourceRootDescriptor, ResourcesTarget> holder,
                    @NotNull BuildOutputConsumer outputConsumer,
                    @NotNull CompileContext context) throws ProjectBuildException {
    if (!isResourceProcessingEnabled(target.getModule())) {
      return;
    }

    try {
      final Map<ResourceRootDescriptor, Boolean> skippedRoots = new HashMap<>();
      holder.processDirtyFiles((t, f, srcRoot) -> {
        Boolean isSkipped = skippedRoots.get(srcRoot);
        if (isSkipped == null) {
          File outputDir = t.getOutputDir();
          isSkipped = Boolean.valueOf(outputDir == null || FileUtil.filesEqual(outputDir, srcRoot.getRootFile()));
          skippedRoots.put(srcRoot, isSkipped);
        }
        if (isSkipped.booleanValue()) {
          return true;
        }
        copyResource(context, srcRoot, f, outputConsumer);
        return !context.getCancelStatus().isCanceled();
      });

      context.checkCanceled();

      context.processMessage(new ProgressMessage(""));
    }
    catch(BuildDataCorruptedException | ProjectBuildException e) {
      throw e;
    }
    catch (Exception e) {
      throw new ProjectBuildException(e.getMessage(), e);
    }
  }
@Override
  public void build(@NotNull ResourcesTarget target,
                    @NotNull DirtyFilesHolder<ResourceRootDescriptor, ResourcesTarget> holder,
                    @NotNull BuildOutputConsumer outputConsumer,
                    @NotNull CompileContext context)