private void cleanOutputRoots(CompileContext context, boolean cleanCaches) throws ProjectBuildException {
    final ProjectDescriptor projectDescriptor = context.getProjectDescriptor();
    ProjectBuildException ex = null;
    final ExecutorService cleanupExecutor = AppExecutorUtil.createBoundedApplicationPoolExecutor("IncProjectBuilder Output Cleanup Pool", SharedThreadPool.getInstance(), MAX_BUILDER_THREADS);
    final List<Future<?>> cleanupTasks = new ArrayList<>();
    final long cleanStart = System.nanoTime();
    try {
      final JpsJavaCompilerConfiguration configuration = JpsJavaExtensionService.getInstance().getCompilerConfiguration(projectDescriptor.getProject());
      if (configuration.isClearOutputDirectoryOnRebuild()) {
        clearOutputs(context, cleanupExecutor, cleanupTasks);
      }
      else {
        for (BuildTarget<?> target : projectDescriptor.getBuildTargetIndex().getAllTargets()) {
          context.checkCanceled();
          if (context.getScope().isBuildForced(target)) {
            if (SYNC_DELETE) {
              clearOutputFilesUninterruptibly(context, target);
            }
            else {
              cleanupTasks.add(cleanupExecutor.submit(() -> clearOutputFilesUninterruptibly(context, target)));
            }
          }
        }
      }

      for (BuildTargetType<?> type : TargetTypeRegistry.getInstance().getTargetTypes()) {
        if (context.getScope().isAllTargetsOfTypeAffected(type)) {
          cleanOutputOfStaleTargets(type, context);
        }
      }
    }
    catch (ProjectBuildException e) {
      ex = e;
    }
    finally {
      for (Future<?> task : cleanupTasks) {
        try {
          task.get();
        }
        catch (Throwable e) {
          LOG.info(e);
        }
      }
      LOG.info("Cleaned output directories in " + TimeUnit.NANOSECONDS.toMillis(System.nanoTime() - cleanStart) + " ms");
      if (cleanCaches) {
        try {
          projectDescriptor.getProjectStamps().getStampStorage().clean();
        }
        catch (IOException e) {
          if (ex == null) {
            ex = new ProjectBuildException(JpsBuildBundle.message("build.message.error.cleaning.timestamps.storage"), e);
          }
          else {
            LOG.info("Error cleaning timestamps storage", e);
          }
        }
        finally {
          try {
            projectDescriptor.dataManager.clean(myAsyncTasks::add);
          }
          catch (IOException e) {
            if (ex == null) {
              ex = new ProjectBuildException(JpsBuildBundle.message("build.message.error.cleaning.compiler.storages"), e);
            }
            else {
              LOG.info("Error cleaning compiler storages", e);
            }
          }
          finally {
            projectDescriptor.fsState.clearAll();
            if (ex != null) {
              throw ex;
            }
          }
        }
      }
      else {
        final BuildTargetsState targetsState = projectDescriptor.getTargetsState();
        for (BuildTarget<?> target : getTargetsWithClearedOutput(context)) {
          // This will ensure the target will be fully rebuilt either in this or in the future build session.
          // if this build fails or is cancelled, all such targets will still be marked as needing recompilation
          targetsState.getTargetConfiguration(target).invalidate();
        }
      }
    }
  }
private void cleanOutputRoots(CompileContext context, boolean cleanCaches)