private static int getJavacServerHeapSize(CompileContext context) {
   final JpsProject project = context.getProjectDescriptor().getProject();
   final JpsJavaCompilerConfiguration config =
       JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(project);
   final JpsJavaCompilerOptions options = config.getCurrentCompilerOptions();
   return options.MAXIMUM_HEAP_SIZE;
 }
 @Override
 public void buildStarted(CompileContext context) {
   final JpsProject project = context.getProjectDescriptor().getProject();
   final JpsJavaCompilerConfiguration config =
       JpsJavaExtensionService.getInstance().getCompilerConfiguration(project);
   final String compilerId = config == null ? JavaCompilers.JAVAC_ID : config.getJavaCompilerId();
   if (LOG.isDebugEnabled()) {
     LOG.debug("Java compiler ID: " + compilerId);
   }
   final boolean isJavac =
       JavaCompilers.JAVAC_ID.equalsIgnoreCase(compilerId)
           || JavaCompilers.JAVAC_API_ID.equalsIgnoreCase(compilerId);
   final boolean isEclipse =
       JavaCompilers.ECLIPSE_ID.equalsIgnoreCase(compilerId)
           || JavaCompilers.ECLIPSE_EMBEDDED_ID.equalsIgnoreCase(compilerId);
   IS_ENABLED.set(context, isJavac || isEclipse);
   String messageText = null;
   if (isJavac) {
     messageText =
         "Using javac " + System.getProperty("java.version") + " to compile java sources";
   } else if (isEclipse) {
     messageText = "Using eclipse compiler to compile java sources";
   }
   COMPILER_VERSION_INFO.set(context, new AtomicReference<String>(messageText));
 }
  private static void loadCommonJavacOptions(CompileContext context) {
    final List<String> options = new ArrayList<String>();
    final List<String> vmOptions = new ArrayList<String>();

    final JpsProject project = context.getProjectDescriptor().getProject();
    final JpsJavaCompilerConfiguration compilerConfig =
        JpsJavaExtensionService.getInstance().getOrCreateCompilerConfiguration(project);
    final JpsJavaCompilerOptions compilerOptions = compilerConfig.getCurrentCompilerOptions();
    if (compilerOptions.DEBUGGING_INFO) {
      options.add("-g");
    }
    if (compilerOptions.DEPRECATION) {
      options.add("-deprecation");
    }
    if (compilerOptions.GENERATE_NO_WARNINGS) {
      options.add("-nowarn");
    }
    if (compilerOptions instanceof EclipseCompilerOptions) {
      final EclipseCompilerOptions eclipseOptions = (EclipseCompilerOptions) compilerOptions;
      if (eclipseOptions.PROCEED_ON_ERROR) {
        options.add("-proceedOnError");
      }
    }
    final String customArgs = compilerOptions.ADDITIONAL_OPTIONS_STRING;
    if (customArgs != null) {
      final StringTokenizer customOptsTokenizer = new StringTokenizer(customArgs, " \t\r\n");
      boolean skip = false;
      while (customOptsTokenizer.hasMoreTokens()) {
        final String userOption = customOptsTokenizer.nextToken();
        if (FILTERED_OPTIONS.contains(userOption)) {
          skip = true;
          continue;
        }
        if (!skip) {
          if (!FILTERED_SINGLE_OPTIONS.contains(userOption)) {
            if (userOption.startsWith("-J-")) {
              vmOptions.add(userOption.substring("-J".length()));
            } else {
              options.add(userOption);
            }
          }
        }
      }
    }

    if (useEclipseCompiler(context)) {
      for (String option : options) {
        if (option.startsWith("-proceedOnError")) {
          Utils.PROCEED_ON_ERROR_KEY.set(context, Boolean.TRUE);
          break;
        }
      }
    }

    JAVAC_OPTIONS.set(context, options);
    JAVAC_VM_OPTIONS.set(context, vmOptions);
  }
 private static boolean useEclipseCompiler(CompileContext context) {
   if (!USE_EMBEDDED_JAVAC) {
     return false;
   }
   JpsProject project = context.getProjectDescriptor().getProject();
   final JpsJavaCompilerConfiguration configuration =
       JpsJavaExtensionService.getInstance().getCompilerConfiguration(project);
   final String compilerId = configuration != null ? configuration.getJavaCompilerId() : null;
   return JavaCompilers.ECLIPSE_ID.equalsIgnoreCase(compilerId)
       || JavaCompilers.ECLIPSE_EMBEDDED_ID.equalsIgnoreCase(compilerId);
 }
  public static void addCompilationOptions(
      List<String> options,
      CompileContext context,
      ModuleChunk chunk,
      @Nullable ProcessorConfigProfile profile) {
    if (!isEncodingSet(options)) {
      final CompilerEncodingConfiguration config =
          context.getProjectDescriptor().getEncodingConfiguration();
      final String encoding = config.getPreferredModuleChunkEncoding(chunk);
      if (config.getAllModuleChunkEncodings(chunk).size() > 1) {
        final StringBuilder msgBuilder = new StringBuilder();
        msgBuilder.append("Multiple encodings set for module chunk ").append(chunk.getName());
        if (encoding != null) {
          msgBuilder.append("\n\"").append(encoding).append("\" will be used by compiler");
        }
        context.processMessage(
            new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.INFO, msgBuilder.toString()));
      }
      if (!StringUtil.isEmpty(encoding)) {
        options.add("-encoding");
        options.add(encoding);
      }
    }

    final String langLevel = getLanguageLevel(chunk.getModules().iterator().next());
    if (!StringUtil.isEmpty(langLevel)) {
      options.add("-source");
      options.add(langLevel);
    }

    JpsJavaCompilerConfiguration compilerConfiguration =
        JpsJavaExtensionService.getInstance()
            .getOrCreateCompilerConfiguration(context.getProjectDescriptor().getProject());
    String bytecodeTarget = null;
    int chunkSdkVersion = -1;
    for (JpsModule module : chunk.getModules()) {
      final JpsSdk<JpsDummyElement> sdk = module.getSdk(JpsJavaSdkType.INSTANCE);
      if (sdk != null) {
        final int moduleSdkVersion = convertToNumber(sdk.getVersionString());
        if (moduleSdkVersion != 0 /*could determine the version*/
            && (chunkSdkVersion < 0 || chunkSdkVersion > moduleSdkVersion)) {
          chunkSdkVersion = moduleSdkVersion;
        }
      }

      final String moduleTarget = compilerConfiguration.getByteCodeTargetLevel(module.getName());
      if (moduleTarget == null) {
        continue;
      }
      if (bytecodeTarget == null) {
        bytecodeTarget = moduleTarget;
      } else {
        if (moduleTarget.compareTo(bytecodeTarget) < 0) {
          bytecodeTarget =
              moduleTarget; // use the lower possible target among modules that form the chunk
        }
      }
    }
    if (bytecodeTarget != null) {
      options.add("-target");
      options.add(bytecodeTarget);
    } else {
      if (chunkSdkVersion > 0 && getCompilerSdkVersion(context) > chunkSdkVersion) {
        // force lower bytecode target level to match the version of sdk assigned to this chunk
        options.add("-target");
        options.add("1." + chunkSdkVersion);
      }
    }

    if (profile != null && profile.isEnabled()) {
      // configuring annotation processing
      if (!profile.isObtainProcessorsFromClasspath()) {
        final String processorsPath = profile.getProcessorPath();
        options.add("-processorpath");
        options.add(
            processorsPath == null ? "" : FileUtil.toSystemDependentName(processorsPath.trim()));
      }

      final Set<String> processors = profile.getProcessors();
      if (!processors.isEmpty()) {
        options.add("-processor");
        options.add(StringUtil.join(processors, ","));
      }

      for (Map.Entry<String, String> optionEntry : profile.getProcessorOptions().entrySet()) {
        options.add("-A" + optionEntry.getKey() + "=" + optionEntry.getValue());
      }

      final File srcOutput =
          ProjectPaths.getAnnotationProcessorGeneratedSourcesOutputDir(
              chunk.getModules().iterator().next(), chunk.containsTests(), profile);
      if (srcOutput != null) {
        srcOutput.mkdirs();
        options.add("-s");
        options.add(srcOutput.getPath());
      }
    } else {
      options.add("-proc:none");
    }
  }
  private boolean compileJava(
      final CompileContext context,
      ModuleChunk chunk,
      Collection<File> files,
      Collection<File> classpath,
      Collection<File> platformCp,
      Collection<File> sourcePath,
      DiagnosticOutputConsumer diagnosticSink,
      final OutputFileConsumer outputSink)
      throws Exception {

    final TasksCounter counter = new TasksCounter();
    COUNTER_KEY.set(context, counter);

    final JpsJavaExtensionService javaExt = JpsJavaExtensionService.getInstance();
    final JpsJavaCompilerConfiguration compilerConfig =
        javaExt.getCompilerConfiguration(context.getProjectDescriptor().getProject());
    assert compilerConfig != null;

    final Set<JpsModule> modules = chunk.getModules();
    ProcessorConfigProfile profile = null;
    if (modules.size() == 1) {
      final JpsModule module = modules.iterator().next();
      profile = compilerConfig.getAnnotationProcessingProfile(module);
    } else {
      // perform cycle-related validations
      Pair<String, LanguageLevel> pair = null;
      for (JpsModule module : modules) {
        final LanguageLevel moduleLevel = javaExt.getLanguageLevel(module);
        if (pair == null) {
          pair = Pair.create(module.getName(), moduleLevel); // first value
        } else {
          if (!Comparing.equal(pair.getSecond(), moduleLevel)) {
            final String message =
                "Modules "
                    + pair.getFirst()
                    + " and "
                    + module.getName()
                    + " must have the same language level because of cyclic dependencies between them";
            diagnosticSink.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, message));
            return true;
          }
        }
      }

      // check that all chunk modules are excluded from annotation processing
      for (JpsModule module : modules) {
        final ProcessorConfigProfile prof = compilerConfig.getAnnotationProcessingProfile(module);
        if (prof.isEnabled()) {
          final String message =
              "Annotation processing is not supported for module cycles. Please ensure that all modules from cycle ["
                  + chunk.getName()
                  + "] are excluded from annotation processing";
          diagnosticSink.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, message));
          return true;
        }
      }
    }

    final Map<File, Set<File>> outs = buildOutputDirectoriesMap(context, chunk);
    final List<String> options = getCompilationOptions(context, chunk, profile);
    final ClassProcessingConsumer classesConsumer =
        new ClassProcessingConsumer(context, outputSink);
    if (LOG.isDebugEnabled()) {
      LOG.debug(
          "Compiling chunk ["
              + chunk.getName()
              + "] with options: \""
              + StringUtil.join(options, " ")
              + "\"");
    }
    try {
      final boolean rc;
      if (USE_EMBEDDED_JAVAC) {
        final boolean useEclipse = useEclipseCompiler(context);
        rc =
            JavacMain.compile(
                options,
                files,
                classpath,
                platformCp,
                sourcePath,
                outs,
                diagnosticSink,
                classesConsumer,
                context.getCancelStatus(),
                useEclipse);
      } else {
        final JavacServerClient client = ensureJavacServerLaunched(context);
        final RequestFuture<JavacServerResponseHandler> future =
            client.sendCompileRequest(
                options,
                files,
                classpath,
                platformCp,
                sourcePath,
                outs,
                diagnosticSink,
                classesConsumer);
        while (!future.waitFor(100L, TimeUnit.MILLISECONDS)) {
          if (context.getCancelStatus().isCanceled()) {
            future.cancel(false);
          }
        }
        rc = future.getMessageHandler().isTerminatedSuccessfully();
      }
      return rc;
    } finally {
      counter.await();
    }
  }