public static File getOrCreateConfigFile(
      final JpsFlexBuildConfiguration bc, final ProjectDescriptor projectDescriptor)
      throws IOException {
    final CompilerConfigGeneratorRt generator =
        new CompilerConfigGeneratorRt(
            bc,
            bc.getModule().getProperties().getModuleLevelCompilerOptions(),
            JpsFlexProjectLevelCompilerOptionsExtension.getProjectLevelCompilerOptions(
                bc.getModule().getProject()),
            projectDescriptor);
    String text = generator.generateConfigFileText();

    if (bc.isTempBCForCompilation()) {
      final JpsFlexBuildConfiguration originalBC =
          bc.getModule().getProperties().findConfigurationByName(bc.getName());
      final boolean makeExternalLibsMerged =
          FlexCommonUtils.isFlexUnitBC(bc)
              || (originalBC != null && originalBC.getOutputType() == OutputType.Library);
      final boolean makeIncludedLibsMerged = FlexCommonUtils.isRuntimeStyleSheetBC(bc);
      text =
          FlexCompilerConfigFileUtilBase.mergeWithCustomConfigFile(
              text,
              bc.getCompilerOptions().getAdditionalConfigFilePath(),
              makeExternalLibsMerged,
              makeIncludedLibsMerged);
    }

    final String name = getConfigFileName(bc, FlexCommonUtils.getBCSpecifier(bc));
    return getOrCreateConfigFile(name, text);
  }
  private boolean includeTestRoots() {
    if (myFlexUnit) return true;
    if (myCSS) return false;
    if (myBC.getOutputType() != OutputType.Application) return false;

    final String path = FlexCommonUtils.getPathToMainClassFile(myBC.getMainClass(), myModule);
    return isInTestSourceRoot(myModule, path);
  }
  private void addLibs(final Element rootElement) {
    for (final JpsFlexDependencyEntry entry : myBC.getDependencies().getEntries()) {
      LinkageType linkageType = entry.getLinkageType();
      if (linkageType == LinkageType.Test) {
        if (myFlexUnit) {
          linkageType = LinkageType.Merged;
        } else {
          continue;
        }
      }
      if (myCSS && linkageType == LinkageType.Include) linkageType = LinkageType.Merged;

      if (entry instanceof JpsFlexBCDependencyEntry) {
        if (linkageType == LinkageType.LoadInRuntime) continue;

        final JpsFlexBuildConfiguration dependencyBC = ((JpsFlexBCDependencyEntry) entry).getBC();
        if (dependencyBC != null
            && FlexCommonUtils.checkDependencyType(
                myBC.getOutputType(), dependencyBC.getOutputType(), linkageType)) {
          addLib(rootElement, dependencyBC.getActualOutputFilePath(), linkageType);
        }
      } else if (entry instanceof JpsLibraryDependencyEntry) {
        final JpsLibrary library = ((JpsLibraryDependencyEntry) entry).getLibrary();
        if (library != null) {
          addLibraryRoots(rootElement, library.getRootUrls(JpsOrderRootType.COMPILED), linkageType);
        }
      }
    }

    if (myFlexUnit) {

      final Collection<String> flexUnitLibNames =
          FlexCommonUtils.getFlexUnitSupportLibNames(
              myBC.getNature(),
              myBC.getDependencies().getComponentSet(),
              getPathToFlexUnitMainClass(
                  myProjectDescriptor, myBC.getNature(), myBC.getMainClass()));
      for (String libName : flexUnitLibNames) {
        final String libPath = FlexCommonUtils.getPathToBundledJar(libName);
        final String flexUnitSwcUrl =
            JpsPathUtil.pathToUrl(FileUtil.toSystemIndependentName(libPath));
        addLibraryRoots(rootElement, Collections.singletonList(flexUnitSwcUrl), LinkageType.Merged);
      }
    }
  }
  private void addOtherOptions(final Element rootElement) {
    final Map<String, String> options =
        new THashMap<String, String>(myProjectLevelCompilerOptions.getAllOptions());
    options.putAll(myModuleLevelCompilerOptions.getAllOptions());
    options.putAll(myBC.getCompilerOptions().getAllOptions());

    final String addOptions =
        myProjectLevelCompilerOptions.getAdditionalOptions()
            + " "
            + myModuleLevelCompilerOptions.getAdditionalOptions()
            + " "
            + myBC.getCompilerOptions().getAdditionalOptions();
    final List<String> contextRootInAddOptions =
        FlexCommonUtils.getOptionValues(addOptions, "context-root", "compiler.context-root");

    if (options.get("compiler.context-root") == null && contextRootInAddOptions.isEmpty()) {
      final List<String> servicesInAddOptions =
          FlexCommonUtils.getOptionValues(addOptions, "services", "compiler.services");
      if (options.get("compiler.services") != null || !servicesInAddOptions.isEmpty()) {
        options.put("compiler.context-root", "");
      }
    }

    for (final Map.Entry<String, String> entry : options.entrySet()) {
      addOption(rootElement, CompilerOptionInfo.getOptionInfo(entry.getKey()), entry.getValue());
    }

    final String namespacesRaw = options.get("compiler.namespaces.namespace");
    if (namespacesRaw != null && myBC.getOutputType() == OutputType.Library) {
      final String namespaces =
          FlexCommonUtils.replacePathMacros(
              namespacesRaw, myModule, myFlexmojos ? "" : mySdk.getHomePath());
      final StringBuilder buf = new StringBuilder();
      for (final String listEntry :
          StringUtil.split(namespaces, CompilerOptionInfo.LIST_ENTRIES_SEPARATOR)) {
        final int tabIndex = listEntry.indexOf(CompilerOptionInfo.LIST_ENTRY_PARTS_SEPARATOR);
        assert tabIndex != -1 : namespaces;
        final String namespace = listEntry.substring(0, tabIndex);
        if (buf.length() > 0) buf.append(CompilerOptionInfo.LIST_ENTRIES_SEPARATOR);
        buf.append(namespace);
      }

      if (buf.length() > 0) {
        addOption(rootElement, CompilerOptionInfo.INCLUDE_NAMESPACES_INFO, buf.toString());
      }
    }
  }
  private void addInputOutputPaths(final Element rootElement) throws IOException {
    if (myBC.getOutputType() == OutputType.Library) {
      addFilesIncludedInSwc(rootElement);

      if (!myFlexmojos) {
        addLibClasses(rootElement);
      }
    } else {
      final InfoFromConfigFile info =
          InfoFromConfigFile.getInfoFromConfigFile(
              myBC.getCompilerOptions().getAdditionalConfigFilePath());

      final String pathToMainClassFile =
          myCSS
              ? myBC.getMainClass()
              : myFlexUnit
                  ? getPathToFlexUnitMainClass(
                      myProjectDescriptor, myBC.getNature(), myBC.getMainClass())
                  : FlexCommonUtils.getPathToMainClassFile(myBC.getMainClass(), myModule);

      if (pathToMainClassFile.isEmpty()
          && info.getMainClass(myModule) == null
          && !Utils.IS_TEST_MODE) {
        throw new IOException(
            FlexCommonBundle.message(
                "bc.incorrect.main.class",
                myBC.getMainClass(),
                myBC.getName(),
                myModule.getName()));
      }

      if (!pathToMainClassFile.isEmpty()) {
        addOption(
            rootElement,
            CompilerOptionInfo.MAIN_CLASS_INFO,
            FileUtil.toSystemIndependentName(pathToMainClassFile));
      }
    }

    addOption(rootElement, CompilerOptionInfo.OUTPUT_PATH_INFO, myBC.getActualOutputFilePath());
  }