/** * Creates a dummy output directory without compiling the module. Either this method or {@link * #precompile} should be called first. */ synchronized Job.Result initWithoutPrecompile(TreeLogger logger) throws UnableToCompleteException { long startTime = System.currentTimeMillis(); CompileDir compileDir = outboxDir.makeCompileDir(logger); TreeLogger compileLogger = makeCompileLogger(compileDir, logger); ModuleDef module; try { module = loadModule(compileLogger); logger.log(TreeLogger.INFO, "Loading Java files in " + inputModuleName + "."); CompilerOptions loadOptions = new CompilerOptionsImpl(compileDir, inputModuleName, options); compilerContext = compilerContextBuilder.options(loadOptions).unitCache(unitCache).build(); // Loads and parses all the Java files in the GWT application using the JDT. // (This is warmup to make compiling faster later; we stop at this point to avoid // needing to know the binding properties.) module.getCompilationState(compileLogger, compilerContext); setUpCompileDir(compileDir, module, compileLogger); if (launcherDir != null) { launcherDir.update(module, compileDir, compileLogger); } outputModuleName.set(module.getName()); } finally { // Make the compile log available no matter what happens. lastBuild.set(compileDir); } long elapsedTime = System.currentTimeMillis() - startTime; compileLogger.log(TreeLogger.Type.INFO, "Module setup completed in " + elapsedTime + " ms"); return new Result(compileDir, module.getName(), null); }
public void testLoadFromLibraryGroup() throws UnableToCompleteException, IOException, IncompatibleLibraryVersionException { // Create the library zip file. File zipFile = File.createTempFile("FooLib", ".gwtlib"); zipFile.deleteOnExit(); // Put data in the library and save it. ZipLibraryWriter zipLibraryWriter = new ZipLibraryWriter(zipFile.getPath()); zipLibraryWriter.setLibraryName("FooLib"); MockResource userXmlResource = new MockResource("com/google/gwt/user/User.gwt.xml") { @Override public CharSequence getContent() { return "<module></module>"; } }; zipLibraryWriter.addBuildResource(userXmlResource); zipLibraryWriter.write(); // Read data back from disk. ZipLibrary zipLibrary = new ZipLibrary(zipFile.getPath()); // Prepare the LibraryGroup and ResourceLoader. compilerContext = compilerContextBuilder .libraryGroup( LibraryGroup.fromLibraries(Lists.<Library>newArrayList(zipLibrary), false)) .build(); ResourceLoader resourceLoader = ResourceLoaders.wrap(new URLClassLoader(new URL[] {zipFile.toURL()}, null)); // Will throw an exception if com.google.gwt.user.User can't be found and parsed. ModuleDefLoader.loadFromResources( TreeLogger.NULL, compilerContext, "com.google.gwt.user.User", resourceLoader, false); }
public void testWritesTargetLibraryProperties() throws UnableToCompleteException { compilerContext = compilerContextBuilder.compileMonolithic(false).build(); ModuleDef libraryOneModule = ModuleDefLoader.loadFromClassPath( TreeLogger.NULL, compilerContext, "com.google.gwt.dev.cfg.testdata.separate.libraryone.LibraryOne", false); // Library one sees all defined values for the "libraryTwoProperty" binding property and knows // which one was defined in this target library. for (BindingProperty bindingProperty : libraryOneModule.getProperties().getBindingProperties()) { if (!bindingProperty.getName().equals("libraryTwoProperty")) { continue; } assertEquals( Sets.newHashSet(bindingProperty.getDefinedValues()), Sets.newHashSet("yes", "no", "maybe")); assertEquals( Sets.newHashSet(bindingProperty.getTargetLibraryDefinedValues()), Sets.newHashSet("maybe")); } // Library one added a new defined value of "maybe" for the "libraryTwoProperty" binding // property. assertEquals( Sets.newHashSet( mockLibraryWriter.getNewBindingPropertyValuesByName().get("libraryTwoProperty")), Sets.newHashSet("maybe")); // Library one sees all defined values for the "libraryTwoConfigProperty" property and knows // which one was defined in this target library. for (ConfigurationProperty configurationProperty : libraryOneModule.getProperties().getConfigurationProperties()) { if (!configurationProperty.getName().equals("libraryTwoConfigProperty")) { continue; } assertEquals(Sets.newHashSet(configurationProperty.getValues()), Sets.newHashSet("false")); assertEquals( Sets.newHashSet(configurationProperty.getTargetLibraryValues()), Sets.newHashSet("false")); } // Library one added a new defined value of "maybe" for the "libraryTwoConfigProperty" // property. assertEquals( Sets.newHashSet( mockLibraryWriter .getNewConfigurationPropertyValuesByName() .get("libraryTwoConfigProperty")), Sets.newHashSet("false")); }
public void testSeparateLibraryName() throws UnableToCompleteException { compilerContext = compilerContextBuilder.compileMonolithic(false).build(); ModuleDefLoader.loadFromClassPath( TreeLogger.NULL, compilerContext, "com.google.gwt.dev.cfg.testdata.separate.libraryone.LibraryOne", false); assertEquals( "com.google.gwt.dev.cfg.testdata.separate.libraryone.LibraryOne", mockLibraryWriter.getLibraryName()); }
public void testSeparateRootFilesetFail() { compilerContext = compilerContextBuilder.compileMonolithic(false).build(); TreeLogger logger = TreeLogger.NULL; try { ModuleDefLoader.loadFromClassPath( logger, compilerContext, "com.google.gwt.dev.cfg.testdata.separate.filesetone.FileSetOne", false); fail("Expected a fileset loaded as the root of a module tree to fail, but it didn't."); } catch (UnableToCompleteException e) { // Expected behavior. } }
Recompiler( OutboxDir outboxDir, LauncherDir launcherDir, String inputModuleName, Options options, UnitCache unitCache, MinimalRebuildCacheManager minimalRebuildCacheManager) { this.outboxDir = outboxDir; this.launcherDir = launcherDir; this.inputModuleName = inputModuleName; this.options = options; this.unitCache = unitCache; this.minimalRebuildCacheManager = minimalRebuildCacheManager; this.serverPrefix = options.getPreferredHost() + ":" + options.getPort(); compilerContext = compilerContextBuilder.build(); }
public void testSeparateModuleReferences() throws UnableToCompleteException { compilerContext = compilerContextBuilder.compileMonolithic(false).build(); ModuleDef libraryOneModule = ModuleDefLoader.loadFromClassPath( TreeLogger.NULL, compilerContext, "com.google.gwt.dev.cfg.testdata.separate.libraryone.LibraryOne", false); // The module sees itself and it's direct fileset module as "target" modules. assertEquals( Sets.newHashSet( "com.google.gwt.dev.cfg.testdata.separate.libraryone.LibraryOne", "com.google.gwt.dev.cfg.testdata.separate.filesetone.FileSetOne"), libraryOneModule.getTargetLibraryModuleNames()); // The module sees the referenced library module as a "library" module. assertEquals( Sets.newHashSet("com.google.gwt.dev.cfg.testdata.separate.librarytwo.LibraryTwo"), libraryOneModule.getExternalLibraryModuleNames()); }
public void testSeparateLibraryModuleReferences() throws UnableToCompleteException { compilerContext = compilerContextBuilder.compileMonolithic(false).build(); ModuleDefLoader.loadFromClassPath( TreeLogger.NULL, compilerContext, "com.google.gwt.dev.cfg.testdata.separate.libraryone.LibraryOne", false); // The library writer was given the module and it's direct fileset module xml files as build // resources. assertEquals( Sets.newHashSet( "com/google/gwt/dev/cfg/testdata/separate/filesetone/FileSetOne.gwt.xml", "com/google/gwt/dev/cfg/testdata/separate/libraryone/LibraryOne.gwt.xml"), mockLibraryWriter.getBuildResourcePaths()); // The library writer was given LibraryTwo as a dependency library. assertEquals( Sets.newHashSet("com.google.gwt.dev.cfg.testdata.separate.librarytwo.LibraryTwo"), mockLibraryWriter.getDependencyLibraryNames()); }
public void testSeparateModuleResourcesLibraryOne() throws UnableToCompleteException { compilerContext = compilerContextBuilder.compileMonolithic(false).build(); ModuleDef libraryOneModule = ModuleDefLoader.loadFromClassPath( TreeLogger.NULL, compilerContext, "com.google.gwt.dev.cfg.testdata.separate.libraryone.LibraryOne", false); // Includes own source. assertNotNull( libraryOneModule.findSourceFile( "com/google/gwt/dev/cfg/testdata/separate/libraryone/client/LibraryOne.java")); // Cascades to include the subtree of fileset sources. assertNotNull( libraryOneModule.findSourceFile( "com/google/gwt/dev/cfg/testdata/separate/filesetone/client/FileSetOne.java")); // Does not include source from referenced libraries. assertNull( libraryOneModule.findSourceFile( "com/google/gwt/dev/cfg/testdata/separate/librarytwo/client/LibraryTwo.java")); }
/** * Calls the GWT compiler with the appropriate settings. Side-effect: a MinimalRebuildCache for * the current binding properties will be found or created. * * @param job used for reporting progress. (Its result will not be set.) * @return a non-error Job.Result if successful. * @throws UnableToCompleteException for compile failures. */ private Job.Result compile(Job job) throws UnableToCompleteException { assert job.wasSubmitted(); if (compilesDone == 0) { System.setProperty("java.awt.headless", "true"); if (System.getProperty("gwt.speedtracerlog") == null) { System.setProperty( "gwt.speedtracerlog", outboxDir.getSpeedTracerLogFile().getAbsolutePath()); } compilerContext = compilerContextBuilder.unitCache(unitCache).build(); } long startTime = System.currentTimeMillis(); int compileId = ++compilesDone; CompileDir compileDir = outboxDir.makeCompileDir(job.getLogger()); TreeLogger compileLogger = makeCompileLogger(compileDir, job.getLogger()); try { job.onStarted(compileId, compileDir); boolean success = doCompile(compileLogger, compileDir, job); if (!success) { compileLogger.log(TreeLogger.Type.ERROR, "Compiler returned false"); throw new UnableToCompleteException(); } } finally { // Make the error log available no matter what happens lastBuild.set(compileDir); } long elapsedTime = System.currentTimeMillis() - startTime; compileLogger.log( TreeLogger.Type.INFO, String.format("%.3fs total -- Compile completed", elapsedTime / 1000d)); return new Result(publishedCompileDir, outputModuleName.get(), null); }
@Override protected void setUp() throws Exception { super.setUp(); ModuleDefLoader.getModulesCache().clear(); compilerContext = compilerContextBuilder.libraryWriter(mockLibraryWriter).build(); }
/** Loads the module and configures it for SuperDevMode. (Does not restrict permutations.) */ private ModuleDef loadModule(TreeLogger logger) throws UnableToCompleteException { // make sure we get the latest version of any modified jar ZipFileClassPathEntry.clearCache(); ResourceOracleImpl.clearCache(); ResourceLoader resources = ResourceLoaders.forClassLoader(Thread.currentThread()); resources = ResourceLoaders.forPathAndFallback(options.getSourcePath(), resources); this.resourceLoader.set(resources); // ModuleDefLoader.loadFromResources() checks for modified .gwt.xml files. ModuleDef moduleDef = ModuleDefLoader.loadFromResources( logger, compilerContext, inputModuleName, resources, true); compilerContext = compilerContextBuilder.module(moduleDef).build(); // Undo all permutation restriction customizations from previous compiles. for (BindingProperty bindingProperty : moduleDef.getProperties().getBindingProperties()) { String[] allowedValues = bindingProperty.getAllowedValues(bindingProperty.getRootCondition()); bindingProperty.setRootGeneratedValues(allowedValues); } // A snapshot of the module's configuration before we modified it. ConfigProps config = new ConfigProps(moduleDef); // We need a cross-site linker. Automatically replace the default linker. if (IFrameLinker.class.isAssignableFrom(moduleDef.getActivePrimaryLinker())) { moduleDef.addLinker("xsiframe"); } // Check that we have a compatible linker. Class<? extends Linker> linker = moduleDef.getActivePrimaryLinker(); if (!CrossSiteIframeLinker.class.isAssignableFrom(linker)) { logger.log( TreeLogger.ERROR, "linkers other than CrossSiteIFrameLinker aren't supported. Found: " + linker.getName()); throw new UnableToCompleteException(); } // Deactivate precompress linker. if (moduleDef.deactivateLinker("precompress")) { logger.log(TreeLogger.WARN, "Deactivated PrecompressLinker"); } // Print a nice error if the superdevmode hook isn't present if (config.getStrings("devModeRedirectEnabled").isEmpty()) { throw new RuntimeException( "devModeRedirectEnabled isn't set for module: " + moduleDef.getName()); } // Disable the redirect hook here to make sure we don't have an infinite loop. // (There is another check in the JavaScript, but just in case.) overrideConfig(moduleDef, "devModeRedirectEnabled", "false"); // Turn off "installCode" if it's on because it makes debugging harder. // (If it's already off, don't change anything.) if (config.getBoolean("installCode", true)) { overrideConfig(moduleDef, "installCode", "false"); // Make sure installScriptJs is set to the default for compiling without installCode. overrideConfig( moduleDef, "installScriptJs", "com/google/gwt/core/ext/linker/impl/installScriptDirect.js"); } // override computeScriptBase.js to enable the "Compile" button overrideConfig( moduleDef, "computeScriptBaseJs", "com/google/gwt/dev/codeserver/computeScriptBase.js"); // Fix bug with SDM and Chrome 24+ where //@ sourceURL directives cause X-SourceMap header to be // ignored // Frustratingly, Chrome won't canonicalize a relative URL overrideConfig( moduleDef, "includeSourceMapUrl", "http://" + serverPrefix + SourceHandler.sourceMapLocationTemplate(moduleDef.getName())); // If present, set some config properties back to defaults. // (Needed for Google's server-side linker.) maybeOverrideConfig(moduleDef, "includeBootstrapInPrimaryFragment", "false"); maybeOverrideConfig( moduleDef, "permutationsJs", "com/google/gwt/core/ext/linker/impl/permutations.js"); maybeOverrideConfig( moduleDef, "propertiesJs", "com/google/gwt/core/ext/linker/impl/properties.js"); if (options.isIncrementalCompileEnabled()) { // CSSResourceGenerator needs to produce stable, unique naming for its input. // Currently on default settings CssResourceGenerator's obfuscation depends on // whole world knowledge and thus will produce collision in obfuscated mode, since in // incremental compiles that information is not available. // // TODO(dankurka): Once we do proper stable hashing of classes in CssResourceGenerator, we // can probably replace / remove this. maybeOverrideConfig(moduleDef, "CssResource.style", "stable"); } overrideBinding(moduleDef, "compiler.useSourceMaps", "true"); overrideBinding(moduleDef, "compiler.useSymbolMaps", "false"); overrideBinding(moduleDef, "superdevmode", "on"); return moduleDef; }
private boolean doCompile(TreeLogger compileLogger, CompileDir compileDir, Job job) throws UnableToCompleteException { job.onProgress("Loading modules"); CompilerOptions loadOptions = new CompilerOptionsImpl(compileDir, inputModuleName, options); compilerContext = compilerContextBuilder.options(loadOptions).build(); ModuleDef module = loadModule(compileLogger); if (!Compiler.maybeRestrictProperties(compileLogger, module, loadOptions.getProperties())) { return false; } // We need to generate the stub before restricting permutations String recompileJs = generateModuleRecompileJs(module, compileLogger); Map<String, String> bindingProperties = restrictPermutations(compileLogger, module, job.getBindingProperties()); // Propagates module rename. String newModuleName = module.getName(); outputModuleName.set(newModuleName); // Check if we can skip the compile altogether. InputSummary input = new InputSummary(bindingProperties, module); if (input.equals(lastBuildInput)) { compileLogger.log(Type.INFO, "skipped compile because no input files have changed"); job.setCompileStrategy(CompileStrategy.SKIPPED); return true; } // Force a recompile if we don't succeed. lastBuildInput = null; job.onProgress("Compiling"); // TODO: use speed tracer to get more compiler events? CompilerOptions runOptions = new CompilerOptionsImpl(compileDir, newModuleName, options); compilerContext = compilerContextBuilder.options(runOptions).build(); MinimalRebuildCache minimalRebuildCache = new NullRebuildCache(); if (options.isIncrementalCompileEnabled()) { // Returns a copy of the intended cache, which is safe to modify in this compile. minimalRebuildCache = minimalRebuildCacheManager.getCache(inputModuleName, bindingProperties); } job.setCompileStrategy( minimalRebuildCache.isPopulated() ? CompileStrategy.INCREMENTAL : CompileStrategy.FULL); boolean success = new Compiler(runOptions, minimalRebuildCache).run(compileLogger, module); if (success) { publishedCompileDir = compileDir; lastBuildInput = input; if (options.isIncrementalCompileEnabled()) { minimalRebuildCacheManager.putCache( inputModuleName, bindingProperties, minimalRebuildCache); } String moduleName = outputModuleName.get(); writeRecompileNoCacheJs( new File(publishedCompileDir.getWarDir(), moduleName), moduleName, recompileJs, compileLogger); if (launcherDir != null) { launcherDir.update(module, compileDir, compileLogger); } } return success; }