| /* |
| * Copyright 2010 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.impl.StandardLinkerContext; |
| import com.google.gwt.dev.CompileTaskRunner.CompileTask; |
| import com.google.gwt.dev.cfg.ModuleDef; |
| import com.google.gwt.dev.cfg.ModuleDefLoader; |
| import com.google.gwt.dev.cfg.PropertyCombinations; |
| import com.google.gwt.dev.shell.CheckForUpdates; |
| import com.google.gwt.dev.shell.CheckForUpdates.UpdateResult; |
| import com.google.gwt.dev.util.Memory; |
| import com.google.gwt.dev.util.Util; |
| import com.google.gwt.dev.util.arg.ArgHandlerPerm; |
| import com.google.gwt.dev.util.arg.OptionPerm; |
| 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 java.io.File; |
| import java.util.List; |
| import java.util.concurrent.FutureTask; |
| |
| /** |
| * Creates a ready-to-compile AST for a single permutation. |
| * |
| * Also collapses similar permutations and builds them together. |
| */ |
| public class PrecompileOnePerm { |
| |
| /** |
| * The set of options for the precompiler. |
| */ |
| public interface PrecompileOnePermOptions extends |
| PrecompileTaskOptions, OptionPerm { |
| } |
| |
| static class ArgProcessor extends PrecompileTaskArgProcessor { |
| public ArgProcessor(PrecompileOnePermOptions options) { |
| super(options); |
| registerHandler(new ArgHandlerPerm(options)); |
| } |
| |
| @Override |
| protected String getName() { |
| return PrecompileOnePerm.class.getName(); |
| } |
| } |
| |
| @SuppressWarnings("serial") |
| static class PrecompileOnePermOptionsImpl extends |
| PrecompileTaskOptionsImpl implements PrecompileOnePermOptions { |
| |
| int permToCompile = -1; |
| |
| public PrecompileOnePermOptionsImpl() { |
| } |
| |
| public PrecompileOnePermOptionsImpl(PrecompileOnePermOptions other) { |
| copyFrom(other); |
| } |
| |
| public void copyFrom(PrecompileOnePermOptions other) { |
| super.copyFrom(other); |
| setPermToCompile(other.getPermToCompile()); |
| } |
| |
| @Override |
| public int getPermToCompile() { |
| return permToCompile; |
| } |
| |
| @Override |
| public void setPermToCompile(int permToCompile) { |
| this.permToCompile = permToCompile; |
| } |
| } |
| |
| /** |
| * Performs a command-line precompile. |
| */ |
| public static void main(String[] args) { |
| Memory.initialize(); |
| SpeedTracerLogger.init(); |
| Event precompileEvent = SpeedTracerLogger.start(CompilerEventType.PRECOMPILE); |
| if (System.getProperty("gwt.jjs.dumpAst") != null) { |
| System.out.println("Will dump AST to: " |
| + System.getProperty("gwt.jjs.dumpAst")); |
| } |
| |
| /* |
| * NOTE: main always exits with a call to System.exit to terminate any |
| * non-daemon threads that were started in Generators. Typically, this is to |
| * shutdown AWT related threads, since the contract for their termination is |
| * still implementation-dependent. |
| */ |
| final PrecompileOnePermOptions options = new PrecompileOnePermOptionsImpl(); |
| boolean success = false; |
| if (new ArgProcessor(options).processArgs(args)) { |
| CompileTask task = new CompileTask() { |
| @Override |
| public boolean run(TreeLogger logger) throws UnableToCompleteException { |
| FutureTask<UpdateResult> updater = null; |
| if (!options.isUpdateCheckDisabled()) { |
| updater = CheckForUpdates.checkForUpdatesInBackgroundThread(logger, |
| CheckForUpdates.ONE_DAY); |
| } |
| boolean success = new PrecompileOnePerm(options).run(logger); |
| if (success) { |
| CheckForUpdates.logUpdateAvailable(logger, updater); |
| } |
| return success; |
| } |
| }; |
| if (CompileTaskRunner.runWithAppropriateLogger(options, task)) { |
| // Exit w/ success code. |
| success = true; |
| } |
| } |
| precompileEvent.end(); |
| System.exit(success ? 0 : 1); |
| } |
| |
| /** |
| * Returns a filename for the serialized AST when precompile is performed |
| * separately on a per-permutation basis. |
| */ |
| static String getPrecompileFilename(int permutationBase) { |
| return Precompile.PRECOMPILE_FILENAME_PREFIX + "-" + permutationBase |
| + Precompile.PRECOMPILE_FILENAME_SUFFIX; |
| } |
| |
| private static boolean validateOptions(TreeLogger logger, PrecompileOnePermOptions options) { |
| // Fatal Errors |
| if (options.getModuleNames().size() != 1) { |
| logger.log(TreeLogger.ERROR, "Expected a single module name."); |
| return false; |
| } |
| if (options.getPermToCompile() < 0) { |
| logger.log(TreeLogger.ERROR, |
| "Expected argument -perm to specify the permutation to compile."); |
| return false; |
| } |
| |
| // Warnings |
| if (!options.isEnabledGeneratingOnShards()) { |
| logger.log(TreeLogger.WARN, |
| "-XdisableGeneratingOnShards has no effect in PrecompileOnePerm"); |
| } |
| |
| return true; |
| } |
| |
| private final PrecompileOnePermOptionsImpl options; |
| |
| private CompilerContext compilerContext; |
| |
| private final CompilerContext.Builder compilerContextBuilder = new CompilerContext.Builder(); |
| |
| public PrecompileOnePerm(PrecompileOnePermOptions options) { |
| this.options = new PrecompileOnePermOptionsImpl(options); |
| compilerContext = compilerContextBuilder.options(options).build(); |
| } |
| |
| public boolean run(TreeLogger logger) throws UnableToCompleteException { |
| |
| if (!validateOptions(logger, options)) { |
| return false; |
| } |
| |
| List<String> moduleNames = options.getModuleNames(); |
| |
| int permToRun = options.getPermToCompile(); |
| |
| String moduleName = moduleNames.get(0); |
| File compilerWorkDir = options.getCompilerWorkDir(moduleName); |
| |
| ModuleDef module = ModuleDefLoader.loadFromClassPath(logger, moduleName); |
| compilerContext = compilerContextBuilder.module(module).build(); |
| StandardLinkerContext linkerContext = new StandardLinkerContext( |
| TreeLogger.NULL, module, compilerContext.getPublicResourceOracle(), options.getOutput()); |
| |
| if (!linkerContext.allLinkersAreShardable()) { |
| logger.log(TreeLogger.ERROR, |
| "This compilation mode requires all linkers to be shardable."); |
| return false; |
| } |
| |
| PrecompileTaskOptions optionsFileData = AnalyzeModule.readAnalyzeModuleOptionsFile( |
| logger, compilerWorkDir); |
| if (optionsFileData == null) { |
| logger.log(TreeLogger.ERROR, "Couldn't find " |
| + AnalyzeModule.OPTIONS_FILENAME + " in " + compilerWorkDir); |
| return false; |
| } |
| logger.log(TreeLogger.INFO, "Precompiling only specified permutations"); |
| |
| if (options.isValidateOnly()) { |
| TreeLogger branch = logger.branch(TreeLogger.INFO, |
| "Validating compilation " + module.getName()); |
| if (!Precompile.validate(branch, compilerContext)) { |
| branch.log(TreeLogger.ERROR, "Validation failed"); |
| return false; |
| } |
| branch.log(TreeLogger.INFO, "Validation succeeded"); |
| } else { |
| TreeLogger branch = logger.branch(TreeLogger.INFO, "Precompiling module " |
| + module.getName()); |
| if (!precompilePermutation(logger, compilerWorkDir, module, branch, |
| permToRun)) { |
| branch.log(TreeLogger.ERROR, "Precompile failed"); |
| return false; |
| } |
| } |
| return true; |
| } |
| |
| private boolean precompilePermutation(TreeLogger logger, |
| File compilerWorkDir, ModuleDef module, TreeLogger branch, int permId) |
| throws UnableToCompleteException { |
| |
| // Only precompile specified permutations |
| List<PropertyCombinations> collapsedPermutations = |
| Precompile.getCollapsedPermutations(module); |
| |
| PropertyCombinations onePerm = collapsedPermutations.get(permId); |
| Precompilation precompilation = Precompile.precompile(branch, compilerContext, permId, onePerm); |
| if (precompilation == null) { |
| branch.log(TreeLogger.ERROR, "Precompilation failed"); |
| return false; |
| } |
| |
| // TODO: precompile should do this after we get the parameter passing refactored. |
| if (!options.shouldSaveSource()) { |
| precompilation.removeSourceArtifacts(logger); |
| } |
| |
| File precompilationFile = new File(compilerWorkDir, |
| getPrecompileFilename(permId)); |
| Util.writeObjectAsFile(logger, precompilationFile, precompilation); |
| |
| if (branch.isLoggable(TreeLogger.INFO)) { |
| branch.log(TreeLogger.INFO, "Precompilation succeeded for permutation " |
| + permId); |
| } |
| |
| return true; |
| } |
| } |