public Set<String> getFiles() { final Set<String> result = new HashSet<String>(); for (FileWrapper f : mySources.keySet()) { result.add(f.getName()); } return result; }
public Set<String> getRemovedFiles(final Properties past) { final Set<String> result = new HashSet<String>(); if (past != null) { for (FileWrapper was : past.mySources.keySet()) { final FileWrapper now = mySources.get(was); if (now == null) { result.add(was.getName()); } } } return result; }
public Set<String> getOutdatedFiles(final Properties past) { final Set<String> result = new HashSet<String>(); for (FileWrapper now : mySources.keySet()) { final FileWrapper than = past == null ? null : past.mySources.get(now); if (than == null || than.getStamp() < now.getStamp() || affectedFiles.contains(now.getName())) { result.add(now.getName()); } } return result; }
private static Map<String, String> buildClassToSourceMap( ModuleChunk chunk, CompileContext context, Set<String> toCompilePaths, String moduleOutputPath) throws IOException { final Map<String, String> class2Src = new HashMap<String, String>(); for (Module module : chunk.getModules()) { final String moduleName = module.getName().toLowerCase(Locale.US); final SourceToOutputMapping srcToOut = context.getDataManager().getSourceToOutputMap(moduleName, context.isCompilingTests()); for (String src : srcToOut.getKeys()) { if (!toCompilePaths.contains(src) && isGroovyFile(src)) { final Collection<String> outs = srcToOut.getState(src); if (outs != null) { for (String out : outs) { if (out.endsWith(".class") && out.startsWith(moduleOutputPath)) { final String className = out.substring(moduleOutputPath.length(), out.length() - ".class".length()) .replace('/', '.'); class2Src.put(className, src); } } } } } } return class2Src; }
private static List<String> generateClasspath(CompileContext context, ModuleChunk chunk) { final Set<String> cp = new LinkedHashSet<String>(); // groovy_rt.jar // IMPORTANT! must be the first in classpath cp.add(ClasspathBootstrap.getResourcePath(GroovyCompilerWrapper.class).getPath()); for (File file : context .getProjectPaths() .getClasspathFiles(chunk, ClasspathKind.compile(context.isCompilingTests()), false)) { cp.add(FileUtil.toCanonicalPath(file.getPath())); } for (File file : context .getProjectPaths() .getClasspathFiles(chunk, ClasspathKind.runtime(context.isCompilingTests()), false)) { cp.add(FileUtil.toCanonicalPath(file.getPath())); } return new ArrayList<String>(cp); }
public ModuleWrapper(final Module m) { m.forceInit(); myModule = m; myDependsOn = null; myTestDependsOn = null; myName = m.getName(); myExcludes = new HashSet<String>(m.getExcludes()); mySource = new Properties(m.getSourceRoots(), m.getOutputPath(), myExcludes); myTest = new Properties(m.getTestRoots(), m.getTestOutputPath(), myExcludes); myLibraries = new HashSet<LibraryWrapper>(); for (Library lib : m.getLibraries().values()) { myLibraries.add(new LibraryWrapper(lib)); } }
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); } }
public void makeModules(final Collection<Module> initial, final Flags flags) { if (myHistory == null && !flags.tests()) { clean(); } new Logger(flags) { @Override public void log(final PrintStream stream) { stream.println("Request to make modules:"); logMany(stream, initial); stream.println("End of request"); } }.log(); final ClasspathKind kind = ClasspathKind.compile(flags.tests()); final Set<Module> modules = new HashSet<Module>(); final Set<String> marked = new HashSet<String>(); final Map<String, Boolean> visited = new HashMap<String, Boolean>(); final Set<String> frontier = new HashSet<String>(); final Map<String, Set<String>> reversedDependencies = new HashMap<String, Set<String>>(); final DotPrinter printer = new DotPrinter(flags.logStream()); printer.header(); for (Module m : myProject.getModules().values()) { final String mName = m.getName(); printer.node(mName); for (ClasspathItem cpi : m.getClasspath(kind)) { if (cpi instanceof Module) { final String name = ((Module) cpi).getName(); printer.edge(name, mName); Set<String> sm = reversedDependencies.get(name); if (sm == null) { sm = new HashSet<String>(); reversedDependencies.put(name, sm); } sm.add(mName); } } } printer.footer(); // Building "upper" subgraph printer.header(); new Object() { public void run(final Collection<Module> initial) { if (initial == null) return; for (Module module : initial) { final String mName = module.getName(); if (marked.contains(mName)) continue; printer.node(mName); final List<Module> dep = new ArrayList<Module>(); for (ClasspathItem cpi : module.getClasspath(kind)) { if (cpi instanceof Module && !marked.contains(((Module) cpi).getName())) { printer.edge(((Module) cpi).getName(), mName); dep.add((Module) cpi); } } if (dep.size() == 0) { frontier.add(mName); } marked.add(mName); run(dep); } } }.run(initial); printer.footer(); // Traversing "upper" subgraph and collecting outdated modules and their descendants new Object() { public void run(final Collection<String> initial, final boolean force) { if (initial == null) return; for (String moduleName : initial) { if (!marked.contains(moduleName)) continue; final Boolean property = visited.get(moduleName); if (property == null || !property && force) { final boolean outdated = getModule(moduleName).isOutdated(flags.tests(), myHistory); if (force || outdated) { visited.put(moduleName, true); modules.add(myProject.getModules().get(moduleName)); run(reversedDependencies.get(moduleName), true); } else { if (property == null) { visited.put(moduleName, false); } run(reversedDependencies.get(moduleName), false); } } } } }.run(frontier, flags.force()); new Logger(flags) { @Override public void log(PrintStream stream) { stream.println("Propagated modules:"); logMany(stream, modules); stream.println("End of propagated"); } }.log(); if (modules.size() == 0 && !flags.force()) { System.out.println("All requested modules are up-to-date."); return; } final BusyBeaver beaver = new BusyBeaver(myProjectBuilder); myProjectBuilder.buildStart(); if (flags.tests()) { beaver.build( modules, new Flags() { public boolean tests() { return false; } public boolean incremental() { return flags.incremental(); } public boolean force() { return flags.force(); } public PrintStream logStream() { return flags.logStream(); } }); } beaver.build(modules, flags); myProjectBuilder.buildStop(); for (Module mod : modules) { getModule(mod.getName()).updateOutputStatus(); } }
public BuildStatus build(final Collection<Module> modules, final Flags flags) { boolean incremental = flags.incremental(); final List<ModuleChunk> chunks = myProjectBuilder.getChunks(flags.tests()).getChunkList(); for (final ModuleChunk c : chunks) { final Set<Module> chunkModules = c.getElements(); if (!DefaultGroovyMethods.intersect(modules, chunkModules).isEmpty()) { final Set<String> removedSources = new HashSet<String>(); if (incremental) { final Set<String> chunkSources = new HashSet<String>(); final Set<String> outdatedSources = new HashSet<String>(); for (Module m : chunkModules) { final ModuleWrapper mw = getModule(m.getName()); outdatedSources.addAll(mw.getOutdatedFiles(flags.tests())); chunkSources.addAll(mw.getSources(flags.tests())); removedSources.addAll(mw.getRemovedFiles(flags.tests())); } final BuildStatus result = iterativeCompile(c, chunkSources, outdatedSources, removedSources, flags); incremental = result == BuildStatus.INCREMENTAL; if (result == BuildStatus.FAILURE) { return result; } } else { new Logger(flags) { @Override public void log(PrintStream stream) { stream.println("Compiling chunk " + c.getName() + " non-incrementally."); } }.log(); for (Module m : chunkModules) { final ModuleWrapper mw = getModule(m.getName()); removedSources.addAll(flags.tests() ? mw.getRemovedTests() : mw.getRemovedSources()); } final Set<Module> toClean = new HashSet<Module>(); for (Module m : chunkModules) { if (!cleared.contains(m)) { toClean.add(m); } } if (!toClean.isEmpty() && !flags.tests()) { builder.clearChunk(new ModuleChunk(toClean), null, ProjectWrapper.this); cleared.addAll(toClean); } final Mappings delta = dependencyMapping.createDelta(); final Callbacks.Backend deltaCallback = delta.getCallback(); try { builder.buildChunk(c, flags.tests(), null, deltaCallback, ProjectWrapper.this); } catch (Exception e) { e.printStackTrace(); return BuildStatus.FAILURE; } final Set<String> allFiles = new HashSet<String>(); for (Module m : c.getElements()) { final ModuleWrapper module = getModule(m.getName()); affectedFiles.removeAll(module.getSources(flags.tests())); allFiles.addAll(module.getSources(flags.tests())); } final Collection<File> files = new HashSet<File>(); for (String f : allFiles) { files.add(new File(f)); } dependencyMapping.integrate(delta, files, removedSources); for (Module m : chunkModules) { Reporter.reportBuildSuccess(m, flags.tests()); } } } } return BuildStatus.INCREMENTAL; }
BuildStatus iterativeCompile( final ModuleChunk chunk, final Set<String> sources, final Set<String> outdated, final Set<String> removed, final Flags flags) { final Collection<String> filesToCompile = DefaultGroovyMethods.intersect(affectedFiles, sources); if (outdated != null) { for (String s : outdated) { assert (s != null); } filesToCompile.addAll(outdated); } filesToCompile.removeAll(compiledFiles); if (!filesToCompile.isEmpty() || removed != null) { final Set<String> outputFiles = new HashSet<String>(); for (String f : filesToCompile) { final Set<ClassRepr> classes = dependencyMapping.getClasses(f); if (classes != null) { for (ClassRepr cr : classes) { outputFiles.add(cr.getFileName()); } } } if (removed != null) { for (String f : removed) { final Set<ClassRepr> classes = dependencyMapping.getClasses(f); if (classes != null) { for (ClassRepr cr : classes) { outputFiles.add(cr.getFileName()); } } } } if (!outputFiles.isEmpty()) { new Logger(flags) { @Override public void log(PrintStream stream) { stream.println("Cleaning output files:"); logFilePaths(stream, outputFiles); stream.println("End of files"); } }.log(); builder.clearChunk(chunk, outputFiles, ProjectWrapper.this); } final Mappings delta = dependencyMapping.createDelta(); final Callbacks.Backend deltaBackend = delta.getCallback(); new Logger(flags) { @Override public void log(PrintStream stream) { stream.println("Compiling files:"); logFilePaths(stream, filesToCompile); stream.println("End of files"); } }.log(); boolean buildException = false; try { builder.buildChunk( chunk, flags.tests(), filesToCompile, deltaBackend, ProjectWrapper.this); } catch (Exception e) { e.printStackTrace(); buildException = true; } if (!buildException) { compiledFiles.addAll(filesToCompile); affectedFiles.removeAll(filesToCompile); final Collection<File> files = new HashSet<File>(); final Collection<File> compiled = new HashSet<File>(); for (String f : filesToCompile) { files.add(new File(f)); } for (String f : compiledFiles) { compiled.add(new File(f)); } final Collection<File> affected = new HashSet<File>(); final boolean incremental = dependencyMapping.differentiate(delta, removed, files, compiled, affected); for (File a : affected) { affectedFiles.add(FileUtil.toSystemIndependentName(a.getAbsolutePath())); } dependencyMapping.integrate(delta, files, removed); if (!incremental) { affectedFiles.addAll(sources); affectedFiles.removeAll(compiledFiles); final BuildStatus result = iterativeCompile(chunk, sources, null, null, flags); if (result == BuildStatus.FAILURE) { return result; } return BuildStatus.CONSERVATIVE; } return iterativeCompile(chunk, sources, null, null, flags); } else { return BuildStatus.FAILURE; } } else { for (Module m : chunk.getElements()) { Reporter.reportBuildSuccess(m, flags.tests()); } } return BuildStatus.INCREMENTAL; }
private static boolean doResourcePackaging( @NotNull CompileContext context, @NotNull Collection<Module> modules, @NotNull Map<Module, AndroidFileSetState> resourcesStates, @NotNull Map<Module, AndroidFileSetState> assetsStates) throws IOException { boolean success = true; final File dataStorageRoot = context.getDataManager().getDataStorageRoot(); final boolean releaseBuild = AndroidJpsUtil.isReleaseBuild(context); AndroidFileSetStorage resourcesStorage = null; AndroidFileSetStorage assetsStorage = null; try { final String resourcesStorageName = releaseBuild ? "resources_packaging_release" : "resources_packaging_dev"; resourcesStorage = new AndroidFileSetStorage(dataStorageRoot, resourcesStorageName); final String assetsStorageName = releaseBuild ? "assets_packaging_release" : "assets_packaging_dev"; assetsStorage = new AndroidFileSetStorage(dataStorageRoot, assetsStorageName); final Set<Module> modulesToUpdateState = new HashSet<Module>(); for (Module module : modules) { final AndroidFacet facet = AndroidJpsUtil.getFacet(module); if (facet == null) { continue; } boolean updateState = true; if (!facet.isLibrary() && !(context.isMake() && checkUpToDate(module, resourcesStates, resourcesStorage) && checkUpToDate(module, assetsStates, assetsStorage))) { updateState = packageResources(facet, context); if (!updateState) { success = false; } } if (updateState) { modulesToUpdateState.add(module); } } for (Module module : modules) { final boolean updateState = modulesToUpdateState.contains(module); resourcesStorage.update(module.getName(), updateState ? resourcesStates.get(module) : null); assetsStorage.update(module.getName(), updateState ? assetsStates.get(module) : null); } } finally { if (resourcesStorage != null) { resourcesStorage.close(); } if (assetsStorage != null) { assetsStorage.close(); } } return success; }