| /* |
| * Copyright 2008 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.BindingProperty; |
| import com.google.gwt.dev.cfg.ConfigurationProperty; |
| import com.google.gwt.dev.cfg.ModuleDef; |
| import com.google.gwt.dev.cfg.ModuleDefLoader; |
| import com.google.gwt.dev.cfg.PropertyPermutations; |
| import com.google.gwt.dev.cfg.Rules; |
| import com.google.gwt.dev.cfg.StaticPropertyOracle; |
| import com.google.gwt.dev.javac.CompilationState; |
| import com.google.gwt.dev.javac.CompilationUnit; |
| import com.google.gwt.dev.javac.StandardGeneratorContext; |
| import com.google.gwt.dev.jdt.RebindOracle; |
| import com.google.gwt.dev.jdt.RebindPermutationOracle; |
| import com.google.gwt.dev.jjs.AbstractCompiler; |
| import com.google.gwt.dev.jjs.JJSOptions; |
| import com.google.gwt.dev.jjs.JJSOptionsImpl; |
| import com.google.gwt.dev.jjs.JavaScriptCompiler; |
| import com.google.gwt.dev.jjs.JsOutputOption; |
| import com.google.gwt.dev.jjs.UnifiedAst; |
| import com.google.gwt.dev.shell.CheckForUpdates; |
| import com.google.gwt.dev.shell.StandardRebindOracle; |
| import com.google.gwt.dev.shell.CheckForUpdates.UpdateResult; |
| import com.google.gwt.dev.util.Memory; |
| import com.google.gwt.dev.util.PerfLogger; |
| import com.google.gwt.dev.util.Util; |
| import com.google.gwt.dev.util.arg.ArgHandlerCompileReport; |
| import com.google.gwt.dev.util.arg.ArgHandlerDisableAggressiveOptimization; |
| import com.google.gwt.dev.util.arg.ArgHandlerDisableCastChecking; |
| import com.google.gwt.dev.util.arg.ArgHandlerDisableClassMetadata; |
| import com.google.gwt.dev.util.arg.ArgHandlerDisableRunAsync; |
| import com.google.gwt.dev.util.arg.ArgHandlerDisableUpdateCheck; |
| import com.google.gwt.dev.util.arg.ArgHandlerDraftCompile; |
| import com.google.gwt.dev.util.arg.ArgHandlerDumpSignatures; |
| import com.google.gwt.dev.util.arg.ArgHandlerEnableAssertions; |
| import com.google.gwt.dev.util.arg.ArgHandlerGenDir; |
| import com.google.gwt.dev.util.arg.ArgHandlerMaxPermsPerPrecompile; |
| import com.google.gwt.dev.util.arg.ArgHandlerScriptStyle; |
| import com.google.gwt.dev.util.arg.ArgHandlerSoyc; |
| import com.google.gwt.dev.util.arg.ArgHandlerSoycDetailed; |
| import com.google.gwt.dev.util.arg.ArgHandlerValidateOnlyFlag; |
| import com.google.gwt.dev.util.arg.OptionDisableUpdateCheck; |
| import com.google.gwt.dev.util.arg.OptionDumpSignatures; |
| import com.google.gwt.dev.util.arg.OptionGenDir; |
| import com.google.gwt.dev.util.arg.OptionMaxPermsPerPrecompile; |
| import com.google.gwt.dev.util.arg.OptionValidateOnly; |
| |
| import java.io.File; |
| import java.io.FileOutputStream; |
| import java.io.IOException; |
| import java.util.Collection; |
| import java.util.HashSet; |
| import java.util.Set; |
| import java.util.SortedMap; |
| import java.util.SortedSet; |
| import java.util.TreeMap; |
| import java.util.concurrent.FutureTask; |
| import java.util.jar.JarOutputStream; |
| import java.util.zip.ZipEntry; |
| |
| /** |
| * Performs the first phase of compilation, generating the set of permutations |
| * to compile, and a ready-to-compile AST. |
| */ |
| public class Precompile { |
| |
| /** |
| * The set of options for the precompiler. |
| */ |
| public interface PrecompileOptions extends JJSOptions, CompileTaskOptions, |
| OptionGenDir, OptionValidateOnly, OptionDisableUpdateCheck, |
| OptionDumpSignatures, OptionMaxPermsPerPrecompile { |
| } |
| |
| static class ArgProcessor extends CompileArgProcessor { |
| public ArgProcessor(PrecompileOptions options) { |
| super(options); |
| registerHandler(new ArgHandlerGenDir(options)); |
| registerHandler(new ArgHandlerScriptStyle(options)); |
| registerHandler(new ArgHandlerEnableAssertions(options)); |
| registerHandler(new ArgHandlerDisableAggressiveOptimization(options)); |
| registerHandler(new ArgHandlerDisableClassMetadata(options)); |
| registerHandler(new ArgHandlerDisableCastChecking(options)); |
| registerHandler(new ArgHandlerValidateOnlyFlag(options)); |
| registerHandler(new ArgHandlerDisableRunAsync(options)); |
| registerHandler(new ArgHandlerDraftCompile(options)); |
| registerHandler(new ArgHandlerDisableUpdateCheck(options)); |
| registerHandler(new ArgHandlerDumpSignatures(options)); |
| registerHandler(new ArgHandlerMaxPermsPerPrecompile(options)); |
| registerHandler(new ArgHandlerCompileReport(options)); |
| registerHandler(new ArgHandlerSoyc(options)); |
| registerHandler(new ArgHandlerSoycDetailed(options)); |
| } |
| |
| @Override |
| protected String getName() { |
| return Precompile.class.getName(); |
| } |
| } |
| |
| static class PrecompileOptionsImpl extends CompileTaskOptionsImpl implements |
| PrecompileOptions { |
| private boolean disableUpdateCheck; |
| private File dumpFile; |
| private File genDir; |
| private final JJSOptionsImpl jjsOptions = new JJSOptionsImpl(); |
| private int maxPermsPerPrecompile; |
| private boolean validateOnly; |
| |
| public PrecompileOptionsImpl() { |
| } |
| |
| public PrecompileOptionsImpl(PrecompileOptions other) { |
| copyFrom(other); |
| } |
| |
| public void copyFrom(PrecompileOptions other) { |
| super.copyFrom(other); |
| |
| jjsOptions.copyFrom(other); |
| |
| setDisableUpdateCheck(other.isUpdateCheckDisabled()); |
| setDumpSignatureFile(other.getDumpSignatureFile()); |
| setGenDir(other.getGenDir()); |
| setMaxPermsPerPrecompile(other.getMaxPermsPerPrecompile()); |
| setValidateOnly(other.isValidateOnly()); |
| } |
| |
| public File getDumpSignatureFile() { |
| return dumpFile; |
| } |
| |
| public File getGenDir() { |
| return genDir; |
| } |
| |
| public int getMaxPermsPerPrecompile() { |
| return maxPermsPerPrecompile; |
| } |
| |
| public JsOutputOption getOutput() { |
| return jjsOptions.getOutput(); |
| } |
| |
| public boolean isAggressivelyOptimize() { |
| return jjsOptions.isAggressivelyOptimize(); |
| } |
| |
| public boolean isCastCheckingDisabled() { |
| return jjsOptions.isCastCheckingDisabled(); |
| } |
| |
| public boolean isClassMetadataDisabled() { |
| return jjsOptions.isClassMetadataDisabled(); |
| } |
| |
| public boolean isDraftCompile() { |
| return jjsOptions.isDraftCompile(); |
| } |
| |
| public boolean isEnableAssertions() { |
| return jjsOptions.isEnableAssertions(); |
| } |
| |
| public boolean isOptimizePrecompile() { |
| return jjsOptions.isOptimizePrecompile(); |
| } |
| |
| public boolean isRunAsyncEnabled() { |
| return jjsOptions.isRunAsyncEnabled(); |
| } |
| |
| public boolean isSoycEnabled() { |
| return jjsOptions.isSoycEnabled(); |
| } |
| |
| public boolean isSoycExtra() { |
| return jjsOptions.isSoycExtra(); |
| } |
| |
| public boolean isUpdateCheckDisabled() { |
| return disableUpdateCheck; |
| } |
| |
| public boolean isValidateOnly() { |
| return validateOnly; |
| } |
| |
| public void setAggressivelyOptimize(boolean aggressivelyOptimize) { |
| jjsOptions.setAggressivelyOptimize(aggressivelyOptimize); |
| } |
| |
| public void setCastCheckingDisabled(boolean disabled) { |
| jjsOptions.setCastCheckingDisabled(disabled); |
| } |
| |
| public void setClassMetadataDisabled(boolean disabled) { |
| jjsOptions.setClassMetadataDisabled(disabled); |
| } |
| |
| public void setDisableUpdateCheck(boolean disabled) { |
| disableUpdateCheck = disabled; |
| } |
| |
| public void setDraftCompile(boolean draft) { |
| jjsOptions.setDraftCompile(draft); |
| } |
| |
| public void setDumpSignatureFile(File dumpFile) { |
| this.dumpFile = dumpFile; |
| } |
| |
| public void setEnableAssertions(boolean enableAssertions) { |
| jjsOptions.setEnableAssertions(enableAssertions); |
| } |
| |
| public void setGenDir(File genDir) { |
| this.genDir = genDir; |
| } |
| |
| public void setMaxPermsPerPrecompile(int maxPermsPerPrecompile) { |
| this.maxPermsPerPrecompile = maxPermsPerPrecompile; |
| } |
| |
| public void setOptimizePrecompile(boolean optimize) { |
| jjsOptions.setOptimizePrecompile(optimize); |
| } |
| |
| public void setOutput(JsOutputOption output) { |
| jjsOptions.setOutput(output); |
| } |
| |
| public void setRunAsyncEnabled(boolean enabled) { |
| jjsOptions.setRunAsyncEnabled(enabled); |
| } |
| |
| public void setSoycEnabled(boolean enabled) { |
| jjsOptions.setSoycEnabled(enabled); |
| } |
| |
| public void setSoycExtra(boolean soycExtra) { |
| jjsOptions.setSoycExtra(soycExtra); |
| } |
| |
| public void setValidateOnly(boolean validateOnly) { |
| this.validateOnly = validateOnly; |
| } |
| } |
| |
| private static class DistillerRebindPermutationOracle implements |
| RebindPermutationOracle { |
| |
| private CompilationState compilationState; |
| private StandardGeneratorContext generatorContext; |
| private final Permutation[] permutations; |
| private final StaticPropertyOracle[] propertyOracles; |
| private final RebindOracle[] rebindOracles; |
| |
| public DistillerRebindPermutationOracle(ModuleDef module, |
| CompilationState compilationState, ArtifactSet generatorArtifacts, |
| PropertyPermutations perms, File genDir, File generatorResourcesDir) { |
| this.compilationState = compilationState; |
| permutations = new Permutation[perms.size()]; |
| propertyOracles = new StaticPropertyOracle[perms.size()]; |
| rebindOracles = new RebindOracle[perms.size()]; |
| generatorContext = new StandardGeneratorContext(compilationState, module, |
| genDir, generatorResourcesDir, generatorArtifacts); |
| BindingProperty[] orderedProps = perms.getOrderedProperties(); |
| SortedSet<ConfigurationProperty> configPropSet = module.getProperties().getConfigurationProperties(); |
| ConfigurationProperty[] configProps = configPropSet.toArray(new ConfigurationProperty[configPropSet.size()]); |
| Rules rules = module.getRules(); |
| for (int i = 0; i < rebindOracles.length; ++i) { |
| String[] orderedPropValues = perms.getOrderedPropertyValues(i); |
| propertyOracles[i] = new StaticPropertyOracle(orderedProps, |
| orderedPropValues, configProps); |
| rebindOracles[i] = new StandardRebindOracle(propertyOracles[i], rules, |
| generatorContext); |
| permutations[i] = new Permutation(i, propertyOracles[i]); |
| } |
| } |
| |
| public void clear() { |
| generatorContext.clear(); |
| compilationState = null; |
| generatorContext = null; |
| } |
| |
| public String[] getAllPossibleRebindAnswers(TreeLogger logger, |
| String requestTypeName) throws UnableToCompleteException { |
| |
| String msg = "Computing all possible rebind results for '" |
| + requestTypeName + "'"; |
| logger = logger.branch(TreeLogger.DEBUG, msg, null); |
| |
| Set<String> answers = new HashSet<String>(); |
| |
| for (int i = 0; i < getPermuationCount(); ++i) { |
| String resultTypeName = rebindOracles[i].rebind(logger, requestTypeName); |
| answers.add(resultTypeName); |
| // Record the correct answer into each permutation. |
| permutations[i].putRebindAnswer(requestTypeName, resultTypeName); |
| } |
| return Util.toArray(String.class, answers); |
| } |
| |
| public CompilationState getCompilationState() { |
| return compilationState; |
| } |
| |
| public StandardGeneratorContext getGeneratorContext() { |
| return generatorContext; |
| } |
| |
| public int getPermuationCount() { |
| return rebindOracles.length; |
| } |
| |
| public Permutation[] getPermutations() { |
| return permutations; |
| } |
| |
| public StaticPropertyOracle getPropertyOracle(int permNumber) { |
| return propertyOracles[permNumber]; |
| } |
| |
| public RebindOracle getRebindOracle(int permNumber) { |
| return rebindOracles[permNumber]; |
| } |
| } |
| |
| /** |
| * The file name for the result of Precompile. |
| */ |
| public static final String PRECOMPILE_FILENAME = "precompilation.ser"; |
| |
| static final String PERM_COUNT_FILENAME = "permCount.txt"; |
| |
| /** |
| * Performs a command-line precompile. |
| */ |
| public static void main(String[] args) { |
| Memory.initialize(); |
| 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 PrecompileOptions options = new PrecompileOptionsImpl(); |
| if (new ArgProcessor(options).processArgs(args)) { |
| CompileTask task = new CompileTask() { |
| public boolean run(TreeLogger logger) throws UnableToCompleteException { |
| FutureTask<UpdateResult> updater = null; |
| if (!options.isUpdateCheckDisabled()) { |
| updater = CheckForUpdates.checkForUpdatesInBackgroundThread(logger, |
| CheckForUpdates.ONE_DAY); |
| } |
| boolean success = new Precompile(options).run(logger); |
| if (success) { |
| CheckForUpdates.logUpdateAvailable(logger, updater); |
| } |
| return success; |
| } |
| }; |
| if (CompileTaskRunner.runWithAppropriateLogger(options, task)) { |
| // Exit w/ success code. |
| System.exit(0); |
| } |
| } |
| // Exit w/ non-success code. |
| System.exit(1); |
| } |
| |
| /** |
| * Precompiles the given module. |
| * |
| * @param logger a logger to use |
| * @param jjsOptions a set of compiler options |
| * @param module the module to compile |
| * @param genDir optional directory to dump generated source, may be |
| * <code>null</code> |
| * @param generatorResourcesDir required directory to dump generator resources |
| * @return the precompilation |
| */ |
| public static Precompilation precompile(TreeLogger logger, |
| JJSOptions jjsOptions, ModuleDef module, File genDir, |
| File generatorResourcesDir, File dumpSignatureFile) { |
| PropertyPermutations allPermutations = new PropertyPermutations( |
| module.getProperties()); |
| return precompile(logger, jjsOptions, module, 0, allPermutations, genDir, |
| generatorResourcesDir, dumpSignatureFile); |
| } |
| |
| /** |
| * Validates the given module can be compiled. |
| * |
| * @param logger a logger to use |
| * @param jjsOptions a set of compiler options |
| * @param module the module to compile |
| * @param genDir optional directory to dump generated source, may be |
| * <code>null</code> |
| * @param generatorResourcesDir required directory to dump generator resources |
| */ |
| public static boolean validate(TreeLogger logger, JJSOptions jjsOptions, |
| ModuleDef module, File genDir, File generatorResourcesDir, |
| File dumpSignatureFile) { |
| try { |
| CompilationState compilationState = module.getCompilationState(logger); |
| if (dumpSignatureFile != null) { |
| // Dump early to avoid generated types. |
| SignatureDumper.dumpSignatures(logger, |
| compilationState.getTypeOracle(), dumpSignatureFile); |
| } |
| |
| String[] declEntryPts = module.getEntryPointTypeNames(); |
| String[] additionalRootTypes = null; |
| if (declEntryPts.length == 0) { |
| // No declared entry points, just validate all visible classes. |
| Collection<CompilationUnit> compilationUnits = compilationState.getCompilationUnits(); |
| additionalRootTypes = new String[compilationUnits.size()]; |
| int i = 0; |
| for (CompilationUnit unit : compilationUnits) { |
| additionalRootTypes[i++] = unit.getTypeName(); |
| } |
| } |
| |
| ArtifactSet generatorArtifacts = new ArtifactSet(); |
| DistillerRebindPermutationOracle rpo = new DistillerRebindPermutationOracle( |
| module, compilationState, generatorArtifacts, |
| new PropertyPermutations(module.getProperties()), genDir, |
| generatorResourcesDir); |
| // Allow GC later. |
| compilationState = null; |
| if (dumpSignatureFile != null) { |
| // Dump early to avoid generated types. |
| SignatureDumper.dumpSignatures(logger, |
| compilationState.getTypeOracle(), dumpSignatureFile); |
| } |
| // Never optimize on a validation run. |
| jjsOptions.setOptimizePrecompile(false); |
| getCompiler(module).precompile(logger, module, rpo, declEntryPts, |
| additionalRootTypes, jjsOptions, true); |
| return true; |
| } catch (UnableToCompleteException e) { |
| // Already logged. |
| return false; |
| } |
| } |
| |
| private static AbstractCompiler getCompiler(ModuleDef module) { |
| ConfigurationProperty compilerClassProp = module.getProperties().createConfiguration( |
| "x.compiler.class", false); |
| String compilerClassName = compilerClassProp.getValue(); |
| if (compilerClassName == null || compilerClassName.length() == 0) { |
| return new JavaScriptCompiler(); |
| } |
| Throwable caught; |
| try { |
| Class<?> compilerClass = Class.forName(compilerClassName); |
| return (AbstractCompiler) compilerClass.newInstance(); |
| } catch (ClassNotFoundException e) { |
| caught = e; |
| } catch (InstantiationException e) { |
| caught = e; |
| } catch (IllegalAccessException e) { |
| caught = e; |
| } |
| throw new RuntimeException("Unable to instantiate compiler class '" |
| + compilerClassName + "'", caught); |
| } |
| |
| private static Precompilation precompile(TreeLogger logger, |
| JJSOptions jjsOptions, ModuleDef module, int permutationBase, |
| PropertyPermutations allPermutations, File genDir, |
| File generatorResourcesDir, File dumpSignatureFile) { |
| |
| try { |
| CompilationState compilationState = module.getCompilationState(logger); |
| if (dumpSignatureFile != null) { |
| // Dump early to avoid generated types. |
| SignatureDumper.dumpSignatures(logger, |
| compilationState.getTypeOracle(), dumpSignatureFile); |
| } |
| |
| String[] declEntryPts = module.getEntryPointTypeNames(); |
| if (declEntryPts.length == 0) { |
| logger.log(TreeLogger.ERROR, "Module has no entry points defined", null); |
| throw new UnableToCompleteException(); |
| } |
| |
| ArtifactSet generatedArtifacts = new ArtifactSet(); |
| DistillerRebindPermutationOracle rpo = new DistillerRebindPermutationOracle( |
| module, compilationState, generatedArtifacts, allPermutations, |
| genDir, generatorResourcesDir); |
| // Allow GC later. |
| compilationState = null; |
| PerfLogger.start("Precompile"); |
| UnifiedAst unifiedAst = getCompiler(module).precompile(logger, |
| module, rpo, declEntryPts, null, jjsOptions, |
| rpo.getPermuationCount() == 1); |
| PerfLogger.end(); |
| |
| // Merge all identical permutations together. |
| Permutation[] permutations = rpo.getPermutations(); |
| // Sort the permutations by an ordered key to ensure determinism. |
| SortedMap<String, Permutation> merged = new TreeMap<String, Permutation>(); |
| SortedSet<String> liveRebindRequests = unifiedAst.getRebindRequests(); |
| for (Permutation permutation : permutations) { |
| // Construct a key from the stringified map of live rebind answers. |
| SortedMap<String, String> rebindAnswers = new TreeMap<String, String>( |
| permutation.getRebindAnswers()); |
| rebindAnswers.keySet().retainAll(liveRebindRequests); |
| String key = rebindAnswers.toString(); |
| if (merged.containsKey(key)) { |
| Permutation existing = merged.get(key); |
| existing.mergeFrom(permutation, liveRebindRequests); |
| } else { |
| merged.put(key, permutation); |
| } |
| } |
| return new Precompilation(unifiedAst, merged.values(), permutationBase, |
| generatedArtifacts); |
| } catch (UnableToCompleteException e) { |
| // We intentionally don't pass in the exception here since the real |
| // cause has been logged. |
| return null; |
| } |
| } |
| |
| private final PrecompileOptionsImpl options; |
| |
| public Precompile(PrecompileOptions options) { |
| this.options = new PrecompileOptionsImpl(options); |
| } |
| |
| public boolean run(TreeLogger logger) throws UnableToCompleteException { |
| // Avoid early optimizations since permutation compiles will run separately. |
| options.setOptimizePrecompile(false); |
| |
| for (String moduleName : options.getModuleNames()) { |
| File compilerWorkDir = options.getCompilerWorkDir(moduleName); |
| Util.recursiveDelete(compilerWorkDir, true); |
| // No need to check mkdirs result because an IOException will occur anyway |
| compilerWorkDir.mkdirs(); |
| |
| JarOutputStream precompilationJar; |
| try { |
| precompilationJar = new JarOutputStream(new FileOutputStream(new File( |
| compilerWorkDir, PRECOMPILE_FILENAME))); |
| } catch (IOException e) { |
| logger.log(TreeLogger.ERROR, "Could not create " + PRECOMPILE_FILENAME, |
| e); |
| return false; |
| } |
| |
| ModuleDef module = ModuleDefLoader.loadFromClassPath(logger, moduleName); |
| |
| // TODO: All JDT checks now before even building TypeOracle? |
| module.getCompilationState(logger); |
| |
| if (options.isValidateOnly()) { |
| TreeLogger branch = logger.branch(TreeLogger.INFO, |
| "Validating compilation " + module.getName()); |
| if (!validate(branch, options, module, options.getGenDir(), |
| compilerWorkDir, options.getDumpSignatureFile())) { |
| 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()); |
| PropertyPermutations allPermutations = new PropertyPermutations( |
| module.getProperties()); |
| int potentialPermutations = allPermutations.size(); |
| int permutationsPerIteration = options.getMaxPermsPerPrecompile(); |
| |
| if (permutationsPerIteration <= 0) { |
| permutationsPerIteration = potentialPermutations; |
| } |
| /* |
| * The potential number of permutations to precompile >= the actual |
| * number of permutations that end up being precompiled, because some of |
| * the permutations might collapse due to identical rebind results. So |
| * we have to track these two counts and ids separately. |
| */ |
| int actualPermutations = 0; |
| for (int potentialFirstPerm = 0; potentialFirstPerm < potentialPermutations; potentialFirstPerm += permutationsPerIteration) { |
| int numPermsToPrecompile = Math.min(potentialPermutations |
| - potentialFirstPerm, permutationsPerIteration); |
| |
| // Select only the range of property permutations that we want |
| PropertyPermutations localPermutations = new PropertyPermutations( |
| allPermutations, potentialFirstPerm, numPermsToPrecompile); |
| |
| Precompilation precompilation = precompile(branch, options, module, |
| actualPermutations, localPermutations, options.getGenDir(), |
| compilerWorkDir, options.getDumpSignatureFile()); |
| if (precompilation == null) { |
| branch.log(TreeLogger.ERROR, "Precompilation failed"); |
| return false; |
| } |
| int actualNumPermsPrecompiled = precompilation.getPermutations().length; |
| String precompilationFilename = PrecompilationFile.fileNameForPermutations( |
| actualPermutations, actualNumPermsPrecompiled); |
| try { |
| precompilationJar.putNextEntry(new ZipEntry(precompilationFilename)); |
| Util.writeObjectToStream(precompilationJar, precompilation); |
| } catch (IOException e) { |
| branch.log(TreeLogger.ERROR, |
| "Failed to write a precompilation result", e); |
| return false; |
| } |
| |
| actualPermutations += actualNumPermsPrecompiled; |
| branch.log(TreeLogger.DEBUG, "Compiled " + actualNumPermsPrecompiled |
| + " permutations starting from " + potentialFirstPerm); |
| } |
| |
| try { |
| precompilationJar.close(); |
| } catch (IOException e) { |
| branch.log(TreeLogger.ERROR, "Failed to finalize " |
| + PRECOMPILE_FILENAME, e); |
| return false; |
| } |
| |
| Util.writeStringAsFile(branch, new File(compilerWorkDir, |
| PERM_COUNT_FILENAME), String.valueOf(actualPermutations)); |
| branch.log(TreeLogger.INFO, |
| "Precompilation succeeded, number of permutations: " |
| + actualPermutations); |
| } |
| } |
| return true; |
| } |
| } |