Package com.google.gwt.dev

Source Code of com.google.gwt.dev.LibraryCompiler$ArgProcessor

/*
* 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.
* <p>
* When compiling the top-level module, you should also pass the -link and -war flags to create the
* GWT application.
* <p>
* 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<PersistenceBackedObject<PermutationResult>> permutationResultFiles =
          new ArrayList<PersistenceBackedObject<PermutationResult>>();
      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<PermutationResult> libraryPermutationResults = Sets.newLinkedHashSet();
    List<PersistenceBackedObject<PermutationResult>> resultFiles = Lists.newArrayList();
    resultFiles.add(resultLibrary.getPermutationResultHandle());
    List<PersistenceBackedObject<PermutationResult>> permutationResultHandles =
        libraryGroup.getPermutationResultHandlesInLinkOrder();
    for (PersistenceBackedObject<PermutationResult> 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);
  }
}
TOP

Related Classes of com.google.gwt.dev.LibraryCompiler$ArgProcessor

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.