public static void processFilesToRecompile( final CompileContext context, final ModuleChunk chunk, final Condition<JpsModule> moduleFilter, final FileProcessor processor) throws IOException { final BuildFSState fsState = context.getProjectDescriptor().fsState; for (ModuleBuildTarget target : chunk.getTargets()) { if (moduleFilter.value(target.getModule())) { fsState.processFilesToRecompile(context, target, processor); } } }
private static String ensureCorrectOutput( ModuleChunk chunk, GroovycOutputParser.OutputItem item, Map<ModuleBuildTarget, String> generationOutputs, String compilerOutput, @NotNull ModuleBuildTarget srcTarget) throws IOException { if (chunk.getModules().size() > 1 && !srcTarget.equals(chunk.representativeTarget())) { File output = new File(item.outputPath); String srcTargetOutput = generationOutputs.get(srcTarget); if (srcTargetOutput == null) { LOG.info( "No output for " + srcTarget + "; outputs=" + generationOutputs + "; targets = " + chunk.getTargets()); return item.outputPath; } // todo honor package prefixes File correctRoot = new File(srcTargetOutput); File correctOutput = new File(correctRoot, FileUtil.getRelativePath(new File(compilerOutput), output)); FileUtil.rename(output, correctOutput); return correctOutput.getPath(); } return item.outputPath; }
private static Map<File, Set<File>> buildOutputDirectoriesMap( CompileContext context, ModuleChunk chunk) { final Map<File, Set<File>> map = new THashMap<File, Set<File>>(FileUtil.FILE_HASHING_STRATEGY); for (ModuleBuildTarget target : chunk.getTargets()) { final File outputDir = target.getOutputDir(); if (outputDir == null) { continue; } final Set<File> roots = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY); for (JavaSourceRootDescriptor descriptor : context.getProjectDescriptor().getBuildRootIndex().getTargetRoots(target, context)) { roots.add(descriptor.root); } map.put(outputDir, roots); } return map; }
private static Map<ModuleBuildTarget, String> getStubGenerationOutputs( ModuleChunk chunk, CompileContext context) throws IOException { Map<ModuleBuildTarget, String> generationOutputs = new HashMap<ModuleBuildTarget, String>(); File commonRoot = getStubRoot(context); for (ModuleBuildTarget target : chunk.getTargets()) { File targetRoot = new File( commonRoot, target.getModule().getName() + File.separator + target.getTargetType().getTypeId()); if (targetRoot.exists() && !FileUtil.deleteWithRenaming(targetRoot)) { throw new IOException("External make cannot clean " + targetRoot.getPath()); } if (!targetRoot.mkdirs()) { throw new IOException("External make cannot create " + targetRoot.getPath()); } generationOutputs.put(target, targetRoot.getPath()); } return generationOutputs; }
@Nullable public static Map<ModuleBuildTarget, String> getCanonicalModuleOutputs( CompileContext context, ModuleChunk chunk, Builder builder) { Map<ModuleBuildTarget, String> finalOutputs = new LinkedHashMap<ModuleBuildTarget, String>(); for (ModuleBuildTarget target : chunk.getTargets()) { File moduleOutputDir = target.getOutputDir(); if (moduleOutputDir == null) { context.processMessage( new CompilerMessage( builder.getPresentableName(), BuildMessage.Kind.ERROR, "Output directory not specified for module " + target.getModule().getName())); return null; } //noinspection ResultOfMethodCallIgnored moduleOutputDir.mkdirs(); String moduleOutputPath = FileUtil.toCanonicalPath(moduleOutputDir.getPath()); assert moduleOutputPath != null; finalOutputs.put( target, moduleOutputPath.endsWith("/") ? moduleOutputPath : moduleOutputPath + "/"); } return finalOutputs; }
static void markDirtyFiles( CompileContext context, ModuleBuildTarget target, Timestamps timestamps, boolean forceMarkDirty, @Nullable THashSet<File> currentFiles) throws IOException { final ModuleExcludeIndex rootsIndex = context.getProjectDescriptor().getModuleExcludeIndex(); final Set<File> excludes = new HashSet<File>(rootsIndex.getModuleExcludes(target.getModule())); for (JavaSourceRootDescriptor rd : context.getProjectDescriptor().getBuildRootIndex().getTargetRoots(target, context)) { if (!rd.root.exists()) { continue; } context.getProjectDescriptor().fsState.clearRecompile(rd); traverseRecursively(context, rd, rd.root, excludes, timestamps, forceMarkDirty, currentFiles); } }
@Override public ExitCode build( CompileContext context, ModuleChunk chunk, DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget> dirtyFilesHolder, OutputConsumer outputConsumer) throws ProjectBuildException, IOException { final IceConfig config = context.getProjectDescriptor().getProject().getContainer().getChild(IceConfig.ROLE); IceConfig iceConfig = config == null ? new IceConfig("") : config; File frameworkHome = JpsPathUtil.urlToFile(iceConfig.getFrameworkHomeUrl()); List<String> includes = new ArrayList<String>(); for (String include : iceConfig.getIncludeUrls()) { includes.add(JpsPathUtil.urlToFile(include).getAbsolutePath()); } final Map<ModuleBuildTarget, List<File>> toCompile = collectChangedFiles(context, dirtyFilesHolder); if (toCompile.isEmpty()) { return ExitCode.NOTHING_DONE; } for (Map.Entry<ModuleBuildTarget, List<File>> e : toCompile.entrySet()) { final ModuleBuildTarget target = e.getKey(); final JpsModule module = target.getModule(); SliceCompilerSettings settings = module.getContainer().getChild(SliceCompilerSettings.ROLE); final SliceCompilerSettings facetConfig = settings == null ? new SliceCompilerSettings() : settings; final List<File> sourceFiles = e.getValue(); List<Target> translators = facetConfig.getComponents(); if (translators.isEmpty()) { context.processMessage( new CompilerMessage( getPresentableName(), BuildMessage.Kind.WARNING, "No valid translators found for module " + module.getName() + ". Check facet configuration.")); continue; } // Translate files for (Target c : translators) { final File outputDir = c.getOutputFile(); if (facetConfig.isCleanOutput()) { try { FileUtils.cleanDirectory(outputDir); } catch (IOException ex) { context.processMessage( new CompilerMessage( getPresentableName(), BuildMessage.Kind.ERROR, "Failed to empty target directory: " + outputDir.getPath() + " . Error: " + ex.getMessage())); return ExitCode.ABORT; } } compileFiles( context, frameworkHome, includes, target, sourceFiles, c.getComponent(), outputDir); } } return ExitCode.OK; }
private void compileFiles( final CompileContext context, File frameworkHome, List<String> includes, ModuleBuildTarget buildTarget, List<File> sourceFiles, IceComponent target, File outputDir) throws StopBuildException { final JpsModule module = buildTarget.getModule(); final String translatorName = target.getTranslatorName(); if (outputDir == null) { context.processMessage( new CompilerMessage( getPresentableName(), BuildMessage.Kind.WARNING, "Output folder is not specified for " + translatorName + " in module " + module.getName() + ". Check facet configuration.")); return; } List<String> command = new ArrayList<String>(); command.add(target.getTranslatorPath(frameworkHome).getAbsolutePath()); command.add("--list-generated"); command.add("--output-dir"); final String outputDirPath = outputDir.getAbsolutePath(); command.add(outputDirPath); for (String include : includes) { command.add("-I" + include); } for (JpsModuleSourceRoot contentRoot : module.getSourceRoots()) { command.add("-I" + contentRoot.getFile().getAbsolutePath()); } for (File source : sourceFiles) { command.add(source.getAbsolutePath()); } try { Process process = new ProcessBuilder().command(command).start(); BaseOSProcessHandler handler = new BaseOSProcessHandler( process, StringUtil.join(command, " "), CharsetToolkit.UTF8_CHARSET); final AtomicBoolean hasErrors = new AtomicBoolean(); handler.addProcessListener( new ProcessAdapter() { final StringBuilder errorOutput = new StringBuilder(); final StringBuilder stdOutput = new StringBuilder(); @Override public void onTextAvailable(ProcessEvent event, Key outputType) { if (outputType == ProcessOutputTypes.STDERR) { errorOutput.append(event.getText()); } else if (outputType == ProcessOutputTypes.STDOUT) { stdOutput.append(event.getText()); } } @Override public void processTerminated(ProcessEvent event) { Document res; final String stdout = stdOutput.toString(); try { res = JDOMUtil.loadDocument(stdout); } catch (Exception e) { context.processMessage( new CompilerMessage( BUILDER_NAME, BuildMessage.Kind.ERROR, "Can't process compiler output: " + stdout)); hasErrors.set(true); return; } int exitCode = event.getExitCode(); if (exitCode != 0) { for (Element source : res.getRootElement().getChildren("source")) { final Element output = source.getChild("output"); if (output != null) { String message = output.getTextTrim(); for (String line : message.split("\n")) { int separatorIndex = line.indexOf(": "); final String path; final long lineNumber; if (separatorIndex <= 0) { path = null; lineNumber = -1L; } else { int lineSep = line.lastIndexOf(':', separatorIndex - 1); if (lineSep == -1) { path = null; lineNumber = -1L; } else { path = line.substring(0, lineSep); long l; try { l = Long.parseLong(line.substring(lineSep + 1, separatorIndex)); } catch (NumberFormatException e) { l = -1L; } lineNumber = l; } } context.processMessage( new CompilerMessage( BUILDER_NAME, BuildMessage.Kind.ERROR, line, path, -1L, -1L, -1L, lineNumber, -1L)); } } } final String stdErr = errorOutput.toString(); if (stdErr.length() > 0) { context.processMessage( new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.ERROR, stdErr)); } context.processMessage( new CompilerMessage( BUILDER_NAME, BuildMessage.Kind.ERROR, "translator '" + translatorName + "' for '" + module.getName() + "' finished with exit code " + exitCode)); hasErrors.set(true); } else { final FileGeneratedEvent msg = new FileGeneratedEvent(); for (Element source : res.getRootElement().getChildren("source")) { for (Element file : source.getChildren("file")) { final String fileName = file.getAttributeValue("name"); if (fileName.startsWith(outputDirPath)) { msg.add(outputDirPath, fileName.substring(outputDirPath.length() + 1)); } } } context.processMessage(msg); } } }); handler.startNotify(); handler.waitFor(); if (hasErrors.get()) { throw new StopBuildException(); } } catch (IOException e) { context.processMessage( new CompilerMessage( getPresentableName(), BuildMessage.Kind.ERROR, "Failed to translate files with " + translatorName + ". Error: " + e.getMessage())); } }