public static boolean compile( Collection<String> options, final Collection<File> sources, Collection<File> classpath, Collection<File> platformClasspath, Collection<File> sourcePath, Map<File, Set<File>> outputDirToRoots, final DiagnosticOutputConsumer outConsumer, final OutputFileConsumer outputSink, CanceledStatus canceledStatus, boolean useEclipseCompiler) { JavaCompiler compiler = null; if (useEclipseCompiler) { for (JavaCompiler javaCompiler : ServiceLoader.load(JavaCompiler.class)) { compiler = javaCompiler; break; } if (compiler == null) { outConsumer.report( new PlainMessageDiagnostic( Diagnostic.Kind.ERROR, "Eclipse Batch Compiler was not found in classpath")); return false; } } final boolean nowUsingJavac; if (compiler == null) { compiler = ToolProvider.getSystemJavaCompiler(); if (compiler == null) { outConsumer.report( new PlainMessageDiagnostic( Diagnostic.Kind.ERROR, "System Java Compiler was not found in classpath")); return false; } nowUsingJavac = true; } else { nowUsingJavac = false; } for (File outputDir : outputDirToRoots.keySet()) { outputDir.mkdirs(); } final List<JavaSourceTransformer> transformers = getSourceTransformers(); final JavacFileManager fileManager = new JavacFileManager( new ContextImpl(compiler, outConsumer, outputSink, canceledStatus, nowUsingJavac), transformers); fileManager.handleOption( "-bootclasspath", Collections.singleton("").iterator()); // this will clear cached stuff fileManager.handleOption( "-extdirs", Collections.singleton("").iterator()); // this will clear cached stuff try { fileManager.setOutputDirectories(outputDirToRoots); } catch (IOException e) { fileManager.getContext().reportMessage(Diagnostic.Kind.ERROR, e.getMessage()); return false; } if (!classpath.isEmpty()) { try { fileManager.setLocation(StandardLocation.CLASS_PATH, classpath); if (!nowUsingJavac && !isOptionSet(options, "-processorpath")) { // for non-javac file manager ensure annotation processor path defaults to classpath fileManager.setLocation(StandardLocation.ANNOTATION_PROCESSOR_PATH, classpath); } } catch (IOException e) { fileManager.getContext().reportMessage(Diagnostic.Kind.ERROR, e.getMessage()); return false; } } if (!platformClasspath.isEmpty()) { try { fileManager.setLocation(StandardLocation.PLATFORM_CLASS_PATH, platformClasspath); } catch (IOException e) { fileManager.getContext().reportMessage(Diagnostic.Kind.ERROR, e.getMessage()); return false; } } try { // ensure the source path is set; // otherwise, if not set, javac attempts to search both classes and sources in classpath; // so if some classpath jars contain sources, it will attempt to compile them fileManager.setLocation(StandardLocation.SOURCE_PATH, sourcePath); } catch (IOException e) { fileManager.getContext().reportMessage(Diagnostic.Kind.ERROR, e.getMessage()); return false; } //noinspection IOResourceOpenedButNotSafelyClosed final LineOutputWriter out = new LineOutputWriter() { protected void lineAvailable(String line) { if (nowUsingJavac) { outConsumer.outputLineAvailable(line); } else { // todo: filter too verbose eclipse output? } } }; try { final Collection<String> _options = prepareOptions(options, nowUsingJavac); // to be on the safe side, we'll have to apply all options _before_ calling any of manager's // methods // i.e. getJavaFileObjectsFromFiles() // This way the manager will be properly initialized. Namely, the encoding will be set // correctly for (Iterator<String> iterator = _options.iterator(); iterator.hasNext(); ) { fileManager.handleOption(iterator.next(), iterator); } final JavaCompiler.CompilationTask task = compiler.getTask( out, fileManager, outConsumer, _options, null, fileManager.getJavaFileObjectsFromFiles(sources)); // if (!IS_VM_6_VERSION) { //todo! // // Do not add the processor for JDK 1.6 because of the bugs in javac // // The processor's presence may lead to NPE and resolve bugs in compiler // final JavacASTAnalyser analyzer = new JavacASTAnalyser(outConsumer, // !annotationProcessingEnabled); // task.setProcessors(Collections.singleton(analyzer)); // } return task.call(); } catch (IllegalArgumentException e) { outConsumer.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, e.getMessage())); } catch (CompilationCanceledException ignored) { outConsumer.report( new PlainMessageDiagnostic(Diagnostic.Kind.OTHER, "Compilation was canceled")); } finally { fileManager.close(); if (nowUsingJavac) { cleanupJavacNameTable(); } } return false; }
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(); } }
public void reportMessage(final Diagnostic.Kind kind, String message) { myOutConsumer.report(new PlainMessageDiagnostic(kind, message)); }