public void readClasspath( JpsModule model, final String testPattern, Element classpathElement, JpsMacroExpander expander) throws IOException { LOG.debug("start loading classpath for " + model.getName()); final HashSet<String> libs = new HashSet<String>(); for (Object o : classpathElement.getChildren(EclipseXml.CLASSPATHENTRY_TAG)) { try { readClasspathEntry( model, new ArrayList<String>(), new ArrayList<String>(), new HashSet<String>(), testPattern, (Element) o, 0, null, expander.getExpandMacroMap(), libs); } catch (ConversionException e) { throw new IOException(e); } } boolean foundSdkDependency = false; JpsDependenciesList dependenciesList = model.getDependenciesList(); for (JpsDependencyElement element : dependenciesList.getDependencies()) { if (element instanceof JpsSdkDependency) { foundSdkDependency = true; break; } } if (!foundSdkDependency) { dependenciesList.addSdkDependency(JpsJavaSdkType.INSTANCE); } if (LOG.isDebugEnabled()) { String name = model.getName(); LOG.debug( "finished loading classpath for " + name + " (" + dependenciesList.getDependencies().size() + " items):"); for (JpsDependencyElement element : dependenciesList.getDependencies()) { LOG.debug(" [" + name + "]:" + element.toString()); } } }
@Override protected void addNamedLibrary( JpsModule rootModel, Collection<String> unknownLibraries, boolean exported, String name, boolean applicationLevel) { if (LOG.isDebugEnabled()) { LOG.debug( "loading " + rootModel.getName() + ": adding " + (applicationLevel ? "application" : "project") + " library '" + name + "'"); } JpsElementFactory factory = JpsElementFactory.getInstance(); JpsLibraryReference libraryReference; final String level = myLibLevels.get(name); libraryReference = level != null ? factory.createLibraryReference( name, JpsLibraryTableSerializer.createLibraryTableReference(level)) : factory.createLibraryReference(name, factory.createGlobalReference()); final JpsLibraryDependency dependency = rootModel.getDependenciesList().addLibraryDependency(libraryReference); setLibraryEntryExported(dependency, exported); }
public void exportModuleOutputProperties() { for (JpsModule module : myModel.getProject().getModules()) { for (boolean test : new boolean[] {true, false}) { myProject.setProperty( "module." + module.getName() + ".output." + (test ? "test" : "main"), getModuleOutput(module, test)); } } }
@NotNull private JpsModule findModule(@NotNull String name) { for (JpsModule module : myProject.getModules()) { if (module.getName().equals(name)) { return module; } } throw new IllegalStateException("Couldn't find module " + name); }
@Override protected void setUpModuleJdk( JpsModule rootModel, Collection<String> unknownJdks, EclipseModuleManager eclipseModuleManager, String jdkName) { if (LOG.isDebugEnabled()) { LOG.debug("loading " + rootModel.getName() + ": set module jdk " + jdkName); } rootModel.getDependenciesList().addSdkDependency(JpsJavaSdkType.INSTANCE); }
private static Set<String> getModuleDependencies(JpsModule module, boolean includeTests) { Set<JpsModule> modules = JpsJavaExtensionService.dependencies(module) .recursively() .includedIn(JpsJavaClasspathKind.compile(includeTests)) .getModules(); Set<String> names = new HashSet<String>(); for (JpsModule depModule : modules) { names.add(depModule.getName()); } return names; }
private void addLibClasses(final Element rootElement) throws IOException { final JpsCompilerExcludes excludes = JpsJavaExtensionService.getInstance() .getOrCreateCompilerConfiguration(myModule.getProject()) .getCompilerExcludes(); final Ref<Boolean> noClasses = new Ref<Boolean>(true); for (JpsTypedModuleSourceRoot srcRoot : myModule.getSourceRoots(JavaSourceRootType.SOURCE)) { final File srcFolder = JpsPathUtil.urlToFile(srcRoot.getUrl()); if (srcFolder.isDirectory()) { processFilesRecursively( srcFolder, new Processor<File>() { public boolean process(final File file) { if (myProjectDescriptor.getIgnoredFileIndex().isIgnored(file.getName())) return false; if (file.isDirectory()) return true; if (!FlexCommonUtils.isSourceFile(file.getName())) return true; if (excludes.isExcluded(file)) return true; String packageRelativePath = FileUtil.getRelativePath(srcFolder, file.getParentFile()); assert packageRelativePath != null : srcFolder.getPath() + ": " + file.getPath(); if (packageRelativePath.equals(".")) packageRelativePath = ""; final String packageName = packageRelativePath.replace(File.separatorChar, '.'); final String qName = StringUtil.getQualifiedName( packageName, FileUtil.getNameWithoutExtension(file)); if (isSourceFileWithPublicDeclaration(file)) { addOption(rootElement, CompilerOptionInfo.INCLUDE_CLASSES_INFO, qName); noClasses.set(false); } return true; } }); } } if (noClasses.get() && myBC.getCompilerOptions().getFilesToIncludeInSWC().isEmpty() && !Utils.IS_TEST_MODE) { throw new IOException( FlexCommonBundle.message( "nothing.to.compile.in.library", myModule.getName(), myBC.getName())); } }
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()); }
@Override protected void addModuleLibrary( JpsModule rootModel, Element element, boolean exported, String libName, String url, String srcUrl, ExpandMacroToPathMap macroMap) { final JpsLibrary jpsLibrary = rootModel.addModuleLibrary(libName, JpsJavaLibraryType.INSTANCE); final JpsDependenciesList dependenciesList = rootModel.getDependenciesList(); final JpsLibraryDependency dependency = dependenciesList.addLibraryDependency(jpsLibrary); url = StringUtil.trimStart(url, "file://"); final String linked = expandLinkedResourcesPath(url, macroMap); if (linked != null) { url = pathToUrl(linked); } else { url = expandEclipsePath2Url(rootModel, url); } LOG.debug("loading " + rootModel.getName() + ": adding module library " + libName + ": " + url); jpsLibrary.addRoot(url, JpsOrderRootType.COMPILED); setLibraryEntryExported(dependency, exported); }
@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())); } }
@Override public void build( @NotNull ErlangTarget target, @NotNull DirtyFilesHolder<ErlangSourceRootDescriptor, ErlangTarget> holder, @NotNull BuildOutputConsumer outputConsumer, @NotNull final CompileContext context) throws ProjectBuildException, IOException { LOG.debug(target.getPresentableName()); final Ref<Boolean> hasDirtyFiles = Ref.create(false); holder.processDirtyFiles( new FileProcessor<ErlangSourceRootDescriptor, ErlangTarget>() { @Override public boolean apply(ErlangTarget target, File file, ErlangSourceRootDescriptor root) throws IOException { hasDirtyFiles.set(true); return true; } }); if (!hasDirtyFiles.get() && !holder.hasRemovedFiles()) { return; } JpsModule module = target.getModule(); JpsJavaExtensionService instance = JpsJavaExtensionService.getInstance(); File outputDirectory = instance.getOutputDirectory(module, target.isTests()); if (outputDirectory == null) { context.processMessage( new CompilerMessage( NAME, BuildMessage.Kind.ERROR, "No output dir for module " + module.getName())); throw new ProjectBuildException(); } if (!outputDirectory.exists()) FileUtil.createDirectory(outputDirectory); JpsSdk<JpsDummyElement> sdk = module.getSdk(JpsErlangSdkType.INSTANCE); if (sdk == null) { context.processMessage( new CompilerMessage( NAME, BuildMessage.Kind.ERROR, "No SDK for module " + module.getName())); throw new ProjectBuildException(); } File executable = JpsErlangSdkType.getByteCodeCompilerExecutable(sdk.getHomePath()); List<String> commandList = new ArrayList<String>(); commandList.add(executable.getAbsolutePath()); CommonProcessors.CollectProcessor<File> processor = new CommonProcessors.CollectProcessor<File>() { @Override protected boolean accept(File file) { return !file.isDirectory() && FileUtilRt.extensionEquals(file.getName(), "erl"); } }; for (JpsModuleSourceRoot root : module.getSourceRoots()) { commandList.add("-I"); commandList.add(root.getFile().getAbsolutePath()); FileUtil.processFilesRecursively(root.getFile(), processor); } for (File f : processor.getResults()) { commandList.add(f.getAbsolutePath()); } LOG.debug(StringUtil.join(commandList, " ")); Process process = new ProcessBuilder(commandList).directory(outputDirectory).start(); BaseOSProcessHandler handler = new BaseOSProcessHandler(process, null, Charset.defaultCharset()); ProcessAdapter adapter = new ProcessAdapter() { @Override public void onTextAvailable(ProcessEvent event, Key outputType) { ErlangCompilerError error = ErlangCompilerError.create("", event.getText()); if (error != null) { boolean isError = error.getCategory() == CompilerMessageCategory.ERROR; BuildMessage.Kind kind = isError ? BuildMessage.Kind.ERROR : BuildMessage.Kind.WARNING; CompilerMessage msg = new CompilerMessage( NAME, kind, error.getErrorMessage(), VirtualFileManager.extractPath(error.getUrl()), -1, -1, -1, error.getLine(), -1); context.processMessage(msg); } } }; handler.addProcessListener(adapter); handler.startNotify(); handler.waitFor(); }
public static void addCompilationOptions( List<String> options, CompileContext context, ModuleChunk chunk, @Nullable ProcessorConfigProfile profile) { if (!isEncodingSet(options)) { final CompilerEncodingConfiguration config = context.getProjectDescriptor().getEncodingConfiguration(); final String encoding = config.getPreferredModuleChunkEncoding(chunk); if (config.getAllModuleChunkEncodings(chunk).size() > 1) { final StringBuilder msgBuilder = new StringBuilder(); msgBuilder.append("Multiple encodings set for module chunk ").append(chunk.getName()); if (encoding != null) { msgBuilder.append("\n\"").append(encoding).append("\" will be used by compiler"); } context.processMessage( new CompilerMessage(BUILDER_NAME, BuildMessage.Kind.INFO, msgBuilder.toString())); } if (!StringUtil.isEmpty(encoding)) { options.add("-encoding"); options.add(encoding); } } final String langLevel = getLanguageLevel(chunk.getModules().iterator().next()); if (!StringUtil.isEmpty(langLevel)) { options.add("-source"); options.add(langLevel); } JpsJavaCompilerConfiguration compilerConfiguration = JpsJavaExtensionService.getInstance() .getOrCreateCompilerConfiguration(context.getProjectDescriptor().getProject()); String bytecodeTarget = null; int chunkSdkVersion = -1; for (JpsModule module : chunk.getModules()) { final JpsSdk<JpsDummyElement> sdk = module.getSdk(JpsJavaSdkType.INSTANCE); if (sdk != null) { final int moduleSdkVersion = convertToNumber(sdk.getVersionString()); if (moduleSdkVersion != 0 /*could determine the version*/ && (chunkSdkVersion < 0 || chunkSdkVersion > moduleSdkVersion)) { chunkSdkVersion = moduleSdkVersion; } } final String moduleTarget = compilerConfiguration.getByteCodeTargetLevel(module.getName()); if (moduleTarget == null) { continue; } if (bytecodeTarget == null) { bytecodeTarget = moduleTarget; } else { if (moduleTarget.compareTo(bytecodeTarget) < 0) { bytecodeTarget = moduleTarget; // use the lower possible target among modules that form the chunk } } } if (bytecodeTarget != null) { options.add("-target"); options.add(bytecodeTarget); } else { if (chunkSdkVersion > 0 && getCompilerSdkVersion(context) > chunkSdkVersion) { // force lower bytecode target level to match the version of sdk assigned to this chunk options.add("-target"); options.add("1." + chunkSdkVersion); } } if (profile != null && profile.isEnabled()) { // configuring annotation processing if (!profile.isObtainProcessorsFromClasspath()) { final String processorsPath = profile.getProcessorPath(); options.add("-processorpath"); options.add( processorsPath == null ? "" : FileUtil.toSystemDependentName(processorsPath.trim())); } final Set<String> processors = profile.getProcessors(); if (!processors.isEmpty()) { options.add("-processor"); options.add(StringUtil.join(processors, ",")); } for (Map.Entry<String, String> optionEntry : profile.getProcessorOptions().entrySet()) { options.add("-A" + optionEntry.getKey() + "=" + optionEntry.getValue()); } final File srcOutput = ProjectPaths.getAnnotationProcessorGeneratedSourcesOutputDir( chunk.getModules().iterator().next(), chunk.containsTests(), profile); if (srcOutput != null) { srcOutput.mkdirs(); options.add("-s"); options.add(srcOutput.getPath()); } } else { options.add("-proc:none"); } }
private boolean compileJava( final CompileContext context, ModuleChunk chunk, Collection<File> files, Collection<File> classpath, Collection<File> platformCp, Collection<File> sourcePath, DiagnosticOutputConsumer diagnosticSink, final OutputFileConsumer outputSink) throws Exception { final TasksCounter counter = new TasksCounter(); COUNTER_KEY.set(context, counter); final JpsJavaExtensionService javaExt = JpsJavaExtensionService.getInstance(); final JpsJavaCompilerConfiguration compilerConfig = javaExt.getCompilerConfiguration(context.getProjectDescriptor().getProject()); assert compilerConfig != null; final Set<JpsModule> modules = chunk.getModules(); ProcessorConfigProfile profile = null; if (modules.size() == 1) { final JpsModule module = modules.iterator().next(); profile = compilerConfig.getAnnotationProcessingProfile(module); } else { // perform cycle-related validations Pair<String, LanguageLevel> pair = null; for (JpsModule module : modules) { final LanguageLevel moduleLevel = javaExt.getLanguageLevel(module); if (pair == null) { pair = Pair.create(module.getName(), moduleLevel); // first value } else { if (!Comparing.equal(pair.getSecond(), moduleLevel)) { final String message = "Modules " + pair.getFirst() + " and " + module.getName() + " must have the same language level because of cyclic dependencies between them"; diagnosticSink.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, message)); return true; } } } // check that all chunk modules are excluded from annotation processing for (JpsModule module : modules) { final ProcessorConfigProfile prof = compilerConfig.getAnnotationProcessingProfile(module); if (prof.isEnabled()) { final String message = "Annotation processing is not supported for module cycles. Please ensure that all modules from cycle [" + chunk.getName() + "] are excluded from annotation processing"; diagnosticSink.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, message)); return true; } } } final Map<File, Set<File>> outs = buildOutputDirectoriesMap(context, chunk); final List<String> options = getCompilationOptions(context, chunk, profile); final ClassProcessingConsumer classesConsumer = new ClassProcessingConsumer(context, outputSink); if (LOG.isDebugEnabled()) { LOG.debug( "Compiling chunk [" + chunk.getName() + "] with options: \"" + StringUtil.join(options, " ") + "\""); } try { final boolean rc; if (USE_EMBEDDED_JAVAC) { final boolean useEclipse = useEclipseCompiler(context); rc = JavacMain.compile( options, files, classpath, platformCp, sourcePath, outs, diagnosticSink, classesConsumer, context.getCancelStatus(), useEclipse); } else { final JavacServerClient client = ensureJavacServerLaunched(context); final RequestFuture<JavacServerResponseHandler> future = client.sendCompileRequest( options, files, classpath, platformCp, sourcePath, outs, diagnosticSink, classesConsumer); while (!future.waitFor(100L, TimeUnit.MILLISECONDS)) { if (context.getCancelStatus().isCanceled()) { future.cancel(false); } } rc = future.getMessageHandler().isTerminatedSuccessfully(); } return rc; } finally { counter.await(); } }