public ModuleLevelBuilder.ExitCode build(final CompileContext context, ModuleChunk chunk)
      throws ProjectBuildException {
    try {
      final List<File> toCompile = collectChangedFiles(context, chunk);
      if (toCompile.isEmpty()) {
        return ExitCode.NOTHING_DONE;
      }

      String moduleOutput = getModuleOutput(context, chunk);
      String compilerOutput = getCompilerOutput(moduleOutput);

      final Set<String> toCompilePaths = new LinkedHashSet<String>();
      for (File file : toCompile) {
        toCompilePaths.add(FileUtil.toSystemIndependentName(file.getPath()));
      }

      Map<String, String> class2Src =
          buildClassToSourceMap(chunk, context, toCompilePaths, moduleOutput);

      String ideCharset = chunk.getProject().getProjectCharset();
      String encoding =
          !Comparing.equal(CharsetToolkit.getDefaultSystemCharset().name(), ideCharset)
              ? ideCharset
              : null;
      List<String> patchers = Collections.emptyList(); // todo patchers
      final File tempFile =
          GroovycOSProcessHandler.fillFileWithGroovycParameters(
              compilerOutput,
              toCompilePaths,
              FileUtil.toSystemDependentName(moduleOutput),
              class2Src,
              encoding,
              patchers);

      // todo different outputs in a chunk
      // todo xmx
      final List<String> cmd =
          ExternalProcessUtil.buildJavaCommandLine(
              getJavaExecutable(chunk),
              "org.jetbrains.groovy.compiler.rt.GroovycRunner",
              Collections.<String>emptyList(),
              new ArrayList<String>(generateClasspath(context, chunk)),
              Arrays.asList(
                  "-Xmx384m",
                  "-Dfile.encoding=" + CharsetToolkit.getDefaultSystemCharset().name() /*,
                      "-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5239"*/),
              Arrays.<String>asList(myForStubs ? "stubs" : "groovyc", tempFile.getPath()));

      final Process process = Runtime.getRuntime().exec(ArrayUtil.toStringArray(cmd));
      GroovycOSProcessHandler handler =
          GroovycOSProcessHandler.runGroovyc(
              process,
              new Consumer<String>() {
                public void consume(String s) {
                  context.processMessage(new ProgressMessage(s));
                }
              });

      if (handler.shouldRetry()) {
        if (CHUNK_REBUILD_ORDERED.get(context) != null) {
          CHUNK_REBUILD_ORDERED.set(context, null);
        } else {
          CHUNK_REBUILD_ORDERED.set(context, Boolean.TRUE);
          return ExitCode.CHUNK_REBUILD_REQUIRED;
        }
      }

      if (myForStubs) {
        JavaBuilder.addTempSourcePathRoot(context, new File(compilerOutput));
      }

      for (CompilerMessage message : handler.getCompilerMessages()) {
        context.processMessage(message);
      }
      if (!myForStubs
          && updateDependencies(
              context, chunk, toCompile, moduleOutput, handler.getSuccessfullyCompiled())) {
        return ExitCode.ADDITIONAL_PASS_REQUIRED;
      }
      return ExitCode.OK;
    } catch (Exception e) {
      throw new ProjectBuildException(e);
    }
  }