private static CharSequence generateModuleScript( String moduleName, ModuleChunk chunk, List<VirtualFile> files, boolean tests, VirtualFile mainOutput, Set<VirtualFile> directoriesToFilterOut) { StringBuilder script = new StringBuilder(); if (tests) { script.append("// Module script for tests\n"); } else { script.append("// Module script for production\n"); } script.append("import kotlin.modules.*\n"); script.append("fun project() {\n"); script.append(" module(\"" + moduleName + "\") {\n"); for (VirtualFile sourceFile : files) { script.append(" sources += \"" + path(sourceFile) + "\"\n"); } // TODO: have a bootclasspath in script API script.append(" // Boot classpath\n"); for (VirtualFile root : chunk.getCompilationBootClasspathFiles()) { script.append(" classpath += \"" + path(root) + "\"\n"); } script.append(" // Compilation classpath\n"); for (VirtualFile root : chunk.getCompilationClasspathFiles()) { String path = path(root); if (directoriesToFilterOut.contains(root)) { // For IDEA's make (incremental compilation) purposes, output directories of the current // module and its dependencies // appear on the class path, so we are at risk of seeing the results of the previous build, // i.e. if some class was // removed in the sources, it may still be there in binaries. Thus, we delete these entries // from the classpath. script.append(" // Output directory, commented out\n"); script.append(" // "); } script.append(" classpath += \"" + path + "\"\n"); } // This is for java files in same roots script.append(" // Java classpath (for Java sources)\n"); for (VirtualFile root : chunk.getSourceRoots()) { script.append(" classpath += \"" + path(root) + "\"\n"); } script.append(" // Main output\n"); if (tests && mainOutput != null) { script.append(" classpath += \"" + path(mainOutput) + "\"\n"); } script.append(" }\n"); script.append("}\n"); return script; }
private void doCompile( CompileContext compileContext, Chunk<Module> moduleChunk, List<VirtualFile> files, Module module, boolean tests) { if (files.isEmpty()) return; VirtualFile mainOutput = compileContext.getModuleOutputDirectory(module); final VirtualFile outputDir = tests ? compileContext.getModuleOutputDirectoryForTests(module) : mainOutput; if (outputDir == null) { compileContext.addMessage(ERROR, "[Internal Error] No output directory", "", -1, -1); return; } File kotlinHome = PathUtil.getDefaultCompilerPath(); if (kotlinHome == null) { compileContext.addMessage( ERROR, "Cannot find kotlinc home. Make sure plugin is properly installed", "", -1, -1); return; } ModuleChunk chunk = new ModuleChunk( (CompileContextEx) compileContext, moduleChunk, Collections.<Module, List<VirtualFile>>emptyMap()); String moduleName = moduleChunk.getNodes().iterator().next().getName(); // Filter the output we are writing to Set<VirtualFile> outputDirectoriesToFilter = Sets.newHashSet(compileContext.getModuleOutputDirectoryForTests(module)); if (!tests) { outputDirectoriesToFilter.add(compileContext.getModuleOutputDirectory(module)); } CharSequence script = generateModuleScript( moduleName, chunk, files, tests, mainOutput, outputDirectoriesToFilter); File scriptFile = new File(path(outputDir), "script.kts"); try { FileUtil.writeToFile(scriptFile, script.toString()); } catch (IOException e) { compileContext.addMessage( ERROR, "[Internal Error] Cannot write script to " + scriptFile.getAbsolutePath(), "", -1, -1); return; } if (RUN_OUT_OF_PROCESS) { runOutOfProcess(compileContext, outputDir, kotlinHome, scriptFile); } else { runInProcess(compileContext, outputDir, kotlinHome, scriptFile); } // compileContext.addMessage(INFORMATION, "Generated module script:\n" + // script.toString(), "file://" + path(mainOutput), 0, 1); }