All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.google.gwt.dev.LibraryCompiler Maven / Gradle / Ivy

/*
 * Copyright 2014 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.google.gwt.dev;

import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.UnableToCompleteException;
import com.google.gwt.core.ext.linker.ArtifactSet;
import com.google.gwt.dev.CompileTaskRunner.CompileTask;
import com.google.gwt.dev.cfg.Libraries.IncompatibleLibraryVersionException;
import com.google.gwt.dev.cfg.Library;
import com.google.gwt.dev.cfg.LibraryGroup;
import com.google.gwt.dev.cfg.LibraryWriter;
import com.google.gwt.dev.cfg.ModuleDef;
import com.google.gwt.dev.cfg.ModuleDefLoader;
import com.google.gwt.dev.cfg.ResourceLoader;
import com.google.gwt.dev.cfg.ResourceLoaders;
import com.google.gwt.dev.cfg.ZipLibrary;
import com.google.gwt.dev.cfg.ZipLibraryWriter;
import com.google.gwt.dev.javac.UnitCacheSingleton;
import com.google.gwt.dev.jjs.JsOutputOption;
import com.google.gwt.dev.jjs.PermutationResult;
import com.google.gwt.dev.url.CloseableJarHandlerFactory;
import com.google.gwt.dev.util.Memory;
import com.google.gwt.dev.util.PersistenceBackedObject;
import com.google.gwt.dev.util.TinyCompileSummary;
import com.google.gwt.dev.util.Util;
import com.google.gwt.dev.util.arg.ArgHandlerDeployDir;
import com.google.gwt.dev.util.arg.ArgHandlerExtraDir;
import com.google.gwt.dev.util.arg.ArgHandlerLibraries;
import com.google.gwt.dev.util.arg.ArgHandlerLink;
import com.google.gwt.dev.util.arg.ArgHandlerLocalWorkers;
import com.google.gwt.dev.util.arg.ArgHandlerOutputLibrary;
import com.google.gwt.dev.util.arg.ArgHandlerSaveSourceOutput;
import com.google.gwt.dev.util.arg.ArgHandlerWarDir;
import com.google.gwt.dev.util.arg.ArgHandlerWorkDirOptional;
import com.google.gwt.dev.util.arg.OptionOptimize;
import com.google.gwt.dev.util.log.speedtracer.CompilerEventType;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger;
import com.google.gwt.dev.util.log.speedtracer.SpeedTracerLogger.Event;
import com.google.gwt.thirdparty.guava.common.base.Preconditions;
import com.google.gwt.thirdparty.guava.common.base.Strings;
import com.google.gwt.thirdparty.guava.common.collect.Lists;
import com.google.gwt.thirdparty.guava.common.collect.Sets;
import com.google.gwt.util.tools.Utility;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * Executable compiler entry point that constructs a library from an input module and its library
 * dependencies.
 * 

* When compiling the top-level module, you should also pass the -link and -war flags to create the * GWT application. *

* This is an alternative to Compiler.java which does a full world compile that neither reads nor * writes libraries. */ public class LibraryCompiler { private static class ArgProcessor extends PrecompileTaskArgProcessor { public ArgProcessor(CompilerOptions options) { super(options); registerHandler(new ArgHandlerLocalWorkers(options)); // Override the ArgHandlerWorkDirRequired in the super class. registerHandler(new ArgHandlerWorkDirOptional(options)); registerHandler(new ArgHandlerWarDir(options)); registerHandler(new ArgHandlerDeployDir(options)); registerHandler(new ArgHandlerExtraDir(options)); registerHandler(new ArgHandlerLink(options)); registerHandler(new ArgHandlerOutputLibrary(options)); registerHandler(new ArgHandlerLibraries(options)); registerHandler(new ArgHandlerSaveSourceOutput(options)); } @Override protected String getName() { return LibraryCompiler.class.getName(); } } public static void main(String[] args) { Memory.initialize(); SpeedTracerLogger.init(); final CompilerOptions compilerOptions = new CompilerOptionsImpl(); ArgProcessor argProcessor = new ArgProcessor(compilerOptions); if (argProcessor.processArgs(args)) { CompileTask compileTask = new CompileTask() { @Override public boolean run(TreeLogger logger) throws UnableToCompleteException { return new LibraryCompiler(compilerOptions).run(logger); } }; boolean success = CompileTaskRunner.runWithAppropriateLogger(compilerOptions, compileTask); System.exit(success ? 0 : 1); } } private CompilerContext compilerContext; private final CompilerContext.Builder compilerContextBuilder = new CompilerContext.Builder(); private final CompilerOptionsImpl compilerOptions; private ArtifactSet generatedArtifacts; private LibraryGroup libraryGroup; private ModuleDef module; private Permutation[] permutations; private ResourceLoader resourceLoader = ResourceLoaders.forClassLoader(Thread.currentThread()); private Library resultLibrary; public LibraryCompiler(CompilerOptions compilerOptions) { this.compilerOptions = new CompilerOptionsImpl(compilerOptions); this.compilerContext = compilerContextBuilder.options(this.compilerOptions).compileMonolithic(false).build(); CloseableJarHandlerFactory.installOverride(); } ModuleDef getModule() { return module; } boolean run(TreeLogger logger) { try { normalizeOptions(logger); loadLibraries(logger); loadModule(logger); compileModule(logger); if (compilerOptions.shouldLink()) { linkLibraries(logger); } return true; } catch (UnableToCompleteException e) { // The real cause has been logged. return false; } finally { // Close all zip files, otherwise the JVM may crash on linux. compilerContext.getLibraryGroup().close(); if (resultLibrary != null) { resultLibrary.close(); } } } void setResourceLoader(ResourceLoader resourceLoader) { this.resourceLoader = resourceLoader; } private void compileModule(TreeLogger logger) throws UnableToCompleteException { long beforeCompileMs = System.currentTimeMillis(); LibraryWriter libraryWriter = compilerContext.getLibraryWriter(); try { if (compilerOptions.isValidateOnly()) { boolean valid = Precompile.validate(logger, compilerContext); if (!valid) { // The real cause has been logged. throw new UnableToCompleteException(); } } Precompilation precompilation = Precompile.precompile(logger, compilerContext); if (precompilation == null) { // The real cause has been logged. throw new UnableToCompleteException(); } // TODO(stalcup): move to precompile() after params are refactored if (!compilerOptions.shouldSaveSource()) { precompilation.removeSourceArtifacts(logger); } Event compilePermutationsEvent = SpeedTracerLogger.start(CompilerEventType.COMPILE_PERMUTATIONS); permutations = new Permutation[] {precompilation.getPermutations()[0]}; List> permutationResultFiles = new ArrayList>(); permutationResultFiles.add(libraryWriter.getPermutationResultHandle()); CompilePerms.compile(logger, compilerContext, precompilation, permutations, compilerOptions.getLocalWorkers(), permutationResultFiles); compilePermutationsEvent.end(); generatedArtifacts = precompilation.getGeneratedArtifacts(); libraryWriter.addGeneratedArtifacts(generatedArtifacts); libraryWriter.setCompilationErrorsIndex(compilerContext.getLocalCompilationErrorsIndex()); } finally { // Even if a compile problem occurs, close the library cleanly so that it can be examined. libraryWriter.write(); } long durationMs = System.currentTimeMillis() - beforeCompileMs; TreeLogger detailBranch = logger.branch(TreeLogger.INFO, String.format("%.3fs -- Translating Java to Javascript", durationMs / 1000d)); TinyCompileSummary tinyCompileSummary = compilerContext.getTinyCompileSummary(); boolean shouldWarn = tinyCompileSummary.getTypesForGeneratorsCount() + tinyCompileSummary.getTypesForAstCount() > 1500; String recommendation = shouldWarn ? " This module should probably be split into smaller " + "modules or should trigger fewer generators since its current size hurts " + "incremental compiles." : ""; detailBranch.log(shouldWarn ? TreeLogger.WARN : TreeLogger.INFO, String.format( "There were %s static source files, %s generated source files, %s types loaded for " + "generators and %s types loaded for AST construction. %s", tinyCompileSummary.getStaticSourceFilesCount(), tinyCompileSummary.getGeneratedSourceFilesCount(), tinyCompileSummary.getTypesForGeneratorsCount(), tinyCompileSummary.getTypesForAstCount(), recommendation)); } private void linkLibraries(TreeLogger logger) throws UnableToCompleteException { long beforeLinkMs = System.currentTimeMillis(); Event linkEvent = SpeedTracerLogger.start(CompilerEventType.LINK); // Load up the library that was just created so that it's possible to get a read-reference to // its contained PermutationResult. try { resultLibrary = new ZipLibrary(compilerOptions.getOutputLibraryPath()); } catch (IncompatibleLibraryVersionException e) { logger.log(TreeLogger.ERROR, e.getMessage()); throw new UnableToCompleteException(); } generatedArtifacts.addAll(libraryGroup.getGeneratedArtifacts()); Set libraryPermutationResults = Sets.newLinkedHashSet(); List> resultFiles = Lists.newArrayList(); resultFiles.add(resultLibrary.getPermutationResultHandle()); List> permutationResultHandles = libraryGroup.getPermutationResultHandlesInLinkOrder(); for (PersistenceBackedObject permutationResultHandle : permutationResultHandles) { libraryPermutationResults.add(permutationResultHandle.newInstance(logger)); } try { Link.link(TreeLogger.NULL, module, compilerContext.getPublicResourceOracle(), generatedArtifacts, permutations, resultFiles, libraryPermutationResults, compilerOptions, compilerOptions); long durationMs = System.currentTimeMillis() - beforeLinkMs; logger.log(TreeLogger.INFO, String.format("%.3fs -- Successfully linking application", durationMs / 1000d)); } catch (IOException e) { long durationMs = System.currentTimeMillis() - beforeLinkMs; logger.log(TreeLogger.INFO, String.format("%.3fs -- Failing to link application", durationMs / 1000d)); throw new UnableToCompleteException(); } linkEvent.end(); } private void loadLibraries(TreeLogger logger) throws UnableToCompleteException { try { libraryGroup = LibraryGroup.fromZipPaths(compilerOptions.getLibraryPaths()); } catch (IncompatibleLibraryVersionException e) { logger.log(TreeLogger.ERROR, e.getMessage()); throw new UnableToCompleteException(); } libraryGroup.verify(logger); try { CloseableJarHandlerFactory.closeStreams(compilerOptions.getOutputLibraryPath()); } catch (IOException e) { logger.log(TreeLogger.WARN, String.format("Failed to close old connections to %s. " + "Repeated incremental compiles in the same JVM process may fail.", compilerOptions.getOutputLibraryPath())); } ZipLibraryWriter zipLibraryWriter = new ZipLibraryWriter(compilerOptions.getOutputLibraryPath()); compilerContext = compilerContextBuilder.libraryGroup(libraryGroup).libraryWriter( zipLibraryWriter).unitCache(UnitCacheSingleton.get(logger, compilerOptions.getWorkDir())) .build(); } private void loadModule(TreeLogger logger) throws UnableToCompleteException { long beforeLoadModuleMs = System.currentTimeMillis(); module = ModuleDefLoader.loadFromResources(logger, compilerContext, compilerOptions.getModuleNames().get(0), resourceLoader, false); compilerContext = compilerContextBuilder.module(module).build(); long durationMs = System.currentTimeMillis() - beforeLoadModuleMs; logger.log(TreeLogger.INFO, String.format("%.3fs -- Parsing and loading module definition", durationMs / 1000d)); } private void normalizeOptions(TreeLogger logger) throws UnableToCompleteException { Preconditions.checkArgument(compilerOptions.getModuleNames().size() == 1); // Current optimization passes are not safe with only partial data. compilerOptions.setOptimizationLevel(OptionOptimize.OPTIMIZE_LEVEL_DRAFT); // Protects against rampant overlapping source inclusion. compilerOptions.setEnforceStrictSourceResources(true); // Ensures that output JS identifiers are named consistently in all modules. compilerOptions.setOutput(JsOutputOption.DETAILED); // Code splitting isn't possible when you can't trace the entire control flow. compilerOptions.setRunAsyncEnabled(false); compilerOptions.setClosureCompilerEnabled(false); if (compilerOptions.getWorkDir() == null) { try { compilerOptions.setWorkDir(Utility.makeTemporaryDirectory(null, "gwtc")); Runtime.getRuntime().addShutdownHook(new Thread() { @Override public void run() { Util.recursiveDelete(compilerOptions.getWorkDir(), false); } }); } catch (IOException e) { logger.log(TreeLogger.ERROR, e.getMessage()); throw new UnableToCompleteException(); } } if ((compilerOptions.isSoycEnabled() || compilerOptions.isJsonSoycEnabled()) && compilerOptions.getExtraDir() == null) { compilerOptions.setExtraDir(new File("extras")); } if (Strings.isNullOrEmpty(compilerOptions.getOutputLibraryPath())) { compilerOptions.setOutputLibraryPath(compilerOptions.getWorkDir().getPath() + "/" + compilerOptions.getModuleNames().get(0) + ".gwtlib"); } // Optimize early since permutation compiles will run in process. compilerOptions.setOptimizePrecompile(true); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy